summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml7
-rw-r--r--.github/workflows/linux_builds.yml3
-rw-r--r--.github/workflows/windows_builds.yml4
-rw-r--r--.gitignore1
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--COPYRIGHT.txt6
-rw-r--r--core/config/engine.cpp9
-rw-r--r--core/config/engine.h4
-rw-r--r--core/config/project_settings.cpp14
-rw-r--r--core/core_bind.cpp11
-rw-r--r--core/core_bind.h3
-rw-r--r--core/core_constants.cpp2
-rw-r--r--core/debugger/remote_debugger.cpp87
-rw-r--r--core/debugger/remote_debugger.h2
-rw-r--r--core/extension/gdnative_interface.h72
-rw-r--r--core/extension/native_extension.cpp4
-rw-r--r--core/input/input_event.cpp2
-rw-r--r--core/io/pck_packer.cpp2
-rw-r--r--core/io/xml_parser.cpp69
-rw-r--r--core/io/xml_parser.h8
-rw-r--r--core/math/basis.cpp8
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/projection.cpp12
-rw-r--r--core/object/object.h2
-rw-r--r--core/object/script_language_extension.h20
-rw-r--r--core/object/undo_redo.cpp4
-rw-r--r--core/object/undo_redo.h1
-rw-r--r--core/string/optimized_translation.cpp33
-rw-r--r--core/string/optimized_translation.h1
-rw-r--r--core/string/translation.cpp13
-rw-r--r--core/string/translation.h1
-rw-r--r--core/string/translation_po.cpp17
-rw-r--r--core/string/translation_po.h1
-rw-r--r--core/string/ustring.cpp8
-rw-r--r--core/string/ustring.h2
-rw-r--r--core/variant/variant.cpp10
-rw-r--r--core/variant/variant_call.cpp4
-rw-r--r--core/variant/variant_construct.cpp2
-rw-r--r--core/variant/variant_construct.h58
-rw-r--r--doc/classes/@GlobalScope.xml68
-rw-r--r--doc/classes/Animation.xml7
-rw-r--r--doc/classes/ArrayMesh.xml12
-rw-r--r--doc/classes/BaseMaterial3D.xml13
-rw-r--r--doc/classes/CharacterBody2D.xml2
-rw-r--r--doc/classes/CompressedCubemap.xml9
-rw-r--r--doc/classes/CompressedCubemapArray.xml9
-rw-r--r--doc/classes/CompressedTexture2D.xml14
-rw-r--r--doc/classes/CompressedTexture2DArray.xml9
-rw-r--r--doc/classes/CompressedTexture3D.xml6
-rw-r--r--doc/classes/CompressedTextureLayered.xml10
-rw-r--r--doc/classes/Control.xml6
-rw-r--r--doc/classes/Cubemap.xml5
-rw-r--r--doc/classes/CubemapArray.xml5
-rw-r--r--doc/classes/Curve3D.xml9
-rw-r--r--doc/classes/DirectionalLight2D.xml3
-rw-r--r--doc/classes/DisplayServer.xml5
-rw-r--r--doc/classes/EditorDebuggerPlugin.xml116
-rw-r--r--doc/classes/EditorDebuggerSession.xml86
-rw-r--r--doc/classes/EditorInterface.xml12
-rw-r--r--doc/classes/EditorNode3DGizmoPlugin.xml2
-rw-r--r--doc/classes/EditorPlugin.xml4
-rw-r--r--doc/classes/EditorProperty.xml2
-rw-r--r--doc/classes/EditorUndoRedoManager.xml2
-rw-r--r--doc/classes/Engine.xml5
-rw-r--r--doc/classes/FileSystemDock.xml2
-rw-r--r--doc/classes/GeometryInstance3D.xml5
-rw-r--r--doc/classes/Image.xml2
-rw-r--r--doc/classes/ImageTexture3D.xml5
-rw-r--r--doc/classes/ImageTextureLayered.xml6
-rw-r--r--doc/classes/MissingNode.xml2
-rw-r--r--doc/classes/MissingResource.xml2
-rw-r--r--doc/classes/Node.xml4
-rw-r--r--doc/classes/OS.xml2
-rw-r--r--doc/classes/OfflineMultiplayerPeer.xml12
-rw-r--r--doc/classes/PathFollow3D.xml13
-rw-r--r--doc/classes/PhysicsBody2D.xml10
-rw-r--r--doc/classes/PhysicsBody3D.xml10
-rw-r--r--doc/classes/PlaceholderCubemap.xml4
-rw-r--r--doc/classes/PlaceholderCubemapArray.xml4
-rw-r--r--doc/classes/PlaceholderMaterial.xml4
-rw-r--r--doc/classes/PlaceholderMesh.xml5
-rw-r--r--doc/classes/PlaceholderTexture2D.xml5
-rw-r--r--doc/classes/PlaceholderTexture2DArray.xml4
-rw-r--r--doc/classes/PlaceholderTexture3D.xml5
-rw-r--r--doc/classes/PlaceholderTextureLayered.xml6
-rw-r--r--doc/classes/PortableCompressedTexture2D.xml2
-rw-r--r--doc/classes/PrimitiveMesh.xml6
-rw-r--r--doc/classes/ProjectSettings.xml35
-rw-r--r--doc/classes/RenderingServer.xml4
-rw-r--r--doc/classes/String.xml4
-rw-r--r--doc/classes/Texture.xml2
-rw-r--r--doc/classes/Texture2D.xml16
-rw-r--r--doc/classes/Texture2DArray.xml3
-rw-r--r--doc/classes/Texture3D.xml16
-rw-r--r--doc/classes/TextureButton.xml10
-rw-r--r--doc/classes/TextureLayered.xml22
-rw-r--r--doc/classes/Translation.xml6
-rw-r--r--doc/classes/Tree.xml8
-rw-r--r--doc/classes/XRInterfaceExtension.xml7
-rw-r--r--doc/classes/float.xml7
-rw-r--r--doc/classes/int.xml7
-rwxr-xr-xdoc/tools/make_rst.py187
-rw-r--r--drivers/gl_context/SCsub2
-rw-r--r--drivers/gles3/effects/copy_effects.cpp18
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp137
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h10
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp209
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h22
-rw-r--r--drivers/gles3/shader_gles3.cpp22
-rw-r--r--drivers/gles3/shader_gles3.h18
-rw-r--r--drivers/gles3/shaders/SCsub2
-rw-r--r--drivers/gles3/shaders/canvas.glsl42
-rw-r--r--drivers/gles3/shaders/cubemap_filter.glsl4
-rw-r--r--drivers/gles3/shaders/particles.glsl501
-rw-r--r--drivers/gles3/shaders/particles_copy.glsl122
-rw-r--r--drivers/gles3/shaders/scene.glsl16
-rw-r--r--drivers/gles3/storage/material_storage.cpp282
-rw-r--r--drivers/gles3/storage/material_storage.h64
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp5
-rw-r--r--drivers/gles3/storage/mesh_storage.h3
-rw-r--r--drivers/gles3/storage/particles_storage.cpp1211
-rw-r--r--drivers/gles3/storage/particles_storage.h315
-rw-r--r--drivers/gles3/storage/texture_storage.cpp48
-rw-r--r--drivers/gles3/storage/texture_storage.h2
-rw-r--r--drivers/gles3/storage/utilities.cpp61
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp10
-rw-r--r--drivers/vulkan/vulkan_context.cpp7
-rw-r--r--drivers/vulkan/vulkan_context.h2
-rw-r--r--editor/action_map_editor.cpp2
-rw-r--r--editor/action_map_editor.h8
-rw-r--r--editor/animation_bezier_editor.cpp18
-rw-r--r--editor/animation_track_editor.cpp17
-rw-r--r--editor/animation_track_editor.h3
-rw-r--r--editor/audio_stream_preview.cpp8
-rw-r--r--editor/code_editor.cpp20
-rw-r--r--editor/create_dialog.cpp7
-rw-r--r--editor/create_dialog.h2
-rw-r--r--editor/debugger/editor_debugger_inspector.cpp2
-rw-r--r--editor/debugger/editor_debugger_node.cpp50
-rw-r--r--editor/debugger/editor_debugger_node.h10
-rw-r--r--editor/debugger/editor_performance_profiler.cpp1
-rw-r--r--editor/debugger/script_editor_debugger.cpp85
-rw-r--r--editor/debugger/script_editor_debugger.h18
-rw-r--r--editor/editor_audio_buses.h1
-rw-r--r--editor/editor_build_profile.h1
-rw-r--r--editor/editor_data.cpp2
-rw-r--r--editor/editor_data.h2
-rw-r--r--editor/editor_feature_profile.h2
-rw-r--r--editor/editor_fonts.cpp2
-rw-r--r--editor/editor_help.cpp155
-rw-r--r--editor/editor_help.h2
-rw-r--r--editor/editor_node.cpp192
-rw-r--r--editor/editor_node.h7
-rw-r--r--editor/editor_plugin.cpp24
-rw-r--r--editor/editor_plugin.h41
-rw-r--r--editor/editor_properties.cpp22
-rw-r--r--editor/editor_properties.h2
-rw-r--r--editor/editor_quick_open.cpp8
-rw-r--r--editor/editor_quick_open.h6
-rw-r--r--editor/editor_resource_picker.cpp4
-rw-r--r--editor/editor_run.cpp1
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/editor_settings_dialog.cpp1
-rw-r--r--editor/editor_spin_slider.cpp11
-rw-r--r--editor/editor_spin_slider.h2
-rw-r--r--editor/editor_themes.cpp10
-rw-r--r--editor/editor_undo_redo_manager.cpp18
-rw-r--r--editor/event_listener_line_edit.cpp68
-rw-r--r--editor/event_listener_line_edit.h3
-rw-r--r--editor/filesystem_dock.cpp35
-rw-r--r--editor/filesystem_dock.h10
-rw-r--r--editor/history_dock.cpp2
-rw-r--r--editor/import/audio_stream_import_settings.cpp5
-rw-r--r--editor/import/audio_stream_import_settings.h3
-rw-r--r--editor/import/dynamic_font_import_settings.cpp177
-rw-r--r--editor/import/dynamic_font_import_settings.h16
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.cpp208
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.h2
-rw-r--r--editor/import/resource_importer_imagefont.cpp49
-rw-r--r--editor/import/resource_importer_scene.cpp2
-rw-r--r--editor/import/resource_importer_wav.cpp10
-rw-r--r--editor/input_event_configuration_dialog.cpp85
-rw-r--r--editor/input_event_configuration_dialog.h2
-rw-r--r--editor/inspector_dock.cpp6
-rw-r--r--editor/plugin_config_dialog.cpp1
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h1
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp14
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h3
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp17
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.h4
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp32
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.h7
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp24
-rw-r--r--editor/plugins/animation_state_machine_editor.h5
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp12
-rw-r--r--editor/plugins/animation_tree_editor_plugin.h5
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp6
-rw-r--r--editor/plugins/asset_library_editor_plugin.h3
-rw-r--r--editor/plugins/bit_map_editor_plugin.h3
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp24
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h9
-rw-r--r--editor/plugins/control_editor_plugin.cpp3
-rw-r--r--editor/plugins/control_editor_plugin.h2
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.h5
-rw-r--r--editor/plugins/curve_editor_plugin.h1
-rw-r--r--editor/plugins/editor_debugger_plugin.cpp159
-rw-r--r--editor/plugins/editor_debugger_plugin.h51
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.h4
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.h4
-rw-r--r--editor/plugins/gpu_particles_collision_sdf_editor_plugin.h1
-rw-r--r--editor/plugins/gradient_editor.cpp1
-rw-r--r--editor/plugins/gradient_editor_plugin.h1
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.h1
-rw-r--r--editor/plugins/material_editor_plugin.cpp18
-rw-r--r--editor/plugins/material_editor_plugin.h3
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp8
-rw-r--r--editor/plugins/mesh_editor_plugin.h1
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h4
-rw-r--r--editor/plugins/multimesh_editor_plugin.h4
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp22
-rw-r--r--editor/plugins/node_3d_editor_plugin.h8
-rw-r--r--editor/plugins/path_2d_editor_plugin.h2
-rw-r--r--editor/plugins/path_3d_editor_plugin.h2
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h6
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.h2
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.h1
-rw-r--r--editor/plugins/root_motion_editor_plugin.cpp114
-rw-r--r--editor/plugins/root_motion_editor_plugin.h5
-rw-r--r--editor/plugins/script_editor_plugin.h1
-rw-r--r--editor/plugins/script_text_editor.cpp2
-rw-r--r--editor/plugins/shader_editor_plugin.h1
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp1
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.h3
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp16
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.h4
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp6
-rw-r--r--editor/plugins/texture_3d_editor_plugin.h1
-rw-r--r--editor/plugins/texture_editor_plugin.h4
-rw-r--r--editor/plugins/texture_layered_editor_plugin.h1
-rw-r--r--editor/plugins/texture_region_editor_plugin.h2
-rw-r--r--editor/plugins/theme_editor_plugin.h2
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp8
-rw-r--r--editor/plugins/tiles/tile_data_editors.h2
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp1
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp23
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp3
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp2
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp30
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h13
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.h1
-rw-r--r--editor/project_converter_3_to_4.cpp2
-rw-r--r--editor/project_manager.cpp2
-rw-r--r--editor/register_editor_types.cpp221
-rw-r--r--editor/register_editor_types.h37
-rw-r--r--editor/scene_create_dialog.cpp2
-rw-r--r--editor/scene_tree_dock.cpp38
-rw-r--r--editor/scene_tree_dock.h2
-rw-r--r--editor/script_create_dialog.cpp2
-rw-r--r--editor/shader_globals_editor.cpp2
-rw-r--r--gles3_builders.py49
-rw-r--r--main/main.cpp24
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj2
-rwxr-xr-xmisc/scripts/file_format.sh4
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp2
-rw-r--r--modules/gdscript/gdscript.cpp425
-rw-r--r--modules/gdscript/gdscript.h23
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp134
-rw-r--r--modules/gdscript/gdscript_analyzer.h2
-rw-r--r--modules/gdscript/gdscript_cache.cpp185
-rw-r--r--modules/gdscript/gdscript_cache.h30
-rw-r--r--modules/gdscript/gdscript_compiler.cpp358
-rw-r--r--modules/gdscript/gdscript_compiler.h8
-rw-r--r--modules/gdscript/gdscript_editor.cpp77
-rw-r--r--modules/gdscript/gdscript_function.cpp7
-rw-r--r--modules/gdscript/gdscript_function.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp19
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd (renamed from modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd)3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_base.gd18
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_base.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out (renamed from modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out)1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd2
-rw-r--r--modules/gltf/doc_classes/GLTFDocument.xml22
-rw-r--r--modules/gltf/doc_classes/GLTFDocumentExtension.xml4
-rw-r--r--modules/gltf/editor/editor_scene_exporter_gltf_plugin.h2
-rw-r--r--modules/gltf/editor/editor_scene_importer_gltf.h3
-rw-r--r--modules/gltf/extensions/gltf_document_extension.cpp (renamed from modules/gltf/gltf_document_extension.cpp)6
-rw-r--r--modules/gltf/extensions/gltf_document_extension.h (renamed from modules/gltf/gltf_document_extension.h)7
-rw-r--r--modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp (renamed from modules/gltf/gltf_document_extension_convert_importer_mesh.cpp)2
-rw-r--r--modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h (renamed from modules/gltf/gltf_document_extension_convert_importer_mesh.h)0
-rw-r--r--modules/gltf/gltf_document.cpp75
-rw-r--r--modules/gltf/gltf_document.h10
-rw-r--r--modules/gltf/register_types.cpp14
-rw-r--r--modules/gltf/structures/gltf_buffer_view.cpp2
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.h3
-rw-r--r--modules/lightmapper_rd/register_types.cpp1
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.cpp7
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs48
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs8
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs2
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs62
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs77
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs58
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs44
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs46
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs46
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs44
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs60
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs32
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs94
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs50
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs90
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs60
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs28
-rw-r--r--modules/multiplayer/editor/editor_network_profiler.cpp (renamed from editor/debugger/editor_network_profiler.cpp)200
-rw-r--r--modules/multiplayer/editor/editor_network_profiler.h (renamed from editor/debugger/editor_network_profiler.h)41
-rw-r--r--modules/multiplayer/editor/multiplayer_editor_plugin.cpp175
-rw-r--r--modules/multiplayer/editor/multiplayer_editor_plugin.h85
-rw-r--r--modules/multiplayer/editor/replication_editor.cpp (renamed from modules/multiplayer/editor/replication_editor_plugin.cpp)71
-rw-r--r--modules/multiplayer/editor/replication_editor.h (renamed from modules/multiplayer/editor/replication_editor_plugin.h)43
-rw-r--r--modules/multiplayer/multiplayer_debugger.cpp333
-rw-r--r--modules/multiplayer/multiplayer_debugger.h134
-rw-r--r--modules/multiplayer/register_types.cpp10
-rw-r--r--modules/multiplayer/scene_cache_interface.cpp8
-rw-r--r--modules/multiplayer/scene_multiplayer.cpp46
-rw-r--r--modules/multiplayer/scene_multiplayer.h39
-rw-r--r--modules/multiplayer/scene_replication_interface.cpp67
-rw-r--r--modules/multiplayer/scene_replication_interface.h6
-rw-r--r--modules/multiplayer/scene_rpc_interface.cpp77
-rw-r--r--modules/multiplayer/scene_rpc_interface.h5
-rw-r--r--modules/navigation/editor/navigation_mesh_editor_plugin.h2
-rw-r--r--modules/navigation/nav_link.h4
-rw-r--r--modules/noise/editor/noise_editor_plugin.cpp2
-rw-r--r--modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp2
-rw-r--r--modules/openxr/openxr_interface.cpp2
-rw-r--r--modules/text_server_adv/SCsub3
-rw-r--r--modules/text_server_adv/gdextension_build/SConstruct74
-rw-r--r--modules/text_server_adv/text_server_adv.cpp14
-rw-r--r--modules/text_server_adv/text_server_adv.h3
-rw-r--r--modules/text_server_adv/thorvg_bounds_iterator.cpp70
-rw-r--r--modules/text_server_adv/thorvg_bounds_iterator.h58
-rw-r--r--modules/text_server_adv/thorvg_svg_in_ot.cpp320
-rw-r--r--modules/text_server_adv/thorvg_svg_in_ot.h86
-rw-r--r--modules/text_server_fb/SCsub3
-rw-r--r--modules/text_server_fb/gdextension_build/SConstruct74
-rw-r--r--modules/text_server_fb/text_server_fb.cpp14
-rw-r--r--modules/text_server_fb/text_server_fb.h3
-rw-r--r--modules/text_server_fb/thorvg_bounds_iterator.cpp70
-rw-r--r--modules/text_server_fb/thorvg_bounds_iterator.h58
-rw-r--r--modules/text_server_fb/thorvg_svg_in_ot.cpp320
-rw-r--r--modules/text_server_fb/thorvg_svg_in_ot.h86
-rw-r--r--modules/theora/SCsub7
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--modules/webp/webp_common.cpp50
-rw-r--r--modules/webp/webp_common.h2
-rw-r--r--modules/webxr/native/library_godot_webxr.js4
-rw-r--r--modules/zip/zip_packer.cpp12
-rw-r--r--platform/android/export/export_plugin.cpp18
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt19
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java2
-rw-r--r--platform/android/java_godot_lib_jni.cpp57
-rw-r--r--platform/android/plugin/godot_plugin_jni.cpp2
-rw-r--r--platform/ios/export/export_plugin.cpp138
-rw-r--r--platform/linuxbsd/detect.py1
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp28
-rw-r--r--platform/linuxbsd/os_linuxbsd.h2
-rw-r--r--platform/linuxbsd/platform_config.h2
-rw-r--r--platform/linuxbsd/x11/SCsub2
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp23
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp8
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp32
-rw-r--r--platform/macos/detect.py20
-rw-r--r--platform/macos/display_server_macos.h1
-rw-r--r--platform/macos/display_server_macos.mm28
-rw-r--r--platform/macos/export/export_plugin.cpp17
-rw-r--r--platform/macos/export/export_plugin.h2
-rw-r--r--platform/macos/godot_application_delegate.mm4
-rw-r--r--platform/macos/godot_window_delegate.mm5
-rw-r--r--platform/macos/platform_config.h2
-rw-r--r--platform/windows/console_wrapper_windows.cpp2
-rw-r--r--platform/windows/display_server_windows.cpp26
-rw-r--r--platform/windows/export/export_plugin.cpp142
-rw-r--r--platform/windows/export/export_plugin.h3
-rw-r--r--platform/windows/gl_manager_windows.cpp59
-rw-r--r--platform/windows/gl_manager_windows.h10
-rw-r--r--platform/windows/godot_res_wrap.rc2
-rw-r--r--platform/windows/os_windows.cpp14
-rw-r--r--platform/windows/platform_config.h2
-rw-r--r--scene/2d/audio_stream_player_2d.h2
-rw-r--r--scene/2d/gpu_particles_2d.cpp4
-rw-r--r--scene/2d/gpu_particles_2d.h2
-rw-r--r--scene/2d/joint_2d.cpp14
-rw-r--r--scene/2d/navigation_link_2d.h6
-rw-r--r--scene/2d/physics_body_2d.cpp16
-rw-r--r--scene/2d/physics_body_2d.h4
-rw-r--r--scene/2d/polygon_2d.cpp2
-rw-r--r--scene/2d/skeleton_2d.cpp2
-rw-r--r--scene/2d/tile_map.h2
-rw-r--r--scene/3d/audio_stream_player_3d.h2
-rw-r--r--scene/3d/bone_attachment_3d.cpp4
-rw-r--r--scene/3d/bone_attachment_3d.h2
-rw-r--r--scene/3d/cpu_particles_3d.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp4
-rw-r--r--scene/3d/gpu_particles_3d.h2
-rw-r--r--scene/3d/navigation_link_3d.h6
-rw-r--r--scene/3d/path_3d.cpp177
-rw-r--r--scene/3d/path_3d.h7
-rw-r--r--scene/3d/physics_body_3d.cpp16
-rw-r--r--scene/3d/physics_body_3d.h4
-rw-r--r--scene/3d/skeleton_3d.cpp2
-rw-r--r--scene/3d/soft_body_3d.cpp4
-rw-r--r--scene/animation/animation_player.cpp4
-rw-r--r--scene/debugger/scene_debugger.cpp79
-rw-r--r--scene/debugger/scene_debugger.h19
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/code_edit.cpp5
-rw-r--r--scene/gui/color_picker.cpp2
-rw-r--r--scene/gui/control.cpp20
-rw-r--r--scene/gui/control.h4
-rw-r--r--scene/gui/file_dialog.cpp7
-rw-r--r--scene/gui/line_edit.cpp29
-rw-r--r--scene/gui/option_button.cpp6
-rw-r--r--scene/gui/popup_menu.cpp2
-rw-r--r--scene/gui/progress_bar.cpp7
-rw-r--r--scene/gui/rich_text_label.cpp15
-rw-r--r--scene/gui/scroll_bar.h2
-rw-r--r--scene/gui/spin_box.cpp5
-rw-r--r--scene/gui/split_container.cpp3
-rw-r--r--scene/gui/tab_bar.cpp3
-rw-r--r--scene/gui/texture_button.cpp52
-rw-r--r--scene/gui/texture_button.h20
-rw-r--r--scene/gui/tree.cpp49
-rw-r--r--scene/gui/tree.h1
-rw-r--r--scene/main/http_request.cpp49
-rw-r--r--scene/main/multiplayer_api.cpp2
-rw-r--r--scene/main/node.cpp22
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/main/scene_tree.cpp21
-rw-r--r--scene/main/scene_tree.h2
-rw-r--r--scene/main/viewport.cpp84
-rw-r--r--scene/main/viewport.h1
-rw-r--r--scene/main/window.cpp2
-rw-r--r--scene/property_utils.h2
-rw-r--r--scene/register_scene_types.cpp1
-rw-r--r--scene/resources/animation.cpp18
-rw-r--r--scene/resources/bit_map.cpp162
-rw-r--r--scene/resources/bit_map.h2
-rw-r--r--scene/resources/bone_map.cpp2
-rw-r--r--scene/resources/curve.cpp395
-rw-r--r--scene/resources/curve.h17
-rw-r--r--scene/resources/font.cpp10
-rw-r--r--scene/resources/importer_mesh.cpp2
-rw-r--r--scene/resources/packed_scene.cpp18
-rw-r--r--scene/resources/packed_scene.h2
-rw-r--r--scene/resources/primitive_meshes.cpp583
-rw-r--r--scene/resources/primitive_meshes.h35
-rw-r--r--scene/resources/resource_format_text.cpp16
-rw-r--r--scene/resources/shape_2d.cpp4
-rw-r--r--scene/resources/shape_3d.cpp4
-rw-r--r--scene/resources/skeleton_modification_2d_fabrik.h4
-rw-r--r--scene/resources/skeleton_modification_3d_fabrik.h6
-rw-r--r--scene/resources/syntax_highlighter.cpp2
-rw-r--r--scene/resources/texture.cpp1
-rw-r--r--scene/resources/tile_set.cpp2
-rw-r--r--scene/resources/tile_set.h2
-rw-r--r--scene/resources/visual_shader_nodes.cpp4
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--scene/scene_string_names.h2
-rw-r--r--servers/navigation/navigation_utilities.h4
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp1
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.cpp7
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h2
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h3
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h1
-rw-r--r--servers/rendering/renderer_canvas_render.cpp4
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp98
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h27
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp1
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h4
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp17
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp6
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp12
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp13
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h6
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp11
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp13
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp20
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h9
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl42
-rw-r--r--servers/rendering/renderer_rd/shaders/cluster_render.glsl12
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl49
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy.glsl12
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl59
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl13
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp19
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h1
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp1
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h12
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp35
-rw-r--r--servers/rendering/renderer_scene_cull.cpp2
-rw-r--r--servers/rendering/renderer_viewport.cpp3
-rw-r--r--servers/rendering/rendering_device.h2
-rw-r--r--servers/rendering/shader_compiler.cpp54
-rw-r--r--servers/rendering/shader_language.cpp115
-rw-r--r--servers/rendering/shader_language.h1
-rw-r--r--servers/rendering/storage/environment_storage.h4
-rw-r--r--servers/rendering/storage/particles_storage.h3
-rw-r--r--servers/rendering_server.cpp14
-rw-r--r--servers/xr/xr_interface.cpp7
-rw-r--r--servers/xr/xr_interface.h2
-rw-r--r--servers/xr/xr_interface_extension.cpp6
-rw-r--r--servers/xr/xr_interface_extension.h3
-rw-r--r--tests/core/math/test_math_funcs.h659
-rw-r--r--tests/core/string/test_string.h19
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl5
-rw-r--r--tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json1
-rw-r--r--tests/scene/test_bit_map.h31
-rw-r--r--thirdparty/README.md24
-rw-r--r--thirdparty/glad/LICENSE83
-rw-r--r--thirdparty/glad/gl.c1995
-rw-r--r--thirdparty/glad/glad.c1951
-rw-r--r--thirdparty/glad/glad/gl.h3884
-rw-r--r--thirdparty/glad/glad/glad.h3801
-rw-r--r--thirdparty/glad/glad/glx.h605
-rw-r--r--thirdparty/glad/glx.c395
-rw-r--r--thirdparty/libtheora/LICENSE8
-rw-r--r--thirdparty/libtheora/analyze.c2283
-rw-r--r--thirdparty/libtheora/apiwrapper.c2
-rw-r--r--thirdparty/libtheora/apiwrapper.h2
-rw-r--r--thirdparty/libtheora/bitpack.c23
-rw-r--r--thirdparty/libtheora/bitpack.h27
-rw-r--r--thirdparty/libtheora/collect.c974
-rw-r--r--thirdparty/libtheora/collect.h109
-rw-r--r--thirdparty/libtheora/dct.h2
-rw-r--r--thirdparty/libtheora/decinfo.c40
-rw-r--r--thirdparty/libtheora/decint.h152
-rw-r--r--thirdparty/libtheora/decode.c1993
-rw-r--r--thirdparty/libtheora/dequant.c2
-rw-r--r--thirdparty/libtheora/dequant.h2
-rw-r--r--thirdparty/libtheora/encfrag.c159
-rw-r--r--thirdparty/libtheora/encinfo.c2
-rw-r--r--thirdparty/libtheora/encint.h502
-rw-r--r--thirdparty/libtheora/encode.c428
-rw-r--r--thirdparty/libtheora/encoder_disabled.c5
-rw-r--r--thirdparty/libtheora/enquant.c198
-rw-r--r--thirdparty/libtheora/enquant.h7
-rw-r--r--thirdparty/libtheora/fdct.c9
-rw-r--r--thirdparty/libtheora/fragment.c43
-rw-r--r--thirdparty/libtheora/huffdec.c694
-rw-r--r--thirdparty/libtheora/huffdec.h72
-rw-r--r--thirdparty/libtheora/huffenc.c112
-rw-r--r--thirdparty/libtheora/huffenc.h3
-rw-r--r--thirdparty/libtheora/huffman.h4
-rw-r--r--thirdparty/libtheora/idct.c59
-rw-r--r--thirdparty/libtheora/info.c10
-rw-r--r--thirdparty/libtheora/internal.c92
-rw-r--r--thirdparty/libtheora/internal.h445
-rw-r--r--thirdparty/libtheora/mathops.c68
-rw-r--r--thirdparty/libtheora/mathops.h44
-rw-r--r--thirdparty/libtheora/mcenc.c215
-rw-r--r--thirdparty/libtheora/modedec.h4389
-rw-r--r--thirdparty/libtheora/ocintrin.h2
-rw-r--r--thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch38
-rw-r--r--thirdparty/libtheora/quant.c10
-rw-r--r--thirdparty/libtheora/quant.h2
-rw-r--r--thirdparty/libtheora/rate.c26
-rw-r--r--thirdparty/libtheora/state.c298
-rw-r--r--thirdparty/libtheora/state.h552
-rw-r--r--thirdparty/libtheora/theora/codec.h77
-rw-r--r--thirdparty/libtheora/theora/theora.h114
-rw-r--r--thirdparty/libtheora/theora/theoradec.h22
-rw-r--r--thirdparty/libtheora/theora/theoraenc.h112
-rw-r--r--thirdparty/libtheora/tokenize.c1006
-rw-r--r--thirdparty/libtheora/x86/mmxencfrag.c284
-rw-r--r--thirdparty/libtheora/x86/mmxfdct.c127
-rw-r--r--thirdparty/libtheora/x86/mmxfrag.c81
-rw-r--r--thirdparty/libtheora/x86/mmxfrag.h64
-rw-r--r--thirdparty/libtheora/x86/mmxidct.c292
-rw-r--r--thirdparty/libtheora/x86/mmxloop.h271
-rw-r--r--thirdparty/libtheora/x86/mmxstate.c162
-rw-r--r--thirdparty/libtheora/x86/sse2encfrag.c501
-rw-r--r--thirdparty/libtheora/x86/sse2fdct.c111
-rw-r--r--thirdparty/libtheora/x86/sse2idct.c456
-rw-r--r--thirdparty/libtheora/x86/sse2trans.h242
-rw-r--r--thirdparty/libtheora/x86/x86cpu.c182
-rw-r--r--thirdparty/libtheora/x86/x86cpu.h (renamed from thirdparty/libtheora/cpu.h)10
-rw-r--r--thirdparty/libtheora/x86/x86enc.c34
-rw-r--r--thirdparty/libtheora/x86/x86enc.h93
-rw-r--r--thirdparty/libtheora/x86/x86enquant.c149
-rw-r--r--thirdparty/libtheora/x86/x86int.h96
-rw-r--r--thirdparty/libtheora/x86/x86state.c47
-rw-r--r--thirdparty/libtheora/x86/x86zigzag.h244
-rw-r--r--thirdparty/libtheora/x86_vc/mmxencfrag.c122
-rw-r--r--thirdparty/libtheora/x86_vc/mmxfdct.c128
-rw-r--r--thirdparty/libtheora/x86_vc/mmxfrag.c83
-rw-r--r--thirdparty/libtheora/x86_vc/mmxfrag.h61
-rw-r--r--thirdparty/libtheora/x86_vc/mmxidct.c230
-rw-r--r--thirdparty/libtheora/x86_vc/mmxstate.c75
-rw-r--r--thirdparty/libtheora/x86_vc/x86cpu.c (renamed from thirdparty/libtheora/cpu.c)60
-rw-r--r--thirdparty/libtheora/x86_vc/x86cpu.h36
-rw-r--r--thirdparty/libtheora/x86_vc/x86enc.c14
-rw-r--r--thirdparty/libtheora/x86_vc/x86enc.h22
-rw-r--r--thirdparty/libtheora/x86_vc/x86int.h23
-rw-r--r--thirdparty/libtheora/x86_vc/x86state.c11
-rw-r--r--thirdparty/libtheora/x86_vc/x86zigzag.h244
638 files changed, 29952 insertions, 19296 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 2c2a963a26..0b4abac1af 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -52,5 +52,8 @@ body:
attributes:
label: Minimal reproduction project
description: |
- A small Godot project which reproduces the issue. Highly recommended to speed up troubleshooting.
- Drag and drop a ZIP archive to upload it.
+ A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
+ Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field.
+ Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.**
+ validations:
+ required: true
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 3a92b8ffb4..95d216deb3 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -102,6 +102,9 @@ jobs:
with:
dotnet-version: '6.0.x'
+ - name: Setup GCC problem matcher
+ uses: ammaraskar/gcc-problem-matcher@master
+
- name: Compilation
uses: ./.github/actions/godot-build
with:
diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml
index 31661e3f90..7f04c3475e 100644
--- a/.github/workflows/windows_builds.yml
+++ b/.github/workflows/windows_builds.yml
@@ -45,10 +45,12 @@ jobs:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
-
- name: Setup python and scons
uses: ./.github/actions/godot-deps
+ - name: Setup MSVC problem matcher
+ uses: ammaraskar/msvc-problem-matcher@master
+
- name: Compilation
uses: ./.github/actions/godot-build
with:
diff --git a/.gitignore b/.gitignore
index ca7d850f9e..15c1e50277 100644
--- a/.gitignore
+++ b/.gitignore
@@ -318,6 +318,7 @@ _ReSharper*/
# Others
ClientBin/
+enc_temp_folder/
~$*
*.dbmdl
*.dbproj.schemaview
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a1e8d3a59d..63e6a89e64 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -63,6 +63,8 @@ understand that:
- What happens to you may not happen to other users.
- We can't take the time to look at your project, understand how it is set up
and then figure out why it's failing.
+- On the contributors' end, recreating a test project from scratch takes valuable
+ time that can be saved by uploading a *minimal* project.
To speed up our work, **please upload a minimal project** that isolates
and reproduces the issue. This is always the **best way for us to fix it**.
@@ -74,7 +76,7 @@ if your ZIP file isn't accepted by GitHub because it's too large.
We recommend always attaching a minimal reproduction project, even if the issue
may seem simple to reproduce manually.
-**Note for C# users:** If your issue is not .NET-specific, please upload a
+**Note for C# users:** If your issue is *not* .NET-specific, please upload a
minimal reproduction project written in GDScript.
This will make it easier for contributors to reproduce the issue
locally as not everyone has a .NET setup available.
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 3f4981b7fb..2dc58158ef 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -202,6 +202,12 @@ Comment: The FreeType Project
Copyright: 1996-2022, David Turner, Robert Wilhelm, and Werner Lemberg.
License: FTL
+Files: ./thirdparty/glad/
+Comment: glad
+Copyright: 2013-2022, David Herberth
+ 2013-2020, The Khronos Group Inc.
+License: CC0-1.0 and Apache-2.0
+
Files: ./thirdparty/glslang/
Comment: glslang
Copyright: 2015-2020, Google, Inc.
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 21e910be5b..7aa5f4d06d 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -48,6 +48,15 @@ int Engine::get_physics_ticks_per_second() const {
return ips;
}
+void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
+ ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
+ max_physics_steps_per_frame = p_max_physics_steps;
+}
+
+int Engine::get_max_physics_steps_per_frame() const {
+ return max_physics_steps_per_frame;
+}
+
void Engine::set_physics_jitter_fix(double p_threshold) {
if (p_threshold < 0) {
p_threshold = 0;
diff --git a/core/config/engine.h b/core/config/engine.h
index 21517e46b7..1b179c5727 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -63,6 +63,7 @@ private:
int _max_fps = 0;
double _time_scale = 1.0;
uint64_t _physics_frames = 0;
+ int max_physics_steps_per_frame = 8;
double _physics_interpolation_fraction = 0.0f;
bool abort_on_gpu_errors = false;
bool use_validation_layers = false;
@@ -93,6 +94,9 @@ public:
virtual void set_physics_ticks_per_second(int p_ips);
virtual int get_physics_ticks_per_second() const;
+ virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
+ virtual int get_max_physics_steps_per_frame() const;
+
void set_physics_jitter_fix(double p_threshold);
double get_physics_jitter_fix() const;
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 4d2006d42a..7aaa9a46b7 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -82,7 +82,7 @@ String ProjectSettings::get_imported_files_path() const {
// Returns the features that a project must have when opened with this build of Godot.
// This is used by the project manager to provide the initial_settings for config/features.
const PackedStringArray ProjectSettings::get_required_features() {
- PackedStringArray features = PackedStringArray();
+ PackedStringArray features;
features.append(VERSION_BRANCH);
#ifdef REAL_T_IS_DOUBLE
features.append("Double Precision");
@@ -115,7 +115,7 @@ const PackedStringArray ProjectSettings::_get_supported_features() {
// Returns the features that this project needs but this build of Godot lacks.
const PackedStringArray ProjectSettings::get_unsupported_features(const PackedStringArray &p_project_features) {
- PackedStringArray unsupported_features = PackedStringArray();
+ PackedStringArray unsupported_features;
PackedStringArray supported_features = singleton->_get_supported_features();
for (int i = 0; i < p_project_features.size(); i++) {
if (!supported_features.has(p_project_features[i])) {
@@ -1246,12 +1246,12 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC("audio/buses/default_bus_layout", "res://default_bus_layout.tres");
custom_prop_info["audio/buses/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/buses/default_bus_layout", PROPERTY_HINT_FILE, "*.tres");
- GLOBAL_DEF_RST("audio/general/2d_panning_strength", 1.0f);
- custom_prop_info["audio/general/2d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/2d_panning_strength", PROPERTY_HINT_RANGE, "0,4,0.01");
- GLOBAL_DEF_RST("audio/general/3d_panning_strength", 1.0f);
- custom_prop_info["audio/general/3d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/3d_panning_strength", PROPERTY_HINT_RANGE, "0,4,0.01");
+ GLOBAL_DEF_RST("audio/general/2d_panning_strength", 0.5f);
+ custom_prop_info["audio/general/2d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/2d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01");
+ GLOBAL_DEF_RST("audio/general/3d_panning_strength", 0.5f);
+ custom_prop_info["audio/general/3d_panning_strength"] = PropertyInfo(Variant::FLOAT, "audio/general/3d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01");
- PackedStringArray extensions = PackedStringArray();
+ PackedStringArray extensions;
extensions.push_back("gd");
if (Engine::get_singleton()->has_singleton("GodotSharp")) {
extensions.push_back("cs");
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 87b36f7a21..1fe34cb4fd 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1477,6 +1477,14 @@ int Engine::get_physics_ticks_per_second() const {
return ::Engine::get_singleton()->get_physics_ticks_per_second();
}
+void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
+ ::Engine::get_singleton()->set_max_physics_steps_per_frame(p_max_physics_steps);
+}
+
+int Engine::get_max_physics_steps_per_frame() const {
+ return ::Engine::get_singleton()->get_max_physics_steps_per_frame();
+}
+
void Engine::set_physics_jitter_fix(double p_threshold) {
::Engine::get_singleton()->set_physics_jitter_fix(p_threshold);
}
@@ -1628,6 +1636,8 @@ bool Engine::is_printing_error_messages() const {
void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_physics_ticks_per_second", "physics_ticks_per_second"), &Engine::set_physics_ticks_per_second);
ClassDB::bind_method(D_METHOD("get_physics_ticks_per_second"), &Engine::get_physics_ticks_per_second);
+ ClassDB::bind_method(D_METHOD("set_max_physics_steps_per_frame", "max_physics_steps"), &Engine::set_max_physics_steps_per_frame);
+ ClassDB::bind_method(D_METHOD("get_max_physics_steps_per_frame"), &Engine::get_max_physics_steps_per_frame);
ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &Engine::set_physics_jitter_fix);
ClassDB::bind_method(D_METHOD("get_physics_jitter_fix"), &Engine::get_physics_jitter_fix);
ClassDB::bind_method(D_METHOD("get_physics_interpolation_fraction"), &Engine::get_physics_interpolation_fraction);
@@ -1675,6 +1685,7 @@ void Engine::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second"), "set_physics_ticks_per_second", "get_physics_ticks_per_second");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_physics_steps_per_frame"), "set_max_physics_steps_per_frame", "get_max_physics_steps_per_frame");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_fps"), "set_max_fps", "get_max_fps");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_scale"), "set_time_scale", "get_time_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "physics_jitter_fix"), "set_physics_jitter_fix", "get_physics_jitter_fix");
diff --git a/core/core_bind.h b/core/core_bind.h
index 784f3e63b1..748ecb4929 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -486,6 +486,9 @@ public:
void set_physics_ticks_per_second(int p_ips);
int get_physics_ticks_per_second() const;
+ void set_max_physics_steps_per_frame(int p_max_physics_steps);
+ int get_max_physics_steps_per_frame() const;
+
void set_physics_jitter_fix(double p_threshold);
double get_physics_jitter_fix() const;
double get_physics_interpolation_fraction() const;
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 0e8532a327..628740ed32 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -595,8 +595,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXPRESSION);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY);
- BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_ID);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TYPE_STRING);
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 23ee977df4..a2e3fab82c 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -39,89 +39,6 @@
#include "core/object/script_language.h"
#include "core/os/os.h"
-class RemoteDebugger::MultiplayerProfiler : public EngineProfiler {
- struct BandwidthFrame {
- uint32_t timestamp;
- int packet_size;
- };
-
- int bandwidth_in_ptr = 0;
- Vector<BandwidthFrame> bandwidth_in;
- int bandwidth_out_ptr = 0;
- Vector<BandwidthFrame> bandwidth_out;
- uint64_t last_bandwidth_time = 0;
-
- int bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer) {
- ERR_FAIL_COND_V(p_buffer.size() == 0, 0);
- int total_bandwidth = 0;
-
- uint64_t timestamp = OS::get_singleton()->get_ticks_msec();
- uint64_t final_timestamp = timestamp - 1000;
-
- int i = (p_pointer + p_buffer.size() - 1) % p_buffer.size();
-
- while (i != p_pointer && p_buffer[i].packet_size > 0) {
- if (p_buffer[i].timestamp < final_timestamp) {
- return total_bandwidth;
- }
- total_bandwidth += p_buffer[i].packet_size;
- i = (i + p_buffer.size() - 1) % p_buffer.size();
- }
-
- ERR_FAIL_COND_V_MSG(i == p_pointer, total_bandwidth, "Reached the end of the bandwidth profiler buffer, values might be inaccurate.");
- return total_bandwidth;
- }
-
-public:
- void toggle(bool p_enable, const Array &p_opts) {
- if (!p_enable) {
- bandwidth_in.clear();
- bandwidth_out.clear();
- } else {
- bandwidth_in_ptr = 0;
- bandwidth_in.resize(16384); // ~128kB
- for (int i = 0; i < bandwidth_in.size(); ++i) {
- bandwidth_in.write[i].packet_size = -1;
- }
- bandwidth_out_ptr = 0;
- bandwidth_out.resize(16384); // ~128kB
- for (int i = 0; i < bandwidth_out.size(); ++i) {
- bandwidth_out.write[i].packet_size = -1;
- }
- }
- }
-
- void add(const Array &p_data) {
- ERR_FAIL_COND(p_data.size() < 3);
- const String inout = p_data[0];
- int time = p_data[1];
- int size = p_data[2];
- if (inout == "in") {
- bandwidth_in.write[bandwidth_in_ptr].timestamp = time;
- bandwidth_in.write[bandwidth_in_ptr].packet_size = size;
- bandwidth_in_ptr = (bandwidth_in_ptr + 1) % bandwidth_in.size();
- } else if (inout == "out") {
- bandwidth_out.write[bandwidth_out_ptr].timestamp = time;
- bandwidth_out.write[bandwidth_out_ptr].packet_size = size;
- bandwidth_out_ptr = (bandwidth_out_ptr + 1) % bandwidth_out.size();
- }
- }
-
- void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
- uint64_t pt = OS::get_singleton()->get_ticks_msec();
- if (pt - last_bandwidth_time > 200) {
- last_bandwidth_time = pt;
- int incoming_bandwidth = bandwidth_usage(bandwidth_in, bandwidth_in_ptr);
- int outgoing_bandwidth = bandwidth_usage(bandwidth_out, bandwidth_out_ptr);
-
- Array arr;
- arr.push_back(incoming_bandwidth);
- arr.push_back(outgoing_bandwidth);
- EngineDebugger::get_singleton()->send_message("multiplayer:bandwidth", arr);
- }
- }
-};
-
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
Object *performance = nullptr;
int last_perf_time = 0;
@@ -659,10 +576,6 @@ RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
max_errors_per_second = GLOBAL_GET("network/limits/debugger/max_errors_per_second");
max_warnings_per_second = GLOBAL_GET("network/limits/debugger/max_warnings_per_second");
- // Multiplayer Profiler
- multiplayer_profiler.instantiate();
- multiplayer_profiler->bind("multiplayer");
-
// Performance Profiler
Object *perf = Engine::get_singleton()->get_singleton_object("Performance");
if (perf) {
diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h
index fe4bbe86ea..944229d361 100644
--- a/core/debugger/remote_debugger.h
+++ b/core/debugger/remote_debugger.h
@@ -50,10 +50,8 @@ public:
private:
typedef DebuggerMarshalls::OutputError ErrorMessage;
- class MultiplayerProfiler;
class PerformanceProfiler;
- Ref<MultiplayerProfiler> multiplayer_profiler;
Ref<PerformanceProfiler> performance_profiler;
Ref<RemoteDebuggerPeer> peer;
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 68eed5a161..50410c4857 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -109,6 +109,7 @@ typedef enum {
GDNATIVE_VARIANT_OP_LESS_EQUAL,
GDNATIVE_VARIANT_OP_GREATER,
GDNATIVE_VARIANT_OP_GREATER_EQUAL,
+
/* mathematic */
GDNATIVE_VARIANT_OP_ADD,
GDNATIVE_VARIANT_OP_SUBTRACT,
@@ -118,6 +119,7 @@ typedef enum {
GDNATIVE_VARIANT_OP_POSITIVE,
GDNATIVE_VARIANT_OP_MODULE,
GDNATIVE_VARIANT_OP_POWER,
+
/* bitwise */
GDNATIVE_VARIANT_OP_SHIFT_LEFT,
GDNATIVE_VARIANT_OP_SHIFT_RIGHT,
@@ -125,11 +127,13 @@ typedef enum {
GDNATIVE_VARIANT_OP_BIT_OR,
GDNATIVE_VARIANT_OP_BIT_XOR,
GDNATIVE_VARIANT_OP_BIT_NEGATE,
+
/* logic */
GDNATIVE_VARIANT_OP_AND,
GDNATIVE_VARIANT_OP_OR,
GDNATIVE_VARIANT_OP_XOR,
GDNATIVE_VARIANT_OP_NOT,
+
/* containment */
GDNATIVE_VARIANT_OP_IN,
GDNATIVE_VARIANT_OP_MAX
@@ -152,11 +156,11 @@ typedef uint64_t GDObjectInstanceID;
typedef enum {
GDNATIVE_CALL_OK,
GDNATIVE_CALL_ERROR_INVALID_METHOD,
- GDNATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */
- GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */
- GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */
+ GDNATIVE_CALL_ERROR_INVALID_ARGUMENT, // Expected a different variant type.
+ GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, // Expected lower number of arguments.
+ GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, // Expected higher number of arguments.
GDNATIVE_CALL_ERROR_INSTANCE_IS_NULL,
- GDNATIVE_CALL_ERROR_METHOD_NOT_CONST, /* used for const call */
+ GDNATIVE_CALL_ERROR_METHOD_NOT_CONST, // Used for const call.
} GDNativeCallErrorType;
typedef struct {
@@ -204,20 +208,24 @@ typedef struct {
GDNativeVariantType type;
GDNativeStringNamePtr name;
GDNativeStringNamePtr class_name;
- uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`)
+ uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`).
GDNativeStringPtr hint_string;
- uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`)
+ uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`).
} GDNativePropertyInfo;
typedef struct {
GDNativeStringNamePtr name;
GDNativePropertyInfo return_value;
- uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags`
+ uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags`.
int32_t id;
- GDNativePropertyInfo *arguments; // array of `argument_count` size
+
+ /* Arguments: `default_arguments` is an array of size `argument_count`. */
uint32_t argument_count;
- GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size
+ GDNativePropertyInfo *arguments;
+
+ /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */
uint32_t default_argument_count;
+ GDNativeVariantPtr *default_arguments;
} GDNativeMethodInfo;
typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
@@ -246,11 +254,11 @@ typedef struct {
GDNativeExtensionClassToString to_string_func;
GDNativeExtensionClassReference reference_func;
GDNativeExtensionClassUnreference unreference_func;
- GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
- GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
- GDNativeExtensionClassGetVirtual get_virtual_func;
+ GDNativeExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
+ GDNativeExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
+ GDNativeExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
GDNativeExtensionClassGetRID get_rid_func;
- void *class_userdata;
+ void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDNativeExtensionClassCreationInfo;
typedef void *GDNativeExtensionClassLibraryPtr;
@@ -289,26 +297,34 @@ typedef struct {
void *method_userdata;
GDNativeExtensionClassMethodCall call_func;
GDNativeExtensionClassMethodPtrCall ptrcall_func;
- uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags`
- uint32_t argument_count;
+ uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags`.
+
+ /* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored. */
GDNativeBool has_return_value;
- GDNativePropertyInfo *return_value_info; // Ignored if `has_return_value` is false
- GDNativeExtensionClassMethodArgumentMetadata return_value_metadata; // Ignored if `has_return_value` is false
- /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
- GDNativePropertyInfo *aguments_info; // array of `argument_count` size
- GDNativeExtensionClassMethodArgumentMetadata *aguments_metadata; // array of `argument_count` size
+ GDNativePropertyInfo *return_value_info;
+ GDNativeExtensionClassMethodArgumentMetadata return_value_metadata;
+
+ /* Arguments: `arguments_info` and `arguments_metadata` are array of size `argument_count`.
+ * Name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies.
+ */
+ uint32_t argument_count;
+ GDNativePropertyInfo *arguments_info;
+ GDNativeExtensionClassMethodArgumentMetadata *arguments_metadata;
+
+ /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */
uint32_t default_argument_count;
- GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size
+ GDNativeVariantPtr *default_arguments;
} GDNativeExtensionClassMethodInfo;
/* SCRIPT INSTANCE EXTENSION */
-typedef void *GDNativeExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation
+typedef void *GDNativeExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation.
typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list);
+typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid);
typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name);
typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
@@ -354,6 +370,7 @@ typedef struct {
GDNativeExtensionScriptInstanceGetMethodList get_method_list_func;
GDNativeExtensionScriptInstanceFreeMethodList free_method_list_func;
+ GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func;
GDNativeExtensionScriptInstanceHasMethod has_method_func;
@@ -387,6 +404,7 @@ typedef struct {
const char *version_string;
/* GODOT CORE */
+
void *(*mem_alloc)(size_t p_bytes);
void *(*mem_realloc)(void *p_ptr, size_t p_bytes);
void (*mem_free)(void *p_ptr);
@@ -453,7 +471,6 @@ typedef struct {
GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const GDNativeStringNamePtr p_function, GDNativeInt p_hash);
/* extra utilities */
-
void (*string_new_with_latin1_chars)(GDNativeStringPtr r_dest, const char *p_contents);
void (*string_new_with_utf8_chars)(GDNativeStringPtr r_dest, const char *p_contents);
void (*string_new_with_utf16_chars)(GDNativeStringPtr r_dest, const char16_t *p_contents);
@@ -464,6 +481,7 @@ typedef struct {
void (*string_new_with_utf16_chars_and_len)(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size);
void (*string_new_with_utf32_chars_and_len)(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size);
void (*string_new_with_wide_chars_and_len)(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size);
+
/* Information about the following functions:
* - The return value is the resulting encoded string length.
* - The length returned is in characters, not in bytes. It also does not include a trailing zero.
@@ -535,13 +553,14 @@ typedef struct {
GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data);
/* CLASSDB */
+
GDNativeObjectPtr (*classdb_construct_object)(const GDNativeStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
GDNativeMethodBindPtr (*classdb_get_method_bind)(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash);
void *(*classdb_get_class_tag)(const GDNativeStringNamePtr p_classname);
/* CLASSDB EXTENSION */
- // Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns
+ /* Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns. */
void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
@@ -577,9 +596,10 @@ typedef struct {
} GDNativeInitialization;
/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar).
- * It will be called on initialization. The name must be an unique one specified in the .gdextension config file.
+ * This is the entry point of the GDExtension library and will be called on initialization.
+ * It can be used to set up different init levels, which are called during various stages of initialization/shutdown.
+ * The function name must be a unique one specified in the .gdextension config file.
*/
-
typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization);
#ifdef __cplusplus
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 8bbb72fd82..83a2e80793 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -108,8 +108,8 @@ public:
}
for (uint32_t i = 0; i < p_method_info->argument_count; i++) {
- arguments_info.push_back(PropertyInfo(p_method_info->aguments_info[i]));
- arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->aguments_metadata[i]));
+ arguments_info.push_back(PropertyInfo(p_method_info->arguments_info[i]));
+ arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->arguments_metadata[i]));
}
set_hint_flags(p_method_info->method_flags);
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 9dc071de9c..0a32b4bf68 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -1562,7 +1562,7 @@ String InputEventMIDI::as_text() const {
}
String InputEventMIDI::to_string() {
- return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d", channel, message, pitch, velocity, pressure);
+ return vformat("InputEventMIDI: channel=%d, message=%d, pitch=%d, velocity=%d, pressure=%d, controller_number=%d, controller_value=%d", channel, message, pitch, velocity, pressure, controller_number, controller_value);
}
void InputEventMIDI::_bind_methods() {
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index aa1b323db2..0118b4c6af 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -107,6 +107,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
}
Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) {
+ ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
+
Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
if (f.is_null()) {
return ERR_FILE_CANT_OPEN;
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index abae48fdd8..16b7f3a1f6 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -41,11 +41,11 @@ static inline bool _is_white_space(char c) {
}
//! sets the state that text was found. Returns true if set should be set
-bool XMLParser::_set_text(char *start, char *end) {
+bool XMLParser::_set_text(const char *start, const char *end) {
// check if text is more than 2 characters, and if not, check if there is
// only white space, so that this text won't be reported
if (end - start < 3) {
- char *p = start;
+ const char *p = start;
for (; p != end; ++p) {
if (!_is_white_space(*p)) {
break;
@@ -92,7 +92,7 @@ void XMLParser::_parse_closing_xml_element() {
void XMLParser::_ignore_definition() {
node_type = NODE_UNKNOWN;
- char *F = P;
+ const char *F = P;
// move until end marked with '>' reached
while (*P && *P != '>') {
next_char();
@@ -123,8 +123,8 @@ bool XMLParser::_parse_cdata() {
return true;
}
- char *cDataBegin = P;
- char *cDataEnd = nullptr;
+ const char *cDataBegin = P;
+ const char *cDataEnd = nullptr;
// find end of CDATA
while (*P && !cDataEnd) {
@@ -152,9 +152,9 @@ void XMLParser::_parse_comment() {
node_type = NODE_COMMENT;
P += 1;
- char *pEndOfInput = data + length;
- char *pCommentBegin;
- char *pCommentEnd;
+ const char *pEndOfInput = data + length;
+ const char *pCommentBegin;
+ const char *pCommentEnd;
if (P + 1 < pEndOfInput && P[0] == '-' && P[1] == '-') {
// Comment, use '-->' as end.
@@ -293,7 +293,7 @@ void XMLParser::_parse_opening_xml_element() {
}
void XMLParser::_parse_current_node() {
- char *start = P;
+ const char *start = P;
node_offset = P - data;
// more forward until '<' found
@@ -458,15 +458,36 @@ bool XMLParser::is_empty() const {
Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) {
ERR_FAIL_COND_V(p_buffer.size() == 0, ERR_INVALID_DATA);
- if (data) {
- memdelete_arr(data);
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
}
length = p_buffer.size();
- data = memnew_arr(char, length + 1);
- memcpy(data, p_buffer.ptr(), length);
- data[length] = 0;
+ data_copy = memnew_arr(char, length + 1);
+ memcpy(data_copy, p_buffer.ptr(), length);
+ data_copy[length] = 0;
+ data = data_copy;
+ P = data;
+ current_line = 0;
+
+ return OK;
+}
+
+Error XMLParser::_open_buffer(const uint8_t *p_buffer, size_t p_size) {
+ ERR_FAIL_COND_V(p_size == 0, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(!p_buffer, ERR_INVALID_DATA);
+
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
+ }
+
+ length = p_size;
+ data = (const char *)p_buffer;
P = data;
+ current_line = 0;
+
return OK;
}
@@ -479,13 +500,15 @@ Error XMLParser::open(const String &p_path) {
length = file->get_length();
ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT);
- if (data) {
- memdelete_arr(data);
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
}
- data = memnew_arr(char, length + 1);
- file->get_buffer((uint8_t *)data, length);
- data[length] = 0;
+ data_copy = memnew_arr(char, length + 1);
+ file->get_buffer((uint8_t *)data_copy, length);
+ data_copy[length] = 0;
+ data = data_copy;
P = data;
current_line = 0;
@@ -512,8 +535,9 @@ void XMLParser::skip_section() {
}
void XMLParser::close() {
- if (data) {
+ if (data_copy) {
memdelete_arr(data);
+ data_copy = nullptr;
}
data = nullptr;
length = 0;
@@ -528,7 +552,8 @@ int XMLParser::get_current_line() const {
}
XMLParser::~XMLParser() {
- if (data) {
- memdelete_arr(data);
+ if (data_copy) {
+ memdelete_arr(data_copy);
+ data_copy = nullptr;
}
}
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index aea252ddc7..be44f771dc 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -65,8 +65,9 @@ public:
};
private:
- char *data = nullptr;
- char *P = nullptr;
+ char *data_copy = nullptr;
+ const char *data = nullptr;
+ const char *P = nullptr;
uint64_t length = 0;
uint64_t current_line = 0;
String node_name;
@@ -81,7 +82,7 @@ private:
Vector<Attribute> attributes;
- bool _set_text(char *start, char *end);
+ bool _set_text(const char *start, const char *end);
void _parse_closing_xml_element();
void _ignore_definition();
bool _parse_cdata();
@@ -118,6 +119,7 @@ public:
Error open(const String &p_path);
Error open_buffer(const Vector<uint8_t> &p_buffer);
+ Error _open_buffer(const uint8_t *p_buffer, size_t p_size);
void close();
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index 41ec6d8ce3..d7bb025b69 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -487,7 +487,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = 0.0f;
}
return euler;
- } break;
+ }
case EulerOrder::XZY: {
// Euler angles in XZY convention.
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
@@ -516,7 +516,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = -Math_PI / 2.0f;
}
return euler;
- } break;
+ }
case EulerOrder::YXZ: {
// Euler angles in YXZ convention.
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
@@ -554,7 +554,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
}
return euler;
- } break;
+ }
case EulerOrder::YZX: {
// Euler angles in YZX convention.
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
@@ -639,7 +639,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const {
euler.z = -Math::atan2(rows[0][1], rows[1][1]);
}
return euler;
- } break;
+ }
default: {
ERR_FAIL_V_MSG(Vector3(), "Invalid parameter for get_euler(order)");
}
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index dcec3929fe..26b809e7f2 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -1420,7 +1420,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
Callable::CallError ce;
Variant::call_utility_function(bifunc->func, &r_ret, (const Variant **)argp.ptr(), argp.size(), ce);
if (ce.error != Callable::CallError::CALL_OK) {
- r_error_str = "Builtin Call Failed. " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce);
+ r_error_str = "Builtin call failed: " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce);
return true;
}
diff --git a/core/math/projection.cpp b/core/math/projection.cpp
index 70cc9b5f7c..9af388b081 100644
--- a/core/math/projection.cpp
+++ b/core/math/projection.cpp
@@ -181,7 +181,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
- } break;
+ }
case PLANE_FAR: {
Plane new_plane = Plane(matrix[3] - matrix[2],
matrix[7] - matrix[6],
@@ -191,7 +191,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
- } break;
+ }
case PLANE_LEFT: {
Plane new_plane = Plane(matrix[3] + matrix[0],
matrix[7] + matrix[4],
@@ -201,7 +201,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
- } break;
+ }
case PLANE_TOP: {
Plane new_plane = Plane(matrix[3] - matrix[1],
matrix[7] - matrix[5],
@@ -211,7 +211,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
- } break;
+ }
case PLANE_RIGHT: {
Plane new_plane = Plane(matrix[3] - matrix[0],
matrix[7] - matrix[4],
@@ -221,7 +221,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
- } break;
+ }
case PLANE_BOTTOM: {
Plane new_plane = Plane(matrix[3] + matrix[1],
matrix[7] + matrix[5],
@@ -231,7 +231,7 @@ Plane Projection::get_projection_plane(Planes p_plane) const {
new_plane.normal = -new_plane.normal;
new_plane.normalize();
return new_plane;
- } break;
+ }
}
return Plane();
diff --git a/core/object/object.h b/core/object/object.h
index 7bb88998a2..16ad7b8832 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -71,8 +71,6 @@ enum PropertyHint {
PROPERTY_HINT_EXPRESSION, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
- PROPERTY_HINT_IMAGE_COMPRESS_LOSSY,
- PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS,
PROPERTY_HINT_OBJECT_ID,
PROPERTY_HINT_TYPE_STRING, ///< a type string, the hint is the base type to choose
PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE, ///< so something else can provide this (used in scripts)
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index c287a6f71a..9a2a176096 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -681,21 +681,15 @@ public:
}
}
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override {
- Variant::Type type = Variant::Type::NIL;
- if (native_info->get_property_list_func) {
- uint32_t pcount;
- const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
- for (uint32_t i = 0; i < pcount; i++) {
- if (p_name == *reinterpret_cast<StringName *>(pinfo->name)) {
- type = Variant::Type(pinfo->type);
- break;
- }
- }
- if (native_info->free_property_list_func) {
- native_info->free_property_list_func(instance, pinfo);
+ if (native_info->get_property_type_func) {
+ GDNativeBool is_valid = 0;
+ GDNativeVariantType type = native_info->get_property_type_func(instance, (const GDNativeStringNamePtr)&p_name, &is_valid);
+ if (r_is_valid) {
+ *r_is_valid = is_valid != 0;
}
+ return Variant::Type(type);
}
- return type;
+ return Variant::NIL;
}
virtual bool property_can_revert(const StringName &p_name) const override {
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index aa66e86bc0..9f8a1de697 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -423,6 +423,10 @@ String UndoRedo::get_current_action_name() const {
return actions[current_action].name;
}
+int UndoRedo::get_action_level() const {
+ return action_level;
+}
+
bool UndoRedo::has_undo() const {
return current_action >= 0;
}
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index c7c58697c3..9c6d2d10ed 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -120,6 +120,7 @@ public:
bool redo();
bool undo();
String get_current_action_name() const;
+ int get_action_level() const;
int get_history_count();
int get_current_action();
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp
index b130c2fc79..2fb3b54e27 100644
--- a/core/string/optimized_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -267,6 +267,39 @@ StringName OptimizedTranslation::get_message(const StringName &p_src_text, const
}
}
+Vector<String> OptimizedTranslation::get_translated_message_list() const {
+ Vector<String> msgs;
+
+ const int *htr = hash_table.ptr();
+ const uint32_t *htptr = (const uint32_t *)&htr[0];
+ const int *btr = bucket_table.ptr();
+ const uint32_t *btptr = (const uint32_t *)&btr[0];
+ const uint8_t *sr = strings.ptr();
+ const char *sptr = (const char *)&sr[0];
+
+ for (int i = 0; i < hash_table.size(); i++) {
+ uint32_t p = htptr[i];
+ if (p != 0xFFFFFFFF) {
+ const Bucket &bucket = *(const Bucket *)&btptr[p];
+ for (int j = 0; j < bucket.size; j++) {
+ if (bucket.elem[j].comp_size == bucket.elem[j].uncomp_size) {
+ String rstr;
+ rstr.parse_utf8(&sptr[bucket.elem[j].str_offset], bucket.elem[j].uncomp_size);
+ msgs.push_back(rstr);
+ } else {
+ CharString uncomp;
+ uncomp.resize(bucket.elem[j].uncomp_size + 1);
+ smaz_decompress(&sptr[bucket.elem[j].str_offset], bucket.elem[j].comp_size, uncomp.ptrw(), bucket.elem[j].uncomp_size);
+ String rstr;
+ rstr.parse_utf8(uncomp.get_data());
+ msgs.push_back(rstr);
+ }
+ }
+ }
+ }
+ return msgs;
+}
+
StringName OptimizedTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const {
// The use of plurals translation is not yet supported in OptimizedTranslation.
return get_message(p_src_text, p_context);
diff --git a/core/string/optimized_translation.h b/core/string/optimized_translation.h
index f3dbfe8f5c..1cd12782d0 100644
--- a/core/string/optimized_translation.h
+++ b/core/string/optimized_translation.h
@@ -81,6 +81,7 @@ protected:
public:
virtual StringName get_message(const StringName &p_src_text, const StringName &p_context = "") const override; //overridable for other implementations
virtual StringName get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context = "") const override;
+ virtual Vector<String> get_translated_message_list() const override;
void generate(const Ref<Translation> &p_from);
OptimizedTranslation() {}
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index 2bed3543dc..d1ac91957a 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -59,6 +59,18 @@ Vector<String> Translation::_get_message_list() const {
return msgs;
}
+Vector<String> Translation::get_translated_message_list() const {
+ Vector<String> msgs;
+ msgs.resize(translation_map.size());
+ int idx = 0;
+ for (const KeyValue<StringName, StringName> &E : translation_map) {
+ msgs.set(idx, E.value);
+ idx += 1;
+ }
+
+ return msgs;
+}
+
void Translation::_set_messages(const Dictionary &p_messages) {
List<Variant> keys;
p_messages.get_key_list(&keys);
@@ -140,6 +152,7 @@ void Translation::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_plural_message", "src_message", "src_plural_message", "n", "context"), &Translation::get_plural_message, DEFVAL(""));
ClassDB::bind_method(D_METHOD("erase_message", "src_message", "context"), &Translation::erase_message, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_message_list"), &Translation::_get_message_list);
+ ClassDB::bind_method(D_METHOD("get_translated_message_list"), &Translation::get_translated_message_list);
ClassDB::bind_method(D_METHOD("get_message_count"), &Translation::get_message_count);
ClassDB::bind_method(D_METHOD("_set_messages", "messages"), &Translation::_set_messages);
ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages);
diff --git a/core/string/translation.h b/core/string/translation.h
index 9a369b0b05..5e8344baac 100644
--- a/core/string/translation.h
+++ b/core/string/translation.h
@@ -64,6 +64,7 @@ public:
virtual void erase_message(const StringName &p_src_text, const StringName &p_context = "");
virtual void get_message_list(List<StringName> *r_messages) const;
virtual int get_message_count() const;
+ virtual Vector<String> get_translated_message_list() const;
Translation() {}
};
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index fa656b634d..724c1d42bc 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -103,6 +103,23 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) {
}
}
+Vector<String> TranslationPO::get_translated_message_list() const {
+ Vector<String> msgs;
+ for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
+ if (E.key != StringName()) {
+ continue;
+ }
+
+ for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) {
+ for (const StringName &E3 : E2.value) {
+ msgs.push_back(E3);
+ }
+ }
+ }
+
+ return msgs;
+}
+
Vector<String> TranslationPO::_get_message_list() const {
// Return all keys in translation_map.
diff --git a/core/string/translation_po.h b/core/string/translation_po.h
index 7d63af2246..c50ea85744 100644
--- a/core/string/translation_po.h
+++ b/core/string/translation_po.h
@@ -70,6 +70,7 @@ protected:
static void _bind_methods();
public:
+ Vector<String> get_translated_message_list() const override;
void get_message_list(List<StringName> *r_messages) const override;
int get_message_count() const override;
void add_message(const StringName &p_src_text, const StringName &p_xlated_text, const StringName &p_context = "") override;
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 2ba389fc4d..175c42542b 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -1256,8 +1256,8 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int
return ret;
}
-Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) const {
- Vector<float> ret;
+Vector<double> String::split_floats(const String &p_splitter, bool p_allow_empty) const {
+ Vector<double> ret;
int from = 0;
int len = length();
@@ -2839,7 +2839,7 @@ String String::substr(int p_from, int p_chars) const {
return String(*this);
}
- String s = String();
+ String s;
s.copy_from_unchecked(&get_data()[p_from], p_chars);
return s;
}
@@ -3922,7 +3922,6 @@ String String::c_unescape() const {
escaped = escaped.replace("\\v", "\v");
escaped = escaped.replace("\\'", "\'");
escaped = escaped.replace("\\\"", "\"");
- escaped = escaped.replace("\\?", "\?");
escaped = escaped.replace("\\\\", "\\");
return escaped;
@@ -3939,7 +3938,6 @@ String String::c_escape() const {
escaped = escaped.replace("\t", "\\t");
escaped = escaped.replace("\v", "\\v");
escaped = escaped.replace("\'", "\\'");
- escaped = escaped.replace("\?", "\\?");
escaped = escaped.replace("\"", "\\\"");
return escaped;
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 8af74584f3..0c171024f7 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -348,7 +348,7 @@ public:
Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
Vector<String> split_spaces() const;
- Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const;
+ Vector<double> split_floats(const String &p_splitter, bool p_allow_empty = true) const;
Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index b4528e67d1..c1166a0a14 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -3609,16 +3609,16 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method,
if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
int errorarg = ce.argument;
if (p_argptrs) {
- err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected));
} else {
- err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected));
}
} else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
- err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount);
} else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
- err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount);
} else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
- err_text = "Method not found.";
+ err_text = "Method not found";
} else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
err_text = "Instance is null";
} else if (ce.error == Callable::CallError::CALL_ERROR_METHOD_NOT_CONST) {
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 91af2bab85..a231a956bf 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -2438,7 +2438,7 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
- Transform3D identity_transform = Transform3D();
+ Transform3D identity_transform;
Transform3D flip_x_transform = Transform3D(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
Transform3D flip_y_transform = Transform3D(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
Transform3D flip_z_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
@@ -2447,7 +2447,7 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Y", flip_y_transform);
_VariantCall::add_variant_constant(Variant::TRANSFORM3D, "FLIP_Z", flip_z_transform);
- Basis identity_basis = Basis();
+ Basis identity_basis;
Basis flip_x_basis = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1);
Basis flip_y_basis = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1);
Basis flip_z_basis = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1);
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index ae9727fe79..624a6f5e06 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -68,11 +68,13 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructor<int64_t, int64_t>>(sarray("from"));
add_constructor<VariantConstructor<int64_t, double>>(sarray("from"));
add_constructor<VariantConstructor<int64_t, bool>>(sarray("from"));
+ add_constructor<VariantConstructorFromString<int64_t>>(sarray("from"));
add_constructor<VariantConstructNoArgs<double>>(sarray());
add_constructor<VariantConstructor<double, double>>(sarray("from"));
add_constructor<VariantConstructor<double, int64_t>>(sarray("from"));
add_constructor<VariantConstructor<double, bool>>(sarray("from"));
+ add_constructor<VariantConstructorFromString<double>>(sarray("from"));
add_constructor<VariantConstructNoArgs<String>>(sarray());
add_constructor<VariantConstructor<String, String>>(sarray("from"));
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 34d228f4d2..f52cc43914 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -222,6 +222,64 @@ public:
}
};
+template <class T>
+class VariantConstructorFromString {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ if (p_args[0]->get_type() != Variant::STRING) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::STRING;
+ return;
+ }
+
+ VariantTypeChanger<T>::change(&r_ret);
+ const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]);
+
+ if (r_ret.get_type() == Variant::Type::INT) {
+ r_ret = src_str.to_int();
+ } else if (r_ret.get_type() == Variant::Type::FLOAT) {
+ r_ret = src_str.to_float();
+ }
+ }
+
+ static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+ VariantTypeChanger<T>::change(r_ret);
+ const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]);
+ T ret = Variant();
+ if (r_ret->get_type() == Variant::Type::INT) {
+ ret = src_str.to_int();
+ } else if (r_ret->get_type() == Variant::Type::FLOAT) {
+ ret = src_str.to_float();
+ }
+ *r_ret = ret;
+ }
+
+ static void ptr_construct(void *base, const void **p_args) {
+ String src_str = PtrToArg<String>::convert(p_args[0]);
+ T dst_var = Variant();
+ Variant type_test = Variant(dst_var);
+ if (type_test.get_type() == Variant::Type::INT) {
+ dst_var = src_str.to_int();
+ } else if (type_test.get_type() == Variant::Type::FLOAT) {
+ dst_var = src_str.to_float();
+ }
+ PtrConstruct<T>::construct(dst_var, base);
+ }
+
+ static int get_argument_count() {
+ return 1;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::STRING;
+ }
+
+ static Variant::Type get_base_type() {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+ }
+};
+
class VariantConstructorCallableArgs {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index ed404ea504..09713bce2f 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -2734,17 +2734,10 @@
<constant name="PROPERTY_HINT_COLOR_NO_ALPHA" value="21" enum="PropertyHint">
Hints that a [Color] property should be edited without affecting its transparency ([member Color.a] is not editable).
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSY" value="22" enum="PropertyHint">
- Hints that an image is compressed using lossy compression. The editor does not internally use this property hint.
+ <constant name="PROPERTY_HINT_OBJECT_ID" value="22" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint">
- Hints that an image is compressed using lossless compression. The editor does not internally use this property hint.
- </constant>
- <constant name="PROPERTY_HINT_OBJECT_ID" value="24" enum="PropertyHint">
- </constant>
- <constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint">
- Hints that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types.
- [b]Example:[/b]
+ <constant name="PROPERTY_HINT_TYPE_STRING" value="23" enum="PropertyHint">
+ Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance:
[codeblock]
hint_string = "%s:" % [TYPE_INT] # Array of integers.
hint_string = "%s:%s:" % [TYPE_ARRAY, TYPE_REAL] # Two-dimensional array of floats.
@@ -2753,56 +2746,53 @@
[/codeblock]
[b]Note:[/b] The final colon is required for properly detecting built-in types.
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="26" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="24" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="27" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="25" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="28" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="26" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="29" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="27" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="30" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="28" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="31" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="29" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="32" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="30" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="33" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="31" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="34" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="32" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="35" enum="PropertyHint">
- Hints that a property's size (in bytes) is too big to be displayed, when debugging a running project. The debugger uses this hint internally.
+ <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="33" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="36" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="34" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_SAVE_FILE" value="37" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_SAVE_FILE" value="35" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="38" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_GLOBAL_SAVE_FILE" value="36" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="39" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="37" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_INT_IS_POINTER" value="40" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_INT_IS_POINTER" value="38" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_ARRAY_TYPE" value="41" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_ARRAY_TYPE" value="39" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_LOCALE_ID" value="42" enum="PropertyHint">
- Hints that a [String] property is a locale code. Editing it will show a locale dialog for picking language and country.
+ <constant name="PROPERTY_HINT_LOCALE_ID" value="40" enum="PropertyHint">
+ Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country.
</constant>
- <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="43" enum="PropertyHint">
- Hints that a [Dictionary] property is string translation map. Dictionary keys are locale codes and, values are translated strings.
+ <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="41" enum="PropertyHint">
+ Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings.
</constant>
- <constant name="PROPERTY_HINT_NODE_TYPE" value="44" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_NODE_TYPE" value="42" enum="PropertyHint">
</constant>
- <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="45" enum="PropertyHint">
- Hints that a [Quaternion] property should disable the temporary euler editor.
+ <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="43" enum="PropertyHint">
+ Hints that a quaternion property should disable the temporary euler editor.
</constant>
- <constant name="PROPERTY_HINT_PASSWORD" value="46" enum="PropertyHint">
- Hints that a [String] property is a password. Every character of the string is displayed as the secret character (typically [code]*[/code]).
- An optional placeholder text can be shown on its input field, similarly to [constant PROPERTY_HINT_PLACEHOLDER_TEXT].
+ <constant name="PROPERTY_HINT_PASSWORD" value="44" enum="PropertyHint">
+ Hints that a string property is a password, and every character is replaced with the secret character.
</constant>
- <constant name="PROPERTY_HINT_MAX" value="47" enum="PropertyHint">
- Represents the size of the [enum PropertyHint] enum.
+ <constant name="PROPERTY_HINT_MAX" value="45" enum="PropertyHint">
</constant>
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
The property is not stored, and does not display in the editor. This is the default for non-exported properties.
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 008296713d..af8d9c416f 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -568,13 +568,6 @@
The animation step value.
</member>
</members>
- <signals>
- <signal name="tracks_changed">
- <description>
- Emitted when there's a change in the list of tracks, e.g. tracks are added, moved or have changed paths.
- </description>
- </signal>
- </signals>
<constants>
<constant name="TYPE_VALUE" value="0" enum="TrackType">
Value tracks set values in node properties, but only those which can be interpolated. For 3D position/rotation/scale, using the dedicated [constant TYPE_POSITION_3D], [constant TYPE_ROTATION_3D] and [constant TYPE_SCALE_3D] track types instead of [constant TYPE_VALUE] is recommended for performance reasons.
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index ab948dd0de..b9c8ab0f6c 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -25,10 +25,12 @@
m.mesh = arr_mesh
[/gdscript]
[csharp]
- var vertices = new Godot.Collections.Array&lt;Vector3&gt;();
- vertices.Add(new Vector3(0, 1, 0));
- vertices.Add(new Vector3(1, 0, 0));
- vertices.Add(new Vector3(0, 0, 1));
+ var vertices = new Vector3[]
+ {
+ new Vector3(0, 1, 0),
+ new Vector3(1, 0, 0),
+ new Vector3(0, 0, 1),
+ };
// Initialize the ArrayMesh.
var arrMesh = new ArrayMesh();
@@ -38,7 +40,7 @@
// Create the Mesh.
arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);
- var m = new MeshInstance();
+ var m = new MeshInstance3D();
m.Mesh = arrMesh;
[/csharp]
[/codeblocks]
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index de980eab0c..fbb31cadcd 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -529,13 +529,13 @@
The material will use the texture's alpha values for transparency.
</constant>
<constant name="TRANSPARENCY_ALPHA_SCISSOR" value="2" enum="Transparency">
- The material will cut off all values below a threshold, the rest will remain opaque.
+ The material will cut off all values below a threshold, the rest will remain opaque. The opaque portions will be rendering in the depth prepass.
</constant>
<constant name="TRANSPARENCY_ALPHA_HASH" value="3" enum="Transparency">
The material will cut off all values below a spatially-deterministic threshold, the rest will remain opaque.
</constant>
<constant name="TRANSPARENCY_ALPHA_DEPTH_PRE_PASS" value="4" enum="Transparency">
- The material will use the texture's alpha value for transparency, but will still be rendered in the pre-pass.
+ The material will use the texture's alpha value for transparency, but will still be rendered in the depth prepass.
</constant>
<constant name="TRANSPARENCY_MAX" value="5" enum="Transparency">
Represents the size of the [enum Transparency] enum.
@@ -613,13 +613,14 @@
Enables AlphaToCoverage and forces all non-zero alpha values to [code]1[/code]. Alpha values in the material are passed to the AntiAliasing sample mask.
</constant>
<constant name="DEPTH_DRAW_OPAQUE_ONLY" value="0" enum="DepthDrawMode">
- Default depth draw mode. Depth is drawn only for opaque objects.
+ Default depth draw mode. Depth is drawn only for opaque objects during the opaque prepass (if any) and during the opaque pass.
</constant>
<constant name="DEPTH_DRAW_ALWAYS" value="1" enum="DepthDrawMode">
- Depth draw is calculated for both opaque and transparent objects.
+ Objects will write to depth during the opaque and the transparent passes. Transparent objects that are close to the camera may obscure other transparent objects behind them.
+ [b]Note:[/b] This does not influence whether transparent objects are included in the depth prepass or not. For that, see [enum Transparency].
</constant>
<constant name="DEPTH_DRAW_DISABLED" value="2" enum="DepthDrawMode">
- No depth draw.
+ Objects will not write their depth to the depth buffer, even during the depth prepass (if enabled).
</constant>
<constant name="CULL_BACK" value="0" enum="CullMode">
Default cull mode. The back of the object is culled when not visible. Back face triangles will be culled when facing the camera. This results in only the front side of triangles being drawn. For closed-surface meshes this means that only the exterior of the mesh will be visible.
@@ -631,7 +632,7 @@
No culling is performed.
</constant>
<constant name="FLAG_DISABLE_DEPTH_TEST" value="0" enum="Flags">
- Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it.
+ Disables the depth test, so this object is drawn on top of all others drawn before it. This puts the object in the transparent draw pass where it is sorted based on distance to camera. Objects drawn after it in the draw order may cover it. This also disables writing to depth.
</constant>
<constant name="FLAG_ALBEDO_FROM_VERTEX_COLOR" value="1" enum="Flags">
Set [code]ALBEDO[/code] to the per-vertex color specified in the mesh.
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
index 0111ef804e..7395556d05 100644
--- a/doc/classes/CharacterBody2D.xml
+++ b/doc/classes/CharacterBody2D.xml
@@ -10,7 +10,7 @@
</description>
<tutorials>
<link title="Kinematic character (2D)">$DOCS_URL/tutorials/physics/kinematic_character_2d.html</link>
- <link title="Using KinematicBody2D">$DOCS_URL/tutorials/physics/using_kinematic_body_2d.html</link>
+ <link title="Using CharacterBody2D">$DOCS_URL/tutorials/physics/using_character_body_2d.html</link>
<link title="2D Kinematic Character Demo">https://godotengine.org/asset-library/asset/113</link>
<link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link>
</tutorials>
diff --git a/doc/classes/CompressedCubemap.xml b/doc/classes/CompressedCubemap.xml
index fbb0879fdc..10ee266897 100644
--- a/doc/classes/CompressedCubemap.xml
+++ b/doc/classes/CompressedCubemap.xml
@@ -1,8 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedCubemap" inherits="CompressedTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ 6-sided texture typically used in 3D rendering, optionally compressed.
</brief_description>
<description>
+ A cubemap that is loaded from a [code].ccube[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemap] can use one of 4 compresson methods:
+ - Uncompressed (uncompressed on the GPU)
+ - Lossless (WebP or PNG, uncompressed on the GPU)
+ - Lossy (WebP, uncompressed on the GPU)
+ - VRAM Compressed (compressed on the GPU)
+ Only [b]VRAM Compressed[/b] actually reduces the memory usage on the GPU. The [b]Lossless[/b] and [b]Lossy[/b] compression methods will reduce the required storage on disk, but they will not reduce memory usage on the GPU as the texture is sent to the GPU uncompressed.
+ Using [b]VRAM Compressed[/b] also improves loading times, as VRAM-compressed textures are faster to load compared to textures using lossless or lossy compression. VRAM compression can exhibit noticeable artifacts and is intended to be used for 3D rendering, not 2D.
+ See [Cubemap] for a general description of cubemaps.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CompressedCubemapArray.xml b/doc/classes/CompressedCubemapArray.xml
index ff096cea47..4221241910 100644
--- a/doc/classes/CompressedCubemapArray.xml
+++ b/doc/classes/CompressedCubemapArray.xml
@@ -1,8 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedCubemapArray" inherits="CompressedTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Array of 6-sided textures typically used in 3D rendering, optionally compressed.
</brief_description>
<description>
+ A cubemap array that is loaded from a [code].ccubearray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemapArray] can use one of 4 compresson methods:
+ - Uncompressed (uncompressed on the GPU)
+ - Lossless (WebP or PNG, uncompressed on the GPU)
+ - Lossy (WebP, uncompressed on the GPU)
+ - VRAM Compressed (compressed on the GPU)
+ Only [b]VRAM Compressed[/b] actually reduces the memory usage on the GPU. The [b]Lossless[/b] and [b]Lossy[/b] compression methods will reduce the required storage on disk, but they will not reduce memory usage on the GPU as the texture is sent to the GPU uncompressed.
+ Using [b]VRAM Compressed[/b] also improves loading times, as VRAM-compressed textures are faster to load compared to textures using lossless or lossy compression. VRAM compression can exhibit noticeable artifacts and is intended to be used for 3D rendering, not 2D.
+ See [CubemapArray] for a general description of cubemap arrays.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CompressedTexture2D.xml b/doc/classes/CompressedTexture2D.xml
index f7464d8951..660062af7b 100644
--- a/doc/classes/CompressedTexture2D.xml
+++ b/doc/classes/CompressedTexture2D.xml
@@ -1,10 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- A [code].ctex[/code] texture.
+ Texture with 2 dimensions, optionally compressed.
</brief_description>
<description>
- A texture that is loaded from a [code].ctex[/code] file.
+ A texture that is loaded from a [code].ctex[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedTexture2D] can use one of 4 compression methods (including a lack of any compression):
+ - Uncompressed (uncompressed on the GPU)
+ - Lossless (WebP or PNG, uncompressed on the GPU)
+ - Lossy (WebP, uncompressed on the GPU)
+ - VRAM Compressed (compressed on the GPU)
+ Only [b]VRAM Compressed[/b] actually reduces the memory usage on the GPU. The [b]Lossless[/b] and [b]Lossy[/b] compression methods will reduce the required storage on disk, but they will not reduce memory usage on the GPU as the texture is sent to the GPU uncompressed.
+ Using [b]VRAM Compressed[/b] also improves loading times, as VRAM-compressed textures are faster to load compared to textures using lossless or lossy compression. VRAM compression can exhibit noticeable artifacts and is intended to be used for 3D rendering, not 2D.
</description>
<tutorials>
</tutorials>
@@ -13,13 +19,13 @@
<return type="int" enum="Error" />
<param index="0" name="path" type="String" />
<description>
- Loads the texture from the given path.
+ Loads the texture from the specified [param path].
</description>
</method>
</methods>
<members>
<member name="load_path" type="String" setter="load" getter="get_load_path" default="&quot;&quot;">
- The CompressedTexture's file path to a [code].ctex[/code] file.
+ The [CompressedTexture2D]'s file path to a [code].ctex[/code] file.
</member>
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
</members>
diff --git a/doc/classes/CompressedTexture2DArray.xml b/doc/classes/CompressedTexture2DArray.xml
index 0c751759af..0bd894a2da 100644
--- a/doc/classes/CompressedTexture2DArray.xml
+++ b/doc/classes/CompressedTexture2DArray.xml
@@ -1,8 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedTexture2DArray" inherits="CompressedTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Array of 2-dimensional textures, optionally compressed.
</brief_description>
<description>
+ A texture array that is loaded from a [code].ctexarray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedTexture2DArray] can use one of 4 compresson methods:
+ - Uncompressed (uncompressed on the GPU)
+ - Lossless (WebP or PNG, uncompressed on the GPU)
+ - Lossy (WebP, uncompressed on the GPU)
+ - VRAM Compressed (compressed on the GPU)
+ Only [b]VRAM Compressed[/b] actually reduces the memory usage on the GPU. The [b]Lossless[/b] and [b]Lossy[/b] compression methods will reduce the required storage on disk, but they will not reduce memory usage on the GPU as the texture is sent to the GPU uncompressed.
+ Using [b]VRAM Compressed[/b] also improves loading times, as VRAM-compressed textures are faster to load compared to textures using lossless or lossy compression. VRAM compression can exhibit noticeable artifacts and is intended to be used for 3D rendering, not 2D.
+ See [Texture2DArray] for a general description of texture arrays.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CompressedTexture3D.xml b/doc/classes/CompressedTexture3D.xml
index 50bd025861..b11583b684 100644
--- a/doc/classes/CompressedTexture3D.xml
+++ b/doc/classes/CompressedTexture3D.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedTexture3D" inherits="Texture3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Texture with 3 dimensions, optionally compressed.
</brief_description>
<description>
+ [CompressedTexture3D] is the VRAM-compressed counterpart of [ImageTexture3D]. The file extension for [CompressedTexture3D] files is [code].ctex3d[/code]. This file format is internal to Godot; it is created by importing other image formats with the import system.
+ [CompressedTexture3D] uses VRAM compression, which allows to reduce memory usage on the GPU when rendering the texture. This also improves loading times, as VRAM-compressed textures are faster to load compared to textures using lossless compression. VRAM compression can exhibit noticeable artifacts and is intended to be used for 3D rendering, not 2D.
+ See [Texture3D] for a general description of 3D textures.
</description>
<tutorials>
</tutorials>
@@ -11,11 +15,13 @@
<return type="int" enum="Error" />
<param index="0" name="path" type="String" />
<description>
+ Loads the texture from the specified [param path].
</description>
</method>
</methods>
<members>
<member name="load_path" type="String" setter="load" getter="get_load_path" default="&quot;&quot;">
+ The [CompressedTexture3D]'s file path to a [code].ctex3d[/code] file.
</member>
</members>
</class>
diff --git a/doc/classes/CompressedTextureLayered.xml b/doc/classes/CompressedTextureLayered.xml
index 547679c0f0..376483ae5c 100644
--- a/doc/classes/CompressedTextureLayered.xml
+++ b/doc/classes/CompressedTextureLayered.xml
@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedTextureLayered" inherits="TextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Base class for texture arrays that can optionally be compressed.
</brief_description>
<description>
+ A texture array that is loaded from a [code].ctexarray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedTexture2D] can use one of 4 compresson methods:
+ - Uncompressed (uncompressed on the GPU)
+ - Lossless (WebP or PNG, uncompressed on the GPU)
+ - Lossy (WebP, uncompressed on the GPU)
+ - VRAM Compressed (compressed on the GPU)
+ Only [b]VRAM Compressed[/b] actually reduces the memory usage on the GPU. The [b]Lossless[/b] and [b]Lossy[/b] compression methods will reduce the required storage on disk, but they will not reduce memory usage on the GPU as the texture is sent to the GPU uncompressed.
+ Using [b]VRAM Compressed[/b] also improves loading times, as VRAM-compressed textures are faster to load compared to textures using lossless or lossy compression. VRAM compression can exhibit noticeable artifacts and is intended to be used for 3D rendering, not 2D.
</description>
<tutorials>
</tutorials>
@@ -11,11 +19,13 @@
<return type="int" enum="Error" />
<param index="0" name="path" type="String" />
<description>
+ Loads the texture at [param path].
</description>
</method>
</methods>
<members>
<member name="load_path" type="String" setter="load" getter="get_load_path" default="&quot;&quot;">
+ The path the texture should be loaded from.
</member>
</members>
</class>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index e1dd2819b2..8a38deeebe 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1010,6 +1010,10 @@
<member name="layout_direction" type="int" setter="set_layout_direction" getter="get_layout_direction" enum="Control.LayoutDirection" default="0">
Controls layout direction and text writing direction. Right-to-left layouts are necessary for certain languages (e.g. Arabic and Hebrew).
</member>
+ <member name="localize_numeral_system" type="bool" setter="set_localize_numeral_system" getter="is_localizing_numeral_system" default="true">
+ If [code]true[/code], automatically converts code line numbers, list indices, [SpinBox] and [ProgressBar] values from the Western Arabic (0..9) to the numeral systems used in current locale.
+ [b]Note:[/b] Numbers within the text are not automatically converted, it can be done manually, using [method TextServer.format_number].
+ </member>
<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" enum="Control.CursorShape" default="0">
The default cursor shape for this control. Useful for Godot plugins and applications or games that use the system's mouse cursors.
[b]Note:[/b] On Linux, shapes may vary depending on the cursor theme of the system.
@@ -1048,7 +1052,7 @@
</member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale, relative to its [member size]. Change this property to scale the node around its [member pivot_offset]. The Control's [member tooltip_text] will also scale according to this value.
- [b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=$DOCS_URL/tutorials/viewports/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually.
+ [b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually.
[b]Note:[/b] If the Control node is a child of a [Container] node, the scale will be reset to [code]Vector2(1, 1)[/code] when the scene is instantiated. To set the Control's scale when it's instantiated, wait for one frame using [code]await get_tree().process_frame[/code] then set its [member scale] property.
</member>
<member name="shortcut_context" type="Node" setter="set_shortcut_context" getter="get_shortcut_context">
diff --git a/doc/classes/Cubemap.xml b/doc/classes/Cubemap.xml
index 0cdebeda95..46ddede9b1 100644
--- a/doc/classes/Cubemap.xml
+++ b/doc/classes/Cubemap.xml
@@ -4,8 +4,9 @@
6-sided texture typically used in 3D rendering.
</brief_description>
<description>
- A cubemap is made of 6 textures organized in layers. They are typically used for faking reflections (see [ReflectionProbe]) in 3D rendering. It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods.
- This resource is typically used as a uniform in custom shaders. Few core Godot methods make use of Cubemap resources.
+ A cubemap is made of 6 textures organized in layers. They are typically used for faking reflections in 3D rendering (see [ReflectionProbe]). It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods.
+ This resource is typically used as a uniform in custom shaders. Few core Godot methods make use of [Cubemap] resources.
+ To create such a texture file yourself, reimport your image files using the Godot Editor import presets.
[b]Note:[/b] Godot doesn't support using cubemaps in a [PanoramaSkyMaterial]. You can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cubemap to an equirectangular sky map.
</description>
<tutorials>
diff --git a/doc/classes/CubemapArray.xml b/doc/classes/CubemapArray.xml
index 07e401a13d..2fd55b66c6 100644
--- a/doc/classes/CubemapArray.xml
+++ b/doc/classes/CubemapArray.xml
@@ -5,8 +5,9 @@
</brief_description>
<description>
[CubemapArray]s are made of an array of [Cubemap]s. Accordingly, like [Cubemap]s they are made of multiple textures the amount of which must be divisible by 6 (one image for each face of the cube). The primary benefit of [CubemapArray]s is that they can be accessed in shader code using a single texture reference. In other words, you can pass multiple [Cubemap]s into a shader using a single [CubemapArray].
- Generally, [CubemapArray]s provide a more efficient way for storing multiple [Cubemap]s, than storing multiple [Cubemap]s themselves in an array.
- Internally Godot, uses [CubemapArray]s for many effects including the [Sky], if you set [member ProjectSettings.rendering/reflections/sky_reflections/texture_array_reflections] to [code]true[/code].
+ Generally, [CubemapArray]s provide a more efficient way for storing multiple [Cubemap]s compared to storing multiple [Cubemap]s themselves in an array.
+ Internally, Godot uses [CubemapArray]s for many effects including the [Sky], if you set [member ProjectSettings.rendering/reflections/sky_reflections/texture_array_reflections] to [code]true[/code].
+ To create such a texture file yourself, reimport your image files using the Godot Editor import presets.
[b]Note:[/b] [CubemapArray] is not supported in the OpenGL 3 rendering backend.
</description>
<tutorials>
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 3e4e05f51a..63134417b1 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -132,6 +132,15 @@
If the curve has no up vectors, the function sends an error to the console, and returns [code](0, 1, 0)[/code].
</description>
</method>
+ <method name="sample_baked_with_rotation" qualifiers="const">
+ <return type="Transform3D" />
+ <param index="0" name="offset" type="float" />
+ <param index="1" name="cubic" type="bool" default="false" />
+ <param index="2" name="apply_tilt" type="bool" default="false" />
+ <description>
+ Similar with [code]interpolate_baked()[/code]. The the return value is [code]Transform3D[/code], with [code]origin[/code] as point position, [code]basis.x[/code] as sideway vector, [code]basis.y[/code] as up vector, [code]basis.z[/code] as forward vector. When the curve length is 0, there is no reasonable way to caculate the rotation, all vectors aligned with global space axes.
+ </description>
+ </method>
<method name="samplef" qualifiers="const">
<return type="Vector3" />
<param index="0" name="fofs" type="float" />
diff --git a/doc/classes/DirectionalLight2D.xml b/doc/classes/DirectionalLight2D.xml
index a1b8ea86be..7a54980c19 100644
--- a/doc/classes/DirectionalLight2D.xml
+++ b/doc/classes/DirectionalLight2D.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="DirectionalLight2D" inherits="Light2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Directional light from a distance.
</brief_description>
<description>
+ A directional light is a type of [Light2D] node that models an infinite number of parallel rays covering the entire scene. It is used for lights with strong intensity that are located far away from the scene (for example: to model sunlight or moonlight).
</description>
<tutorials>
</tutorials>
@@ -11,6 +13,7 @@
The height of the light. Used with 2D normal mapping. Ranges from 0 (parallel to the plane) to 1 (perpendicular to the plane).
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="10000.0">
+ Maximum distance this light covers. Increasing this value will make directional shadows visible from further away, at the cost of lower overall shadow detail and performance (due to more objects being included in shadow rendering).
</member>
</members>
</class>
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 76c67fd704..0039301bf6 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -1638,8 +1638,9 @@
Regardless of the platform, enabling full screen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling full screen mode.
</constant>
<constant name="WINDOW_MODE_EXCLUSIVE_FULLSCREEN" value="4" enum="WindowMode">
- Exclusive full screen window mode. This mode is implemented on Windows only. On other platforms, it is equivalent to [constant WINDOW_MODE_FULLSCREEN].
- Only one window in exclusive full screen mode can be visible on a given screen at a time. If multiple windows are in exclusive full screen mode for the same screen, the last one being set to this mode takes precedence.
+ Exclusive full screen window mode. This mode is implemented on Windows and macOS only. On other platforms, it is equivalent to [constant WINDOW_MODE_FULLSCREEN].
+ [b]On Windows:[/b] Only one window in exclusive full screen mode can be visible on a given screen at a time. If multiple windows are in exclusive full screen mode for the same screen, the last one being set to this mode takes precedence.
+ [b]On macOS:[/b] Exclusive full-screen mode prevents Dock and Menu from showing up when the mouse pointer is hovering the edge of the screen.
Regardless of the platform, enabling full screen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling full screen mode.
</constant>
<constant name="WINDOW_FLAG_RESIZE_DISABLED" value="0" enum="WindowFlags">
diff --git a/doc/classes/EditorDebuggerPlugin.xml b/doc/classes/EditorDebuggerPlugin.xml
index c3e0a995c6..10da1edd56 100644
--- a/doc/classes/EditorDebuggerPlugin.xml
+++ b/doc/classes/EditorDebuggerPlugin.xml
@@ -1,88 +1,88 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorDebuggerPlugin" inherits="Control" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="EditorDebuggerPlugin" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A base class to implement debugger plugins.
</brief_description>
<description>
[EditorDebuggerPlugin] provides functions related to the editor side of the debugger.
- You don't need to instantiate this class; that is automatically handled by the debugger. [Control] nodes can be added as child nodes to provide a GUI for the plugin.
- Do not free or reparent this node, otherwise it becomes unusable.
- To use [EditorDebuggerPlugin], register it using the [method EditorPlugin.add_debugger_plugin] method first.
+ To interact with the debugger, an instance of this class must be added to the editor via [method EditorPlugin.add_debugger_plugin].
+ Once added, the [method _setup_session] callback will be called for every [EditorDebuggerSession] available to the plugin, and when new ones are created (the sessions may be inactive during this stage).
+ You can retrieve the available [EditorDebuggerSession]s via [method get_sessions] or get a specific one via [method get_session].
+ [codeblocks]
+ [gdscript]
+ @tool
+ extends EditorPlugin
+
+ class ExampleEditorDebugger extends EditorDebuggerPlugin:
+
+ func _has_capture(prefix):
+ # Return true if you wish to handle message with this prefix.
+ return prefix == "my_plugin"
+
+ func _capture(message, data, session_id):
+ if message == "my_plugin:ping":
+ get_session(session_id).send_message("my_plugin:echo", data)
+
+ func _setup_session(session_id):
+ # Add a new tab in the debugger session UI containing a label.
+ var label = Label.new()
+ label.name = "Example plugin"
+ label.text = "Example plugin"
+ var session = get_session(session_id)
+ # Listens to the session started and stopped signals.
+ session.started.connect(func (): print("Session started"))
+ session.stopped.connect(func (): print("Session stopped"))
+ session.add_session_tab(label)
+
+ var debugger = ExampleEditorDebugger.new()
+
+ func _enter_tree():
+ add_debugger_plugin(debugger)
+
+ func _exit_tree():
+ remove_debugger_plugin(debugger)
+ [/gdscript]
+ [/codeblocks]
</description>
<tutorials>
</tutorials>
<methods>
- <method name="has_capture">
- <return type="bool" />
- <param index="0" name="name" type="StringName" />
- <description>
- Returns [code]true[/code] if a message capture with given name is present otherwise [code]false[/code].
- </description>
- </method>
- <method name="is_breaked">
- <return type="bool" />
- <description>
- Returns [code]true[/code] if the game is in break state otherwise [code]false[/code].
- </description>
- </method>
- <method name="is_debuggable">
+ <method name="_capture" qualifiers="virtual">
<return type="bool" />
+ <param index="0" name="message" type="String" />
+ <param index="1" name="data" type="Array" />
+ <param index="2" name="session_id" type="int" />
<description>
- Returns [code]true[/code] if the game can be debugged otherwise [code]false[/code].
+ Override this method to process incoming messages. The [param session_id] is the ID of the [EditorDebuggerSession] that received the message (which you can retrieve via [method get_session]).
</description>
</method>
- <method name="is_session_active">
+ <method name="_has_capture" qualifiers="virtual const">
<return type="bool" />
+ <param index="0" name="capture" type="String" />
<description>
- Returns [code]true[/code] if there is an instance of the game running with the attached debugger otherwise [code]false[/code].
+ Override this method to enable receiving messages from the debugger. If [param capture] is "my_message" then messages starting with "my_message:" will be passes to the [method _capture] method.
</description>
</method>
- <method name="register_message_capture">
+ <method name="_setup_session" qualifiers="virtual">
<return type="void" />
- <param index="0" name="name" type="StringName" />
- <param index="1" name="callable" type="Callable" />
+ <param index="0" name="session_id" type="int" />
<description>
- Registers a message capture with given [param name]. If [param name] is "my_message" then messages starting with "my_message:" will be called with the given callable.
- Callable must accept a message string and a data array as argument. If the message and data are valid then callable must return [code]true[/code] otherwise [code]false[/code].
+ Override this method to be notified whenever a new [EditorDebuggerSession] is created (the session may be inactive during this stage).
</description>
</method>
- <method name="send_message">
- <return type="void" />
- <param index="0" name="message" type="String" />
- <param index="1" name="data" type="Array" />
+ <method name="get_session">
+ <return type="EditorDebuggerSession" />
+ <param index="0" name="id" type="int" />
<description>
- Sends a message with given [param message] and [param data] array.
+ Returns the [EditorDebuggerSession] with the given [param id].
</description>
</method>
- <method name="unregister_message_capture">
- <return type="void" />
- <param index="0" name="name" type="StringName" />
+ <method name="get_sessions">
+ <return type="Array" />
<description>
- Unregisters the message capture with given name.
+ Returns an array of [EditorDebuggerSession] currently available to this debugger plugin.
+ Note: Not sessions in the array may be inactive, check their state via [method EditorDebuggerSession.is_active]
</description>
</method>
</methods>
- <signals>
- <signal name="breaked">
- <param index="0" name="can_debug" type="bool" />
- <description>
- Emitted when the game enters a break state.
- </description>
- </signal>
- <signal name="continued">
- <description>
- Emitted when the game exists a break state.
- </description>
- </signal>
- <signal name="started">
- <description>
- Emitted when the debugging starts.
- </description>
- </signal>
- <signal name="stopped">
- <description>
- Emitted when the debugging stops.
- </description>
- </signal>
- </signals>
</class>
diff --git a/doc/classes/EditorDebuggerSession.xml b/doc/classes/EditorDebuggerSession.xml
new file mode 100644
index 0000000000..faf528c143
--- /dev/null
+++ b/doc/classes/EditorDebuggerSession.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorDebuggerSession" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ A class to interact with the editor debugger.
+ </brief_description>
+ <description>
+ This class cannot be directly instantiated and must be retrieved via a [EditorDebuggerPlugin].
+ You can add tabs to the session UI via [method add_session_tab], send messages via [method send_message], and toggle [EngineProfiler]s via [method toggle_profiler].
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_session_tab">
+ <return type="void" />
+ <param index="0" name="control" type="Control" />
+ <description>
+ Adds the given [param control] to the debug session UI in the debugger bottom panel.
+ </description>
+ </method>
+ <method name="is_active">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the debug session is currently attached to a remote instance.
+ </description>
+ </method>
+ <method name="is_breaked">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the attached remote instance is currently in the debug loop.
+ </description>
+ </method>
+ <method name="is_debuggable">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the attached remote instance can be debugged.
+ </description>
+ </method>
+ <method name="remove_session_tab">
+ <return type="void" />
+ <param index="0" name="control" type="Control" />
+ <description>
+ Removes the given [param control] from the debug session UI in the debugger bottom panel.
+ </description>
+ </method>
+ <method name="send_message">
+ <return type="void" />
+ <param index="0" name="message" type="String" />
+ <param index="1" name="data" type="Array" default="[]" />
+ <description>
+ Sends the given [param message] to the attached remote instance, optionally passing additionally [param data]. See [EngineDebugger] for how to retrieve those messages.
+ </description>
+ </method>
+ <method name="toggle_profiler">
+ <return type="void" />
+ <param index="0" name="profiler" type="String" />
+ <param index="1" name="enable" type="bool" />
+ <param index="2" name="data" type="Array" default="[]" />
+ <description>
+ Toggle the given [param profiler] on the attached remote instance, optionally passing additionally [param data]. See [EngineProfiler] for more details.
+ </description>
+ </method>
+ </methods>
+ <signals>
+ <signal name="breaked">
+ <param index="0" name="can_debug" type="bool" />
+ <description>
+ Emitted when the attached remote instance enters a break state. If [param can_debug] is [code]true[/code], the remote instance will enter the debug loop.
+ </description>
+ </signal>
+ <signal name="continued">
+ <description>
+ Emitted when the attached remote instance exits a break state.
+ </description>
+ </signal>
+ <signal name="started">
+ <description>
+ Emitted when a remote instance is attached to this session (i.e. the session becomes active).
+ </description>
+ </signal>
+ <signal name="stopped">
+ <description>
+ Emitted when a remote instance is detached from this session (i.e. the session becomes inactive).
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml
index bb319cb5a3..5d4b83bc27 100644
--- a/doc/classes/EditorInterface.xml
+++ b/doc/classes/EditorInterface.xml
@@ -48,6 +48,12 @@
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
</description>
</method>
+ <method name="get_current_directory" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the current directory being viewed in the [FileSystemDock]. If a file is selected, its base directory will be returned using [method String.get_base_dir] instead.
+ </description>
+ </method>
<method name="get_current_path" qualifiers="const">
<return type="String" />
<description>
@@ -131,10 +137,10 @@
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
</description>
</method>
- <method name="get_selected_path" qualifiers="const">
- <return type="String" />
+ <method name="get_selected_paths" qualifiers="const">
+ <return type="PackedStringArray" />
<description>
- Returns the path of the directory currently selected in the [FileSystemDock]. If a file is selected, its base directory will be returned using [method String.get_base_dir] instead.
+ Returns an array containing the paths of the currently selected files (and directories) in the [FileSystemDock].
</description>
</method>
<method name="get_selection">
diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml
index 24e1a2da7c..3ab13ec5c0 100644
--- a/doc/classes/EditorNode3DGizmoPlugin.xml
+++ b/doc/classes/EditorNode3DGizmoPlugin.xml
@@ -8,7 +8,7 @@
To use [EditorNode3DGizmoPlugin], register it using the [method EditorPlugin.add_node_3d_gizmo_plugin] method first.
</description>
<tutorials>
- <link title="Node3D gizmo plugins">$DOCS_URL/tutorials/plugins/editor/spatial_gizmos.html</link>
+ <link title="Node3D gizmo plugins">$DOCS_URL/tutorials/plugins/editor/3d_gizmos.html</link>
</tutorials>
<methods>
<method name="_can_be_hidden" qualifiers="virtual const">
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 2289a373bf..806588d100 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -415,7 +415,7 @@
</method>
<method name="add_debugger_plugin">
<return type="void" />
- <param index="0" name="script" type="Script" />
+ <param index="0" name="script" type="EditorDebuggerPlugin" />
<description>
Adds a [Script] as debugger plugin to the Debugger. The script must extend [EditorDebuggerPlugin].
</description>
@@ -599,7 +599,7 @@
</method>
<method name="remove_debugger_plugin">
<return type="void" />
- <param index="0" name="script" type="Script" />
+ <param index="0" name="script" type="EditorDebuggerPlugin" />
<description>
Removes the debugger plugin with given script from the Debugger.
</description>
diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml
index 2aca19510b..e18bea1f67 100644
--- a/doc/classes/EditorProperty.xml
+++ b/doc/classes/EditorProperty.xml
@@ -150,7 +150,7 @@
<param index="1" name="pinned" type="bool" />
<description>
Emit it if you want to mark (or unmark) the value of a property for being saved regardless of being equal to the default value.
- The default value is the one the property will get when the node is just instantiated and can come from an ancestor scene in the inheritance/instancing chain, a script or a builtin class.
+ The default value is the one the property will get when the node is just instantiated and can come from an ancestor scene in the inheritance/instantiation chain, a script or a builtin class.
</description>
</signal>
<signal name="resource_selected">
diff --git a/doc/classes/EditorUndoRedoManager.xml b/doc/classes/EditorUndoRedoManager.xml
index c1e771d653..133ee9db0d 100644
--- a/doc/classes/EditorUndoRedoManager.xml
+++ b/doc/classes/EditorUndoRedoManager.xml
@@ -110,7 +110,7 @@
<signals>
<signal name="history_changed">
<description>
- Emitted when the list of actions in any history has changed, either when an action is commited or a history is cleared.
+ Emitted when the list of actions in any history has changed, either when an action is committed or a history is cleared.
</description>
</signal>
<signal name="version_changed">
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index 821fae37a6..d583e07f59 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -275,13 +275,16 @@
If [member ProjectSettings.display/window/vsync/vsync_mode] is [code]Disabled[/code], limiting the FPS to a high value that can be consistently reached on the system can reduce input lag compared to an uncapped framerate. Since this works by ensuring the GPU load is lower than 100%, this latency reduction is only effective in GPU-bottlenecked scenarios, not CPU-bottlenecked scenarios.
See also [member physics_ticks_per_second] and [member ProjectSettings.application/run/max_fps].
</member>
+ <member name="max_physics_steps_per_frame" type="int" setter="set_max_physics_steps_per_frame" getter="get_max_physics_steps_per_frame" default="8">
+ Controls the maximum number of physics steps that can be simulated each rendered frame. The default value is tuned to avoid "spiral of death" situations where expensive physics simulations trigger more expensive simulations indefinitely. However, the game will appear to slow down if the rendering FPS is less than [code]1 / max_physics_steps_per_frame[/code] of [member physics_ticks_per_second]. This occurs even if [code]delta[/code] is consistently used in physics calculations. To avoid this, increase [member max_physics_steps_per_frame] if you have increased [member physics_ticks_per_second] significantly above its default value.
+ </member>
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of the in-game clock and real clock but smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
[b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics_jitter_fix] to [code]0[/code].
</member>
<member name="physics_ticks_per_second" type="int" setter="set_physics_ticks_per_second" getter="get_physics_ticks_per_second" default="60">
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. This value should generally always be set to [code]60[/code] or above, as Godot doesn't interpolate the physics step. As a result, values lower than [code]60[/code] will look stuttery. This value can be increased to make input more reactive or work around collision tunneling issues, but keep in mind doing so will increase CPU usage. See also [member max_fps] and [member ProjectSettings.physics/common/physics_ticks_per_second].
- [b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member physics_ticks_per_second] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS.
+ [b]Note:[/b] Only [member max_physics_steps_per_frame] physics ticks may be simulated per rendered frame at most. If more physics ticks have to be simulated per rendered frame to keep up with rendering, the project will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended to also increase [member max_physics_steps_per_frame] if increasing [member physics_ticks_per_second] significantly above its default value.
</member>
<member name="print_error_messages" type="bool" setter="set_print_error_messages" getter="is_printing_error_messages" default="true">
If [code]false[/code], stops printing error and warning messages to the console and editor Output log. This can be used to hide error and warning messages during unit test suite runs. This property is equivalent to the [member ProjectSettings.application/run/disable_stderr] project setting.
diff --git a/doc/classes/FileSystemDock.xml b/doc/classes/FileSystemDock.xml
index 5578f449b3..00f5c7ddff 100644
--- a/doc/classes/FileSystemDock.xml
+++ b/doc/classes/FileSystemDock.xml
@@ -46,7 +46,7 @@
<description>
</description>
</signal>
- <signal name="instance">
+ <signal name="instantiate">
<param index="0" name="files" type="PackedStringArray" />
<description>
</description>
diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml
index 86d52ae9be..90a983d28b 100644
--- a/doc/classes/GeometryInstance3D.xml
+++ b/doc/classes/GeometryInstance3D.xml
@@ -13,6 +13,7 @@
<return type="Variant" />
<param index="0" name="name" type="StringName" />
<description>
+ Get the value of a shader parameter as set on this instance.
</description>
</method>
<method name="set_custom_aabb">
@@ -27,6 +28,7 @@
<param index="0" name="name" type="StringName" />
<param index="1" name="value" type="Variant" />
<description>
+ Set the value of a shader parameter for this instance only.
</description>
</method>
</methods>
@@ -45,8 +47,11 @@
[b]Note:[/b] Lights' bake mode will also affect the global illumination rendering. See [member Light3D.light_bake_mode].
</member>
<member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling" default="false">
+ If [code]true[/code], disables occlusion culling for this instance. Useful for gizmos that must be rendered even when occlusion culling is in use.
</member>
<member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias" default="1.0">
+ Changes how quickly the mesh transitions to a lower level of detail. A value of 0 will force the mesh to its lowest level of detail, a value of 1 will use the default settings, and larger values will keep the mesh in a higher level of detail at farther distances.
+ Useful for testing level of detail transitions in the editor.
</member>
<member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay">
The material overlay for the whole geometry.
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index bbd633819b..be66b8a7b9 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -118,7 +118,7 @@
<param index="2" name="use_mipmaps" type="bool" />
<param index="3" name="format" type="int" enum="Image.Format" />
<description>
- Creates an empty image of given size and format. See [enum Format] constants. If [param use_mipmaps] is [code]true[/code] then generate mipmaps for this image. See the [method generate_mipmaps].
+ Creates an empty image of given size and format. See [enum Format] constants. If [param use_mipmaps] is [code]true[/code], then generate mipmaps for this image. See the [method generate_mipmaps].
</description>
</method>
<method name="create_from_data" qualifiers="static">
diff --git a/doc/classes/ImageTexture3D.xml b/doc/classes/ImageTexture3D.xml
index 958c5f90f1..ee26a959aa 100644
--- a/doc/classes/ImageTexture3D.xml
+++ b/doc/classes/ImageTexture3D.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ImageTexture3D" inherits="Texture3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Texture with 3 dimensions.
</brief_description>
<description>
+ [ImageTexture3D] is a 3-dimensional [ImageTexture] that has a width, height, and depth. See also [ImageTextureLayered].
+ 3D textures are typically used to store density maps for [FogMaterial], color correction LUTs for [Environment], vector fields for [GPUParticlesAttractorVectorField3D] and collision maps for [GPUParticlesCollisionSDF3D]. 3D textures can also be used in custom shaders.
</description>
<tutorials>
</tutorials>
@@ -16,12 +19,14 @@
<param index="4" name="use_mipmaps" type="bool" />
<param index="5" name="data" type="Image[]" />
<description>
+ Creates the [ImageTexture3D] with specified [param width], [param height], and [param depth]. See [enum Image.Format] for [param format] options. If [param use_mipmaps] is [code]true[/code], then generate mipmaps for the [ImageTexture3D].
</description>
</method>
<method name="update">
<return type="void" />
<param index="0" name="data" type="Image[]" />
<description>
+ Replaces the texture's existing data with the layers specified in [code]data[/code]. The size of [code]data[/code] must match the parameters that were used for [method create]. In other words, the texture cannot be resized or have its format changed by calling [method update].
</description>
</method>
</methods>
diff --git a/doc/classes/ImageTextureLayered.xml b/doc/classes/ImageTextureLayered.xml
index f5786f070a..0aa1d65d5a 100644
--- a/doc/classes/ImageTextureLayered.xml
+++ b/doc/classes/ImageTextureLayered.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ImageTextureLayered" inherits="TextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Base class for texture types which contain the data of multiple [ImageTexture]s. Each image is of the same size and format.
</brief_description>
<description>
+ Base class for [Texture2DArray], [Cubemap] and [CubemapArray]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types. See also [Texture3D].
</description>
<tutorials>
</tutorials>
@@ -11,7 +13,7 @@
<return type="int" enum="Error" />
<param index="0" name="images" type="Image[]" />
<description>
- Creates an [ImageTextureLayered] from an array of [Image]s. The first image decides the width, height, image format and mipmapping setting. The other images must have the same width, height, image format and mipmapping setting.
+ Creates an [ImageTextureLayered] from an array of [Image]s. See [method Image.create] for the expected data format. The first image decides the width, height, image format and mipmapping setting. The other images [i]must[/i] have the same width, height, image format and mipmapping setting.
Each [Image] represents one [code]layer[/code].
</description>
</method>
@@ -23,7 +25,7 @@
Replaces the existing [Image] data at the given [code]layer[/code] with this new image.
The given [Image] must have the same width, height, image format and mipmapping setting (a [code]bool[/code] value) as the rest of the referenced images.
If the image format is unsupported, it will be decompressed and converted to a similar and supported [enum Image.Format].
- The update is immediate: synced with the draw.
+ The update is immediate: it's synchronized with drawing.
</description>
</method>
</methods>
diff --git a/doc/classes/MissingNode.xml b/doc/classes/MissingNode.xml
index b5aa02cfd6..ac54329313 100644
--- a/doc/classes/MissingNode.xml
+++ b/doc/classes/MissingNode.xml
@@ -4,7 +4,7 @@
This is an internal editor class intended for keeping data of nodes of unknown type.
</brief_description>
<description>
- This is an internal editor class intended for keeping data of nodes of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can´t be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
+ This is an internal editor class intended for keeping data of nodes of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can't be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/MissingResource.xml b/doc/classes/MissingResource.xml
index eede6350d8..e5a6c4d064 100644
--- a/doc/classes/MissingResource.xml
+++ b/doc/classes/MissingResource.xml
@@ -4,7 +4,7 @@
This is an internal editor class intended for keeping data of resources of unknown type.
</brief_description>
<description>
- This is an internal editor class intended for keeping data of resources of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can´t be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
+ This is an internal editor class intended for keeping data of resources of unknown type (most likely this type was supplied by an extension that is no longer loaded). It can't be manually instantiated or placed in the scene. Ignore it if you don't know what it is.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index b83bff5d5e..21fb9d139c 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -606,7 +606,7 @@
<return type="void" />
<param index="0" name="group" type="StringName" />
<description>
- Removes a node from a group. See notes in the description, and the group methods in [SceneTree].
+ Removes a node from the [param group]. Does nothing if the node is not in the [param group]. See notes in the description, and the group methods in [SceneTree].
</description>
</method>
<method name="replace_by">
@@ -991,7 +991,7 @@
<constant name="DUPLICATE_SCRIPTS" value="4" enum="DuplicateFlags">
Duplicate the node's scripts.
</constant>
- <constant name="DUPLICATE_USE_INSTANCING" value="8" enum="DuplicateFlags">
+ <constant name="DUPLICATE_USE_INSTANTIATION" value="8" enum="DuplicateFlags">
Duplicate using instancing.
An instance stays linked to the original so when the original changes, the instance changes too.
</constant>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index f4a5288481..ea9b83d2aa 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -467,7 +467,7 @@
<return type="bool" />
<param index="0" name="tag_name" type="String" />
<description>
- Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=$DOCS_URL/getting_started/workflow/export/feature_tags.html]Feature Tags[/url] documentation for more details.
+ Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=$DOCS_URL/tutorials/export/feature_tags.html]Feature Tags[/url] documentation for more details.
[b]Note:[/b] Tag names are case-sensitive.
</description>
</method>
diff --git a/doc/classes/OfflineMultiplayerPeer.xml b/doc/classes/OfflineMultiplayerPeer.xml
new file mode 100644
index 0000000000..5e15992d54
--- /dev/null
+++ b/doc/classes/OfflineMultiplayerPeer.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="OfflineMultiplayerPeer" inherits="MultiplayerPeer" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ A [MultiplayerPeer] which is always connected and acts as a server.
+ </brief_description>
+ <description>
+ This is the default [member MultiplayerAPI.multiplayer_peer] for the [member Node.multiplayer]. It mimics the behavior of a server with no peers connected.
+ This means that the [SceneTree] will act as the multiplayer authority by default. Calls to [method MultiplayerAPI.is_server] will return [code]true[/code], and calls to [method MultiplayerAPI.get_unique_id] will return [constant MultiplayerPeer.TARGET_PEER_SERVER].
+ </description>
+ <tutorials>
+ </tutorials>
+</class>
diff --git a/doc/classes/PathFollow3D.xml b/doc/classes/PathFollow3D.xml
index ba7207be8f..fa7580b7b6 100644
--- a/doc/classes/PathFollow3D.xml
+++ b/doc/classes/PathFollow3D.xml
@@ -9,6 +9,16 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="correct_posture" qualifiers="static">
+ <return type="Transform3D" />
+ <param index="0" name="transform" type="Transform3D" />
+ <param index="1" name="rotation_mode" type="int" enum="PathFollow3D.RotationMode" />
+ <description>
+ Correct the [code]transform[/code]. [code]rotation_mode[/code] implicitly specifies how posture (forward, up and sideway direction) is caculated.
+ </description>
+ </method>
+ </methods>
<members>
<member name="cubic_interp" type="bool" setter="set_cubic_interpolation" getter="get_cubic_interpolation" default="true">
If [code]true[/code], the position between two cached points is interpolated cubically, and linearly otherwise.
@@ -30,6 +40,9 @@
<member name="rotation_mode" type="int" setter="set_rotation_mode" getter="get_rotation_mode" enum="PathFollow3D.RotationMode" default="3">
Allows or forbids rotation on one or more axes, depending on the [enum RotationMode] constants being used.
</member>
+ <member name="tilt_enabled" type="bool" setter="set_tilt_enabled" getter="is_tilt_enabled" default="true">
+ If [code]true[/code], the tilt property of [Curve3D] takes effect.
+ </member>
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The node's offset perpendicular to the curve.
</member>
diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml
index 59660b4de5..30fa54d669 100644
--- a/doc/classes/PhysicsBody2D.xml
+++ b/doc/classes/PhysicsBody2D.xml
@@ -25,12 +25,12 @@
</method>
<method name="move_and_collide">
<return type="KinematicCollision2D" />
- <param index="0" name="distance" type="Vector2" />
+ <param index="0" name="motion" type="Vector2" />
<param index="1" name="test_only" type="bool" default="false" />
<param index="2" name="safe_margin" type="float" default="0.08" />
<param index="3" name="recovery_as_collision" type="bool" default="false" />
<description>
- Moves the body along the vector [param distance]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
+ Moves the body along the vector [param motion]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
Returns a [KinematicCollision2D], which contains information about the collision when stopped, or when touching another body along the motion.
If [param test_only] is [code]true[/code], the body does not move but the would-be collision information is given.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody2D.safe_margin] for more details).
@@ -47,13 +47,13 @@
<method name="test_move">
<return type="bool" />
<param index="0" name="from" type="Transform2D" />
- <param index="1" name="distance" type="Vector2" />
+ <param index="1" name="motion" type="Vector2" />
<param index="2" name="collision" type="KinematicCollision2D" default="null" />
<param index="3" name="safe_margin" type="float" default="0.08" />
<param index="4" name="recovery_as_collision" type="bool" default="false" />
<description>
- Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
- Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [param distance]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
+ Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
+ Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [param motion]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
[param collision] is an optional object of type [KinematicCollision2D], which contains additional information about the collision when stopped, or when touching another body along the motion.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody2D.safe_margin] for more details).
If [param recovery_as_collision] is [code]true[/code], any depenetration from the recovery phase is also reported as a collision; this is useful for checking whether the body would [i]touch[/i] any other bodies.
diff --git a/doc/classes/PhysicsBody3D.xml b/doc/classes/PhysicsBody3D.xml
index bf7882a1ea..2ef54683f2 100644
--- a/doc/classes/PhysicsBody3D.xml
+++ b/doc/classes/PhysicsBody3D.xml
@@ -32,13 +32,13 @@
</method>
<method name="move_and_collide">
<return type="KinematicCollision3D" />
- <param index="0" name="distance" type="Vector3" />
+ <param index="0" name="motion" type="Vector3" />
<param index="1" name="test_only" type="bool" default="false" />
<param index="2" name="safe_margin" type="float" default="0.001" />
<param index="3" name="recovery_as_collision" type="bool" default="false" />
<param index="4" name="max_collisions" type="int" default="1" />
<description>
- Moves the body along the vector [param distance]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
+ Moves the body along the vector [param motion]. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
The body will stop if it collides. Returns a [KinematicCollision3D], which contains information about the collision when stopped, or when touching another body along the motion.
If [param test_only] is [code]true[/code], the body does not move but the would-be collision information is given.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody3D.safe_margin] for more details).
@@ -64,14 +64,14 @@
<method name="test_move">
<return type="bool" />
<param index="0" name="from" type="Transform3D" />
- <param index="1" name="distance" type="Vector3" />
+ <param index="1" name="motion" type="Vector3" />
<param index="2" name="collision" type="KinematicCollision3D" default="null" />
<param index="3" name="safe_margin" type="float" default="0.001" />
<param index="4" name="recovery_as_collision" type="bool" default="false" />
<param index="5" name="max_collisions" type="int" default="1" />
<description>
- Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param distance] should be computed using [code]delta[/code].
- Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [param distance]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
+ Checks for collisions without moving the body. In order to be frame rate independent in [method Node._physics_process] or [method Node._process], [param motion] should be computed using [code]delta[/code].
+ Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [param motion]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
[param collision] is an optional object of type [KinematicCollision3D], which contains additional information about the collision when stopped, or when touching another body along the motion.
[param safe_margin] is the extra margin used for collision recovery (see [member CharacterBody3D.safe_margin] for more details).
If [param recovery_as_collision] is [code]true[/code], any depenetration from the recovery phase is also reported as a collision; this is useful for checking whether the body would [i]touch[/i] any other bodies.
diff --git a/doc/classes/PlaceholderCubemap.xml b/doc/classes/PlaceholderCubemap.xml
index 3617c6ac2c..0892b023a2 100644
--- a/doc/classes/PlaceholderCubemap.xml
+++ b/doc/classes/PlaceholderCubemap.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderCubemap" inherits="PlaceholderTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a cubemap texture.
</brief_description>
<description>
+ This class is used when loading a project that uses a [Cubemap] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PlaceholderCubemapArray.xml b/doc/classes/PlaceholderCubemapArray.xml
index 1fcf1e7795..c7a7e9154c 100644
--- a/doc/classes/PlaceholderCubemapArray.xml
+++ b/doc/classes/PlaceholderCubemapArray.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderCubemapArray" inherits="PlaceholderTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a cubemap texture array.
</brief_description>
<description>
+ This class is used when loading a project that uses a [CubemapArray] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PlaceholderMaterial.xml b/doc/classes/PlaceholderMaterial.xml
index c66641d81c..7febdc7a07 100644
--- a/doc/classes/PlaceholderMaterial.xml
+++ b/doc/classes/PlaceholderMaterial.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderMaterial" inherits="Material" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a material.
</brief_description>
<description>
+ This class is used when loading a project that uses a [Material] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PlaceholderMesh.xml b/doc/classes/PlaceholderMesh.xml
index cc688816b6..8021a57878 100644
--- a/doc/classes/PlaceholderMesh.xml
+++ b/doc/classes/PlaceholderMesh.xml
@@ -1,13 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderMesh" inherits="Mesh" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a mesh.
</brief_description>
<description>
+ This class is used when loading a project that uses a [Mesh] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
<members>
<member name="aabb" type="AABB" setter="set_aabb" getter="get_aabb" default="AABB(0, 0, 0, 0, 0, 0)">
+ The smallest [AABB] enclosing this mesh in local space.
</member>
</members>
</class>
diff --git a/doc/classes/PlaceholderTexture2D.xml b/doc/classes/PlaceholderTexture2D.xml
index 5d8509ec77..c889055e4d 100644
--- a/doc/classes/PlaceholderTexture2D.xml
+++ b/doc/classes/PlaceholderTexture2D.xml
@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a 2-dimensional texture.
</brief_description>
<description>
+ This class is used when loading a project that uses a [Texture2D] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
<members>
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(1, 1)">
+ The texture's size (in pixels).
</member>
</members>
</class>
diff --git a/doc/classes/PlaceholderTexture2DArray.xml b/doc/classes/PlaceholderTexture2DArray.xml
index a502e5d334..a749e8c039 100644
--- a/doc/classes/PlaceholderTexture2DArray.xml
+++ b/doc/classes/PlaceholderTexture2DArray.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderTexture2DArray" inherits="PlaceholderTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a 2-dimensional texture array.
</brief_description>
<description>
+ This class is used when loading a project that uses a [Texture2D] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PlaceholderTexture3D.xml b/doc/classes/PlaceholderTexture3D.xml
index d31e538307..ccd3c94fc2 100644
--- a/doc/classes/PlaceholderTexture3D.xml
+++ b/doc/classes/PlaceholderTexture3D.xml
@@ -1,13 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderTexture3D" inherits="Texture3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a 3-dimensional texture.
</brief_description>
<description>
+ This class is used when loading a project that uses a [Texture3D] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
<members>
<member name="size" type="Vector3i" setter="set_size" getter="get_size" default="Vector3i(1, 1, 1)">
+ The texture's size (in pixels).
</member>
</members>
</class>
diff --git a/doc/classes/PlaceholderTextureLayered.xml b/doc/classes/PlaceholderTextureLayered.xml
index 39af08473a..8cc6dd606a 100644
--- a/doc/classes/PlaceholderTextureLayered.xml
+++ b/doc/classes/PlaceholderTextureLayered.xml
@@ -1,15 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PlaceholderTextureLayered" inherits="TextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Placeholder class for a 2-dimensional texture array.
</brief_description>
<description>
+ This class is used when loading a project that uses a [TextureLayered] subclass in 2 conditions:
+ - When running the project exported in dedicated server mode, only the texture's dimensions are kept (as they may be relied upon for gameplay purposes or positioning of other elements). This allows reducing the exported PCK's size significantly.
+ - When this subclass is missing due to using a different engine version or build (e.g. modules disabled).
</description>
<tutorials>
</tutorials>
<members>
<member name="layers" type="int" setter="set_layers" getter="get_layers" default="1">
+ The number of layers in the texture array.
</member>
<member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i(1, 1)">
+ The size of each texture layer (in pixels).
</member>
</members>
</class>
diff --git a/doc/classes/PortableCompressedTexture2D.xml b/doc/classes/PortableCompressedTexture2D.xml
index b64cda6df5..693eaafad3 100644
--- a/doc/classes/PortableCompressedTexture2D.xml
+++ b/doc/classes/PortableCompressedTexture2D.xml
@@ -21,7 +21,7 @@
<param index="3" name="lossy_quality" type="float" default="0.8" />
<description>
Initializes the compressed texture from a base image. The compression mode must be provided.
- If this image will be used as a normal map, the "normal map" flag is recommended, to ensure optimum quality.
+ [param normal_map] is recommended to ensure optimum quality if this image will be used as a normal map.
If lossy compression is requested, the quality setting can optionally be provided. This maps to Lossy WebP compression quality.
</description>
</method>
diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml
index 7a411b27ac..b1c8907d8e 100644
--- a/doc/classes/PrimitiveMesh.xml
+++ b/doc/classes/PrimitiveMesh.xml
@@ -34,6 +34,9 @@
</method>
</methods>
<members>
+ <member name="add_uv2" type="bool" setter="set_add_uv2" getter="get_add_uv2" default="false">
+ If set, generates UV2 UV coordinates applying a padding using the [member uv2_padding] setting. UV2 is needed for lightmapping.
+ </member>
<member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB(0, 0, 0, 0, 0, 0)">
Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices.
</member>
@@ -44,5 +47,8 @@
<member name="material" type="Material" setter="set_material" getter="get_material">
The current [Material] of the primitive mesh.
</member>
+ <member name="uv2_padding" type="float" setter="set_uv2_padding" getter="get_uv2_padding" default="2.0">
+ If [member add_uv2] is set, specifies the padding in pixels applied along seams of the mesh. If at generation the size of the lightmap texture can't be determined, the UVs are calculated assuming a texture size of 1024x1024.
+ </member>
</members>
</class>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 4699131c41..3478215f4f 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -208,7 +208,7 @@
If [code]true[/code], applies linear filtering when scaling the image (recommended for high-resolution artwork). If [code]false[/code], uses nearest-neighbor interpolation (recommended for pixel art).
</member>
<member name="application/config/custom_user_dir_name" type="String" setter="" getter="" default="&quot;&quot;">
- This user directory is used for storing persistent data ([code]user://[/code] filesystem). If left empty, [code]user://[/code] resolves to a project-specific folder in Godot's own configuration folder (see [method OS.get_user_data_dir]). If a custom directory name is defined, this name will be used instead and appended to the system-specific user data directory (same parent folder as the Godot configuration folder documented in [method OS.get_user_data_dir]).
+ This user directory is used for storing persistent data ([code]user://[/code] filesystem). If a custom directory name is defined, this name will be appended to the system-specific user data directory (same parent folder as the Godot configuration folder documented in [method OS.get_user_data_dir]).
The [member application/config/use_custom_user_dir] setting must be enabled for this to take effect.
</member>
<member name="application/config/description" type="String" setter="" getter="" default="&quot;&quot;">
@@ -235,7 +235,8 @@
[b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings.
</member>
<member name="application/config/use_custom_user_dir" type="bool" setter="" getter="" default="false">
- If [code]true[/code], the project will save user data to its own user directory (see [member application/config/custom_user_dir_name]). This setting is only effective on desktop platforms. A name must be set in the [member application/config/custom_user_dir_name] setting for this to take effect. If [code]false[/code], the project will save user data to [code](OS user data directory)/Godot/app_userdata/(project name)[/code].
+ If [code]true[/code], the project will save user data to its own user directory. If [member application/config/custom_user_dir_name] is empty, [code]&lt;OS user data directory&gt;/&lt;project name&gt;[/code] directory will be used. If [code]false[/code], the project will save user data to [code]&lt;OS user data directory&gt;/Godot/app_userdata/&lt;project name&gt;[/code].
+ See also [url=$DOCS_URL/tutorials/io/data_paths.html#accessing-persistent-user-data-user]File paths in Godot projects[/url]. This setting is only effective on desktop platforms.
</member>
<member name="application/config/use_hidden_project_data_directory" type="bool" setter="" getter="" default="true">
If [code]true[/code], the project will use a hidden directory ([code].godot[/code]) for storing project-specific data (metadata, shader cache, etc.).
@@ -317,11 +318,13 @@
<member name="audio/driver/output_latency.web" type="int" setter="" getter="" default="50">
Safer override for [member audio/driver/output_latency] in the Web platform, to avoid audio issues especially on mobile devices.
</member>
- <member name="audio/general/2d_panning_strength" type="float" setter="" getter="" default="1.0">
- The base strength of the panning effect for all AudioStreamPlayer2D nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer2D.panning_strength].
+ <member name="audio/general/2d_panning_strength" type="float" setter="" getter="" default="0.5">
+ The base strength of the panning effect for all [AudioStreamPlayer2D] nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer2D.panning_strength]. A value of [code]0.0[/code] disables stereo panning entirely, leaving only volume attenuation in place. A value of [code]1.0[/code] completely mutes one of the channels if the sound is located exactly to the left (or right) of the listener.
+ The default value of [code]0.5[/code] is tuned for headphones. When using speakers, you may find lower values to sound better as speakers have a lower stereo separation compared to headphones.
</member>
- <member name="audio/general/3d_panning_strength" type="float" setter="" getter="" default="1.0">
- The base strength of the panning effect for all AudioStreamPlayer3D nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer3D.panning_strength].
+ <member name="audio/general/3d_panning_strength" type="float" setter="" getter="" default="0.5">
+ The base strength of the panning effect for all [AudioStreamPlayer3D] nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer3D.panning_strength]. A value of [code]0.0[/code] disables stereo panning entirely, leaving only volume attenuation in place. A value of [code]1.0[/code] completely mutes one of the channels if the sound is located exactly to the left (or right) of the listener.
+ The default value of [code]0.5[/code] is tuned for headphones. When using speakers, you may find lower values to sound better as speakers have a lower stereo separation compared to headphones.
</member>
<member name="audio/video/video_delay_compensation_ms" type="int" setter="" getter="" default="0">
Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing.
@@ -555,7 +558,7 @@
Position offset for tooltips, relative to the mouse cursor's hotspot.
</member>
<member name="display/window/dpi/allow_hidpi" type="bool" setter="" getter="" default="true">
- If [code]true[/code], allows HiDPI display on Windows, macOS, Android, iOS and Web. If [code]false[/code], the platform's low-DPI fallback will be used on HiDPI displays, which causes the window to be displayed in a blurry or pixelated manner (and can cause various window management bugs). Therefore, it is recommended to make your project scale to [url=$DOCS_URL/tutorials/viewports/multiple_resolutions.html]multiple resolutions[/url] instead of disabling this setting.
+ If [code]true[/code], allows HiDPI display on Windows, macOS, Android, iOS and Web. If [code]false[/code], the platform's low-DPI fallback will be used on HiDPI displays, which causes the window to be displayed in a blurry or pixelated manner (and can cause various window management bugs). Therefore, it is recommended to make your project scale to [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] instead of disabling this setting.
[b]Note:[/b] This setting has no effect on Linux as DPI-awareness fallbacks are not supported there.
</member>
<member name="display/window/energy_saving/keep_screen_on" type="bool" setter="" getter="" default="true">
@@ -1811,6 +1814,10 @@
<member name="physics/common/enable_object_picking" type="bool" setter="" getter="" default="true">
Enables [member Viewport.physics_object_picking] on the root viewport.
</member>
+ <member name="physics/common/max_physics_steps_per_frame" type="int" setter="" getter="" default="8">
+ Controls the maximum number of physics steps that can be simulated each rendered frame. The default value is tuned to avoid "spiral of death" situations where expensive physics simulations trigger more expensive simulations indefinitely. However, the game will appear to slow down if the rendering FPS is less than [code]1 / max_physics_steps_per_frame[/code] of [member physics/common/physics_ticks_per_second]. This occurs even if [code]delta[/code] is consistently used in physics calculations. To avoid this, increase [member physics/common/max_physics_steps_per_frame] if you have increased [member physics/common/physics_ticks_per_second] significantly above its default value.
+ [b]Note:[/b] This property is only read when the project starts. To change the maximum number of simulated physics steps per frame at runtime, set [member Engine.max_physics_steps_per_frame] instead.
+ </member>
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5">
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
[b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics/common/physics_jitter_fix] to [code]0[/code].
@@ -1819,7 +1826,7 @@
<member name="physics/common/physics_ticks_per_second" type="int" setter="" getter="" default="60">
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. See also [member application/run/max_fps].
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_ticks_per_second] instead.
- [b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member physics/common/physics_ticks_per_second] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS.
+ [b]Note:[/b] Only [member physics/common/max_physics_steps_per_frame] physics ticks may be simulated per rendered frame at most. If more physics ticks have to be simulated per rendered frame to keep up with rendering, the project will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended to also increase [member physics/common/max_physics_steps_per_frame] if increasing [member physics/common/physics_ticks_per_second] significantly above its default value.
</member>
<member name="rendering/2d/sdf/oversize" type="int" setter="" getter="" default="1">
</member>
@@ -2016,6 +2023,9 @@
<member name="rendering/lightmapping/bake_quality/ultra_quality_ray_count" type="int" setter="" getter="" default="1024">
The number of rays to use for baking lightmaps with [LightmapGI] when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_ULTRA].
</member>
+ <member name="rendering/lightmapping/primitive_meshes/texel_size" type="float" setter="" getter="" default="0.2">
+ The texel_size that is used to calculate the [member Mesh.lightmap_size_hint] on [PrimitiveMesh] resources if [member PrimitiveMesh.add_uv2] is enabled.
+ </member>
<member name="rendering/lightmapping/probe_capture/update_speed" type="float" setter="" getter="" default="15">
The framerate-independent update speed when representing dynamic object lighting from [LightmapProbe]s. Higher values make dynamic object lighting update faster. Higher values can prevent fast-moving objects from having "outdated" indirect lighting displayed on them, at the cost of possible flickering when an object moves from a bright area to a shaded area.
</member>
@@ -2226,9 +2236,6 @@
<member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
</member>
- <member name="rendering/textures/lossless_compression/webp_compression_level" type="int" setter="" getter="" default="2">
- The default compression level for lossless WebP. Higher levels result in smaller files at the cost of compression speed. Decompression speed is mostly unaffected by the compression level. Supported values are 0 to 9. Note that compression levels above 6 are very slow and offer very little savings.
- </member>
<member name="rendering/textures/vram_compression/import_bptc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the Vulkan renderer.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
@@ -2245,6 +2252,12 @@
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
+ <member name="rendering/textures/webp_compression/compression_method" type="int" setter="" getter="" default="2">
+ The default compression method for WebP. Affects both lossy and lossless WebP. A higher value results in smaller files at the cost of compression speed. Decompression speed is mostly unaffected by the compression method. Supported values are 0 to 6. Note that compression methods above 4 are very slow and offer very little savings.
+ </member>
+ <member name="rendering/textures/webp_compression/lossless_compression_factor" type="float" setter="" getter="" default="25">
+ The default compression factor for lossless WebP. Decompression speed is mostly unaffected by the compression factor. Supported values are 0 to 100.
+ </member>
<member name="rendering/transparent_background" type="bool" setter="" getter="" default="false">
If [code]true[/code], enables [member Viewport.transparent_bg] on the root viewport. This allows per-pixel transparency to be effective after also enabling [member display/window/size/transparent] and [member display/window/per_pixel_transparency/allowed].
</member>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 13e5470a56..2ffa4dc50b 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -838,6 +838,8 @@
<method name="create_local_rendering_device" qualifiers="const">
<return type="RenderingDevice" />
<description>
+ Creates a RenderingDevice that can be used to do draw and compute operations on a separate thread. Cannot draw to the screen nor share data with the global RenderingDevice.
+ [b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code].
</description>
</method>
<method name="decal_create">
@@ -1273,6 +1275,8 @@
<method name="get_rendering_device" qualifiers="const">
<return type="RenderingDevice" />
<description>
+ Returns the global RenderingDevice.
+ [b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code].
</description>
</method>
<method name="get_rendering_info">
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index b0b4f74b46..53040b2753 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -80,7 +80,7 @@
<method name="c_unescape" qualifiers="const">
<return type="String" />
<description>
- Returns a copy of the string with escaped characters replaced by their meanings. Supported escape sequences are [code]\'[/code], [code]\"[/code], [code]\?[/code], [code]\\[/code], [code]\a[/code], [code]\b[/code], [code]\f[/code], [code]\n[/code], [code]\r[/code], [code]\t[/code], [code]\v[/code].
+ Returns a copy of the string with escaped characters replaced by their meanings. Supported escape sequences are [code]\'[/code], [code]\"[/code], [code]\\[/code], [code]\a[/code], [code]\b[/code], [code]\f[/code], [code]\n[/code], [code]\r[/code], [code]\t[/code], [code]\v[/code].
[b]Note:[/b] Unlike the GDScript parser, this method doesn't support the [code]\uXXXX[/code] escape sequence.
</description>
</method>
@@ -738,7 +738,7 @@
</description>
</method>
<method name="split_floats" qualifiers="const">
- <return type="PackedFloat32Array" />
+ <return type="PackedFloat64Array" />
<param index="0" name="delimiter" type="String" />
<param index="1" name="allow_empty" type="bool" default="true" />
<description>
diff --git a/doc/classes/Texture.xml b/doc/classes/Texture.xml
index df6e0433dc..86c9026fd1 100644
--- a/doc/classes/Texture.xml
+++ b/doc/classes/Texture.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Texture" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Base class for all texture types.
</brief_description>
<description>
+ [Texture] is the base class for all texture types. Common texture types are [Texture2D] and [ImageTexture]. See also [Image].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Texture2D.xml b/doc/classes/Texture2D.xml
index 3dd8c339b2..aac197090a 100644
--- a/doc/classes/Texture2D.xml
+++ b/doc/classes/Texture2D.xml
@@ -19,6 +19,8 @@
<param index="2" name="modulate" type="Color" />
<param index="3" name="transpose" type="bool" />
<description>
+ Called when the entire [Texture2D] is requested to be drawn over a [CanvasItem], with the top-left offset specified in [param pos]. [param modulate] specifies a multiplier for the colors being drawn, while [param transpose] specifies whether drawing should be performed in column-major order instead of row-major order (resulting in 90-degree clockwise rotation).
+ [b]Note:[/b] This is only used in 2D rendering, not 3D.
</description>
</method>
<method name="_draw_rect" qualifiers="virtual const">
@@ -29,6 +31,8 @@
<param index="3" name="modulate" type="Color" />
<param index="4" name="transpose" type="bool" />
<description>
+ Called when the [Texture2D] is requested to be drawn onto [CanvasItem]'s specified [param rect]. [param modulate] specifies a multiplier for the colors being drawn, while [param transpose] specifies whether drawing should be performed in column-major order instead of row-major order (resulting in 90-degree clockwise rotation).
+ [b]Note:[/b] This is only used in 2D rendering, not 3D.
</description>
</method>
<method name="_draw_rect_region" qualifiers="virtual const">
@@ -40,21 +44,26 @@
<param index="4" name="transpose" type="bool" />
<param index="5" name="clip_uv" type="bool" />
<description>
+ Called when a part of the [Texture2D] specified by [param src_rect]'s coordinates is requested to be drawn onto [CanvasItem]'s specified [param rect]. [param modulate] specifies a multiplier for the colors being drawn, while [param transpose] specifies whether drawing should be performed in column-major order instead of row-major order (resulting in 90-degree clockwise rotation).
+ [b]Note:[/b] This is only used in 2D rendering, not 3D.
</description>
</method>
<method name="_get_height" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the [Texture2D]'s height is queried.
</description>
</method>
<method name="_get_width" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the [Texture2D]'s width is queried.
</description>
</method>
<method name="_has_alpha" qualifiers="virtual const">
<return type="bool" />
<description>
+ Called when the presence of an alpha channel in the [Texture2D] is queried.
</description>
</method>
<method name="_is_pixel_opaque" qualifiers="virtual const">
@@ -62,6 +71,7 @@
<param index="0" name="x" type="int" />
<param index="1" name="y" type="int" />
<description>
+ Called when a pixel's opaque state in the [Texture2D] is queried at the specified [code](x, y)[/code] position.
</description>
</method>
<method name="draw" qualifiers="const">
@@ -100,7 +110,7 @@
<method name="get_height" qualifiers="const">
<return type="int" />
<description>
- Returns the texture height.
+ Returns the texture height in pixels.
</description>
</method>
<method name="get_image" qualifiers="const">
@@ -113,13 +123,13 @@
<method name="get_size" qualifiers="const">
<return type="Vector2" />
<description>
- Returns the texture size.
+ Returns the texture size in pixels.
</description>
</method>
<method name="get_width" qualifiers="const">
<return type="int" />
<description>
- Returns the texture width.
+ Returns the texture width in pixels.
</description>
</method>
<method name="has_alpha" qualifiers="const">
diff --git a/doc/classes/Texture2DArray.xml b/doc/classes/Texture2DArray.xml
index 113f37f974..ec00198db1 100644
--- a/doc/classes/Texture2DArray.xml
+++ b/doc/classes/Texture2DArray.xml
@@ -4,8 +4,9 @@
A single texture resource which consists of multiple, separate images. Each image has the same dimensions and number of mipmap levels.
</brief_description>
<description>
- A Texture2DArray is different from a Texture3D: The Texture2DArray does not support trilinear interpolation between the [Image]s, i.e. no blending.
+ A Texture2DArray is different from a Texture3D: The Texture2DArray does not support trilinear interpolation between the [Image]s, i.e. no blending. See also [Cubemap] and [CubemapArray], which are texture arrays with specialized cubemap functions.
A Texture2DArray is also different from an [AtlasTexture]: In a Texture2DArray, all images are treated separately. In an atlas, the regions (i.e. the single images) can be of different sizes. Furthermore, you usually need to add a padding around the regions, to prevent accidental UV mapping to more than one region. The same goes for mipmapping: Mipmap chains are handled separately for each layer. In an atlas, the slicing has to be done manually in the fragment shader.
+ To create such a texture file yourself, reimport your image files using the Godot Editor import presets.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Texture3D.xml b/doc/classes/Texture3D.xml
index 4968f46fe8..1a66932d62 100644
--- a/doc/classes/Texture3D.xml
+++ b/doc/classes/Texture3D.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Texture3D" inherits="Texture" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ Base class for 3-dimensionnal textures.
</brief_description>
<description>
+ Base class for [ImageTexture3D] and [CompressedTexture3D]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types. [Texture3D] is the base class for all 3-dimensional texture types. See also [TextureLayered].
+ All images need to have the same width, height and number of mipmap levels.
+ To create such a texture file yourself, reimport your image files using the Godot Editor import presets.
</description>
<tutorials>
</tutorials>
@@ -10,61 +14,73 @@
<method name="_get_data" qualifiers="virtual const">
<return type="Image[]" />
<description>
+ Called when the [Texture3D]'s data is queried.
</description>
</method>
<method name="_get_depth" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the [Texture3D]'s depth is queried.
</description>
</method>
<method name="_get_format" qualifiers="virtual const">
<return type="int" enum="Image.Format" />
<description>
+ Called when the [Texture3D]'s format is queried.
</description>
</method>
<method name="_get_height" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the [Texture3D]'s height is queried.
</description>
</method>
<method name="_get_width" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the [Texture3D]'s width is queried.
</description>
</method>
<method name="_has_mipmaps" qualifiers="virtual const">
<return type="bool" />
<description>
+ Called when the presence of mipmaps in the [Texture3D] is queried.
</description>
</method>
<method name="get_data" qualifiers="const">
<return type="Image[]" />
<description>
+ Returns the [Texture3D]'s data as an array of [Image]s. Each [Image] represents a [i]slice[/i] of the [Texture3D], with different slices mapping to different depth (Z axis) levels.
</description>
</method>
<method name="get_depth" qualifiers="const">
<return type="int" />
<description>
+ Returns the [Texture3D]'s depth in pixels. Depth is typically represented by the Z axis (a dimension not present in [Texture2D]).
</description>
</method>
<method name="get_format" qualifiers="const">
<return type="int" enum="Image.Format" />
<description>
+ Returns the current format being used by this texture. See [enum Image.Format] for details.
</description>
</method>
<method name="get_height" qualifiers="const">
<return type="int" />
<description>
+ Returns the [Texture3D]'s height in pixels. Width is typically represented by the Y axis.
</description>
</method>
<method name="get_width" qualifiers="const">
<return type="int" />
<description>
+ Returns the [Texture3D]'s width in pixels. Width is typically represented by the X axis.
</description>
</method>
<method name="has_mipmaps" qualifiers="const">
<return type="bool" />
<description>
+ Returns [code]true[/code] if the [Texture3D] has generated mipmaps.
</description>
</method>
</methods>
diff --git a/doc/classes/TextureButton.xml b/doc/classes/TextureButton.xml
index 043eeb9a80..b185828577 100644
--- a/doc/classes/TextureButton.xml
+++ b/doc/classes/TextureButton.xml
@@ -27,19 +27,19 @@
<member name="texture_click_mask" type="BitMap" setter="set_click_mask" getter="get_click_mask">
Pure black and white [BitMap] image to use for click detection. On the mask, white pixels represent the button's clickable area. Use it to create buttons with curved shapes.
</member>
- <member name="texture_disabled" type="Texture2D" setter="set_disabled_texture" getter="get_disabled_texture">
+ <member name="texture_disabled" type="Texture2D" setter="set_texture_disabled" getter="get_texture_disabled">
Texture to display when the node is disabled. See [member BaseButton.disabled].
</member>
- <member name="texture_focused" type="Texture2D" setter="set_focused_texture" getter="get_focused_texture">
+ <member name="texture_focused" type="Texture2D" setter="set_texture_focused" getter="get_texture_focused">
Texture to display when the node has mouse or keyboard focus. [member texture_focused] is displayed [i]over[/i] the base texture, so a partially transparent texture should be used to ensure the base texture remains visible. A texture that represents an outline or an underline works well for this purpose. To disable the focus visual effect, assign a fully transparent texture of any size. Note that disabling the focus visual effect will harm keyboard/controller navigation usability, so this is not recommended for accessibility reasons.
</member>
- <member name="texture_hover" type="Texture2D" setter="set_hover_texture" getter="get_hover_texture">
+ <member name="texture_hover" type="Texture2D" setter="set_texture_hover" getter="get_texture_hover">
Texture to display when the mouse hovers the node.
</member>
- <member name="texture_normal" type="Texture2D" setter="set_normal_texture" getter="get_normal_texture">
+ <member name="texture_normal" type="Texture2D" setter="set_texture_normal" getter="get_texture_normal">
Texture to display by default, when the node is [b]not[/b] in the disabled, focused, hover or pressed state.
</member>
- <member name="texture_pressed" type="Texture2D" setter="set_pressed_texture" getter="get_pressed_texture">
+ <member name="texture_pressed" type="Texture2D" setter="set_texture_pressed" getter="get_texture_pressed">
Texture to display on mouse down over the node, if the node has keyboard focus and the player presses the Enter key or if the player presses the [member BaseButton.shortcut] key.
</member>
</members>
diff --git a/doc/classes/TextureLayered.xml b/doc/classes/TextureLayered.xml
index 5e6afcbc5c..8f6dff7acf 100644
--- a/doc/classes/TextureLayered.xml
+++ b/doc/classes/TextureLayered.xml
@@ -4,12 +4,11 @@
Base class for texture types which contain the data of multiple [Image]s. Each image is of the same size and format.
</brief_description>
<description>
- Base class for [Texture2DArray], [Cubemap] and [CubemapArray]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types.
+ Base class for [ImageTextureLayered]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types. See also [Texture3D].
Data is set on a per-layer basis. For [Texture2DArray]s, the layer specifies the array layer.
All images need to have the same width, height and number of mipmap levels.
- A [TextureLayered] can be loaded with [code]method ResourceFormatLoader.load[/code].
- To create such a texture file yourself, re-import your image files using the Godot Editor import presets.
- Internally, Godot maps these files to their respective counterparts in the target rendering driver (GLES3, Vulkan).
+ A [TextureLayered] can be loaded with [method ResourceLoader.load].
+ Internally, Godot maps these files to their respective counterparts in the target rendering driver (Vulkan, GLES3).
</description>
<tutorials>
</tutorials>
@@ -17,37 +16,44 @@
<method name="_get_format" qualifiers="virtual const">
<return type="int" enum="Image.Format" />
<description>
+ Called when the [TextureLayered]'s format is queried.
</description>
</method>
<method name="_get_height" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the the [TextureLayered]'s height is queried.
</description>
</method>
<method name="_get_layer_data" qualifiers="virtual const">
<return type="Image" />
<param index="0" name="layer_index" type="int" />
<description>
+ Called when the data for a layer in the [TextureLayered] is queried.
</description>
</method>
<method name="_get_layered_type" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the layers' type in the [TextureLayered] is queried.
</description>
</method>
<method name="_get_layers" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the number of layers in the [TextureLayered] is queried.
</description>
</method>
<method name="_get_width" qualifiers="virtual const">
<return type="int" />
<description>
+ Called when the [TextureLayered]'s width queried.
</description>
</method>
<method name="_has_mipmaps" qualifiers="virtual const">
<return type="bool" />
<description>
+ Called when the presence of mipmaps in the [TextureLayered] is queried.
</description>
</method>
<method name="get_format" qualifiers="const">
@@ -59,7 +65,7 @@
<method name="get_height" qualifiers="const">
<return type="int" />
<description>
- Returns the height of the texture. Height is typically represented by the Y-axis.
+ Returns the height of the texture in pixels. Height is typically represented by the Y axis.
</description>
</method>
<method name="get_layer_data" qualifiers="const">
@@ -72,6 +78,7 @@
<method name="get_layered_type" qualifiers="const">
<return type="int" enum="TextureLayered.LayeredType" />
<description>
+ Returns the [TextureLayered]'s type. The type determines how the data is accessed, with cubemaps having special types.
</description>
</method>
<method name="get_layers" qualifiers="const">
@@ -83,7 +90,7 @@
<method name="get_width" qualifiers="const">
<return type="int" />
<description>
- Returns the width of the texture. Width is typically represented by the X-axis.
+ Returns the width of the texture in pixels. Width is typically represented by the X axis.
</description>
</method>
<method name="has_mipmaps" qualifiers="const">
@@ -95,10 +102,13 @@
</methods>
<constants>
<constant name="LAYERED_TYPE_2D_ARRAY" value="0" enum="LayeredType">
+ Texture is a generic [Texture2DArray].
</constant>
<constant name="LAYERED_TYPE_CUBEMAP" value="1" enum="LayeredType">
+ Texture is a [Cubemap], with each side in its own layer (6 in total).
</constant>
<constant name="LAYERED_TYPE_CUBEMAP_ARRAY" value="2" enum="LayeredType">
+ Texture is a [CubemapArray], with each cubemap being made of 6 layers.
</constant>
</constants>
</class>
diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml
index 314be9adf8..ae2f8d8dff 100644
--- a/doc/classes/Translation.xml
+++ b/doc/classes/Translation.xml
@@ -88,6 +88,12 @@
The number [param n] is the number or quantity of the plural object. It will be used to guide the translation system to fetch the correct plural form for the selected language.
</description>
</method>
+ <method name="get_translated_message_list" qualifiers="const">
+ <return type="PackedStringArray" />
+ <description>
+ Returns all the messages (translated text).
+ </description>
+ </method>
</methods>
<members>
<member name="locale" type="String" setter="set_locale" getter="get_locale" default="&quot;en&quot;">
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 532f6703b2..bf79821e2d 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -293,6 +293,14 @@
Sets language code of column title used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</description>
</method>
+ <method name="set_selected">
+ <return type="void" />
+ <param index="0" name="item" type="TreeItem" />
+ <param index="1" name="column" type="int" />
+ <description>
+ Selects the specified [TreeItem] and column.
+ </description>
+ </method>
</methods>
<members>
<member name="allow_reselect" type="bool" setter="set_allow_reselect" getter="get_allow_reselect" default="false">
diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml
index c6b215daa3..0fe54e947f 100644
--- a/doc/classes/XRInterfaceExtension.xml
+++ b/doc/classes/XRInterfaceExtension.xml
@@ -141,13 +141,6 @@
Returns [code]true[/code] if this interface has been initialized.
</description>
</method>
- <method name="_notification" qualifiers="virtual">
- <return type="void" />
- <param index="0" name="what" type="int" />
- <description>
- Informs the interface of an applicable system notification.
- </description>
- </method>
<method name="_post_draw_viewport" qualifiers="virtual">
<return type="void" />
<param index="0" name="render_target" type="RID" />
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index e3938fb5d5..a196021249 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -28,6 +28,13 @@
</constructor>
<constructor name="float">
<return type="float" />
+ <param index="0" name="from" type="String" />
+ <description>
+ Converts a [String] to a [float], following the same rules as [method String.to_float].
+ </description>
+ </constructor>
+ <constructor name="float">
+ <return type="float" />
<param index="0" name="from" type="bool" />
<description>
Cast a [bool] value to a floating-point value, [code]float(true)[/code] will be equal to 1.0 and [code]float(false)[/code] will be equal to 0.0.
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index 65ab5d4656..93fc8386c6 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -54,6 +54,13 @@
</constructor>
<constructor name="int">
<return type="int" />
+ <param index="0" name="from" type="String" />
+ <description>
+ Converts a [String] to an [int], following the same rules as [method String.to_int].
+ </description>
+ </constructor>
+ <constructor name="int">
+ <return type="int" />
<param index="0" name="from" type="bool" />
<description>
Cast a [bool] value to an integer value, [code]int(true)[/code] will be equals to 1 and [code]int(false)[/code] will be equals to 0.
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 492a438d9b..9fb60511ae 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -29,6 +29,12 @@ MARKUP_ALLOWED_SUBSEQUENT = " -.,:;!?\\/'\")]}>"
# write in this script (check `translate()` uses), and also hardcoded in
# `doc/translations/extract.py` to include them in the source POT file.
BASE_STRINGS = [
+ "All classes",
+ "Globals",
+ "Nodes",
+ "Resources",
+ "Other objects",
+ "Variant types",
"Description",
"Tutorials",
"Properties",
@@ -63,6 +69,19 @@ strings_l10n: Dict[str, str] = {}
STYLES: Dict[str, str] = {}
+CLASS_GROUPS: Dict[str, str] = {
+ "global": "Globals",
+ "node": "Nodes",
+ "resource": "Resources",
+ "object": "Other objects",
+ "variant": "Variant types",
+}
+CLASS_GROUPS_BASE: Dict[str, str] = {
+ "node": "Node",
+ "resource": "Resource",
+ "object": "Object",
+}
+
class State:
def __init__(self) -> None:
@@ -329,7 +348,7 @@ class State:
return cast
def sort_classes(self) -> None:
- self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0]))
+ self.classes = OrderedDict(sorted(self.classes.items(), key=lambda t: t[0].lower()))
class TypeName:
@@ -601,12 +620,25 @@ def main() -> None:
print("Generating the RST class reference...")
+ grouped_classes: Dict[str, List[str]] = {}
+
for class_name, class_def in state.classes.items():
if args.filter and not pattern.search(class_def.filepath):
continue
state.current_class = class_name
make_rst_class(class_def, state, args.dry_run, args.output)
+ group_name = get_class_group(class_def, state)
+
+ if group_name not in grouped_classes:
+ grouped_classes[group_name] = []
+ grouped_classes[group_name].append(class_name)
+
+ print("")
+ print("Generating the index file...")
+
+ make_rst_index(grouped_classes, args.dry_run, args.output)
+
print("")
if state.num_warnings >= 2:
@@ -655,6 +687,42 @@ def translate(string: str) -> str:
return strings_l10n.get(string, string)
+def get_git_branch() -> str:
+ if hasattr(version, "docs") and version.docs != "latest":
+ return version.docs
+
+ return "master"
+
+
+def get_class_group(class_def: ClassDef, state: State) -> str:
+ group_name = "variant"
+ class_name = class_def.name
+
+ if class_name.startswith("@"):
+ group_name = "global"
+ elif class_def.inherits:
+ inherits = class_def.inherits.strip()
+
+ while inherits in state.classes:
+ if inherits == "Node":
+ group_name = "node"
+ break
+ if inherits == "Resource":
+ group_name = "resource"
+ break
+ if inherits == "Object":
+ group_name = "object"
+ break
+
+ inode = state.classes[inherits].inherits
+ if inode:
+ inherits = inode.strip()
+ else:
+ break
+
+ return group_name
+
+
# Generator methods.
@@ -672,10 +740,7 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
# Warn contributors not to edit this file directly.
# Also provide links to the source files for reference.
- git_branch = "master"
- if hasattr(version, "docs") and version.docs != "latest":
- git_branch = version.docs
-
+ git_branch = get_git_branch()
source_xml_path = os.path.relpath(class_def.filepath, root_directory).replace("\\", "/")
source_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/{source_xml_path}"
generator_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/doc/tools/make_rst.py"
@@ -723,15 +788,30 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
f.write(make_type(child, state))
f.write("\n\n")
+ has_description = False
+
# Brief description
- if class_def.brief_description is not None:
+ if class_def.brief_description is not None and class_def.brief_description.strip() != "":
+ has_description = True
+
f.write(f"{format_text_block(class_def.brief_description.strip(), class_def, state)}\n\n")
# Class description
if class_def.description is not None and class_def.description.strip() != "":
+ has_description = True
+
f.write(make_heading("Description", "-"))
f.write(f"{format_text_block(class_def.description.strip(), class_def, state)}\n\n")
+ if not has_description:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this class. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
+
# Online tutorials
if len(class_def.tutorials) > 0:
f.write(make_heading("Tutorials", "-"))
@@ -872,6 +952,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this annotation. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -904,6 +992,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if property_def.text is not None and property_def.text.strip() != "":
f.write(f"{format_text_block(property_def.text.strip(), property_def, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this property. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -925,6 +1021,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this constructor. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -945,6 +1049,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this method. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -967,6 +1079,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if m.description is not None and m.description.strip() != "":
f.write(f"{format_text_block(m.description.strip(), m, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this operator. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -992,6 +1112,14 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
if theme_item_def.text is not None and theme_item_def.text.strip() != "":
f.write(f"{format_text_block(theme_item_def.text.strip(), theme_item_def, state)}\n\n")
+ else:
+ f.write(".. container:: contribute\n\n\t")
+ f.write(
+ translate(
+ "There is currently no description for this theme property. Please help us by :ref:`contributing one <doc_updating_the_class_reference>`!"
+ )
+ + "\n\n"
+ )
index += 1
@@ -1142,6 +1270,53 @@ def make_link(url: str, title: str) -> str:
return f"`{url} <{url}>`__"
+def make_rst_index(grouped_classes: Dict[str, List[str]], dry_run: bool, output_dir: str) -> None:
+
+ if dry_run:
+ f = open(os.devnull, "w", encoding="utf-8")
+ else:
+ f = open(os.path.join(output_dir, "index.rst"), "w", encoding="utf-8")
+
+ # Remove the "Edit on Github" button from the online docs page.
+ f.write(":github_url: hide\n\n")
+
+ # Warn contributors not to edit this file directly.
+ # Also provide links to the source files for reference.
+
+ git_branch = get_git_branch()
+ generator_github_url = f"https://github.com/godotengine/godot/tree/{git_branch}/doc/tools/make_rst.py"
+
+ f.write(".. DO NOT EDIT THIS FILE!!!\n")
+ f.write(".. Generated automatically from Godot engine sources.\n")
+ f.write(f".. Generator: {generator_github_url}.\n\n")
+
+ f.write(".. _doc_class_reference:\n\n")
+
+ main_title = translate("All classes")
+ f.write(f"{main_title}\n")
+ f.write(f"{'=' * len(main_title)}\n\n")
+
+ for group_name in CLASS_GROUPS:
+ if group_name in grouped_classes:
+ group_title = translate(CLASS_GROUPS[group_name])
+
+ f.write(f"{group_title}\n")
+ f.write(f"{'=' * len(group_title)}\n\n")
+
+ f.write(".. toctree::\n")
+ f.write(" :maxdepth: 1\n")
+ f.write(f" :name: toc-class-ref-{group_name}s\n")
+ f.write("\n")
+
+ if group_name in CLASS_GROUPS_BASE:
+ f.write(f" class_{CLASS_GROUPS_BASE[group_name].lower()}\n")
+
+ for class_name in grouped_classes[group_name]:
+ f.write(f" class_{class_name.lower()}\n")
+
+ f.write("\n")
+
+
# Formatting helpers.
diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub
index 7e8bd22960..2204c486c6 100644
--- a/drivers/gl_context/SCsub
+++ b/drivers/gl_context/SCsub
@@ -6,7 +6,7 @@ if env["platform"] in ["haiku", "macos", "windows", "linuxbsd"]:
# Thirdparty source files
thirdparty_dir = "#thirdparty/glad/"
thirdparty_sources = [
- "glad.c",
+ "gl.c",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp
index 3acbcf6b53..b552b52cd5 100644
--- a/drivers/gles3/effects/copy_effects.cpp
+++ b/drivers/gles3/effects/copy_effects.cpp
@@ -115,13 +115,21 @@ CopyEffects::~CopyEffects() {
}
void CopyEffects::copy_to_rect(const Rect2 &p_rect) {
- copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
+ bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
+ if (!success) {
+ return;
+ }
+
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
draw_screen_quad();
}
void CopyEffects::copy_screen() {
- copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
+ bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
+ if (!success) {
+ return;
+ }
+
draw_screen_triangle();
}
@@ -151,7 +159,11 @@ void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, con
}
void CopyEffects::set_color(const Color &p_color, const Rect2i &p_region) {
- copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
+ bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
+ if (!success) {
+ return;
+ }
+
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_region.position.x, p_region.position.y, p_region.size.x, p_region.size.y, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
copy.shader.version_set_uniform(CopyShaderGLES3::COLOR_IN, p_color, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
draw_screen_quad();
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 0a64cda787..0c102bfc1d 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -41,6 +41,7 @@
#include "storage/config.h"
#include "storage/material_storage.h"
#include "storage/mesh_storage.h"
+#include "storage/particles_storage.h"
#include "storage/texture_storage.h"
void RasterizerCanvasGLES3::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -578,7 +579,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX;
- _record_item_commands(ci, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken);
+ _record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken);
}
if (index == 0) {
@@ -623,7 +624,10 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
uint64_t specialization = 0;
specialization |= uint64_t(state.canvas_instance_batches[i].lights_disabled);
specialization |= uint64_t(!GLES3::Config::get_singleton()->float_texture_supported) << 1;
- _bind_material(material_data, variant, specialization);
+ bool success = _bind_material(material_data, variant, specialization);
+ if (!success) {
+ continue;
+ }
GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode;
@@ -707,7 +711,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
r_last_index += index;
}
-void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken) {
+void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken) {
RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter;
if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) {
@@ -1064,15 +1068,45 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Tran
state.canvas_instance_batches[state.current_batch_index].tex = m->texture;
_update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, state.instance_data_array[r_index].world);
modulate = m->modulate;
+
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
state.canvas_instance_batches[state.current_batch_index].tex = mm->texture;
- uint32_t instance_count = GLES3::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(mm->multimesh);
- if (instance_count > 1) {
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
- }
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
+
} else if (c->type == Item::Command::TYPE_PARTICLES) {
- WARN_PRINT_ONCE("Particles not supported yet, sorry :(");
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
+ const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
+ RID particles = pt->particles;
+ state.canvas_instance_batches[state.current_batch_index].tex = pt->texture;
+ state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
+ bool local_coords = particles_storage->particles_is_using_local_coords(particles);
+
+ if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
+ // Pass collision information.
+ Transform2D xform;
+ if (local_coords) {
+ xform = p_item->final_transform;
+ } else {
+ xform = p_canvas_transform_inverse;
+ }
+
+ GLuint sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
+
+ Rect2 to_screen;
+ {
+ Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_render_target);
+
+ to_screen.size = Vector2(1.0 / sdf_rect.size.width, 1.0 / sdf_rect.size.height);
+ to_screen.position = -sdf_rect.position * to_screen.size;
+ }
+
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
+ } else {
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), 0);
+ }
}
state.canvas_instance_batches[state.current_batch_index].command = c;
@@ -1209,20 +1243,21 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
case Item::Command::TYPE_MULTIMESH:
case Item::Command::TYPE_PARTICLES: {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
RID mesh;
RID mesh_instance;
- RID texture;
uint32_t instance_count = 1;
- GLuint multimesh_buffer = 0;
- uint32_t multimesh_stride = 0;
- uint32_t multimesh_color_offset = 0;
- bool multimesh_uses_color = false;
- bool multimesh_uses_custom_data = false;
+ GLuint instance_buffer = 0;
+ uint32_t instance_stride = 0;
+ uint32_t instance_color_offset = 0;
+ bool instance_uses_color = false;
+ bool instance_uses_custom_data = false;
if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(state.canvas_instance_batches[p_index].command);
mesh = m->mesh;
mesh_instance = m->mesh_instance;
+
} else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(state.canvas_instance_batches[p_index].command);
RID multimesh = mm->multimesh;
@@ -1238,13 +1273,41 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
break;
}
- multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
- multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
- multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
- multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
- multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
+ instance_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
+ instance_stride = mesh_storage->multimesh_get_stride(multimesh);
+ instance_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
+ instance_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
+ instance_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
+
} else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_PARTICLES) {
- // Do nothing for now.
+ const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(state.canvas_instance_batches[p_index].command);
+ RID particles = pt->particles;
+ mesh = particles_storage->particles_get_draw_pass_mesh(particles, 0);
+
+ ERR_BREAK(particles_storage->particles_get_mode(particles) != RS::PARTICLES_MODE_2D);
+ particles_storage->particles_request_process(particles);
+
+ if (particles_storage->particles_is_inactive(particles)) {
+ break;
+ }
+
+ RenderingServerDefault::redraw_request(); // Active particles means redraw request.
+
+ int dpc = particles_storage->particles_get_draw_passes(particles);
+ if (dpc == 0) {
+ break; // Nothing to draw.
+ }
+
+ instance_count = particles_storage->particles_get_amount(particles);
+ instance_buffer = particles_storage->particles_get_gl_buffer(particles);
+ instance_stride = 12; // 8 bytes for instance transform and 4 bytes for packed color and custom.
+ instance_color_offset = 8; // 8 bytes for instance transform.
+ instance_uses_color = true;
+ instance_uses_custom_data = true;
+ }
+
+ if (instance_buffer == 0) {
+ break;
}
ERR_FAIL_COND(mesh.is_null());
@@ -1277,17 +1340,17 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
if (instance_count > 1) {
// Bind instance buffers.
- glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, instance_buffer);
glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
glVertexAttribDivisor(1, 1);
glEnableVertexAttribArray(2);
- glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
glVertexAttribDivisor(2, 1);
- if (multimesh_uses_color || multimesh_uses_custom_data) {
+ if (instance_uses_color || instance_uses_custom_data) {
glEnableVertexAttribArray(5);
- glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
+ glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(instance_color_offset * sizeof(float)));
glVertexAttribDivisor(5, 1);
}
}
@@ -1361,17 +1424,17 @@ void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken, uint32_t &r_index)
_align_instance_data_buffer(r_index);
}
-void RasterizerCanvasGLES3::_bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization) {
+bool RasterizerCanvasGLES3::_bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization) {
if (p_material_data) {
if (p_material_data->shader_data->version.is_valid() && p_material_data->shader_data->valid) {
// Bind uniform buffer and textures
p_material_data->bind_uniforms();
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(p_material_data->shader_data->version, p_variant, p_specialization);
+ return GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(p_material_data->shader_data->version, p_variant, p_specialization);
} else {
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
+ return GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
}
} else {
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
+ return GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
}
}
@@ -1435,7 +1498,10 @@ void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, c
RS::CanvasOccluderPolygonCullMode cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
CanvasOcclusionShaderGLES3::ShaderVariant variant = config->float_texture_supported ? CanvasOcclusionShaderGLES3::MODE_SHADOW : CanvasOcclusionShaderGLES3::MODE_SHADOW_RGBA;
- shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ if (!success) {
+ return;
+ }
for (int i = 0; i < 4; i++) {
glViewport((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
@@ -1553,7 +1619,10 @@ void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_sha
RS::CanvasOccluderPolygonCullMode cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
CanvasOcclusionShaderGLES3::ShaderVariant variant = config->float_texture_supported ? CanvasOcclusionShaderGLES3::MODE_SHADOW : CanvasOcclusionShaderGLES3::MODE_SHADOW_RGBA;
- shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ if (!success) {
+ return;
+ }
Projection projection;
projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
@@ -1685,7 +1754,10 @@ void RasterizerCanvasGLES3::render_sdf(RID p_render_target, LightOccluderInstanc
glClear(GL_COLOR_BUFFER_BIT);
CanvasOcclusionShaderGLES3::ShaderVariant variant = CanvasOcclusionShaderGLES3::MODE_SDF;
- shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
+ if (!success) {
+ return;
+ }
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::PROJECTION, Projection(), shadow_render.shader_version, variant);
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::DIRECTION, 0.0, 0.0, shadow_render.shader_version, variant);
@@ -2555,7 +2627,6 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.initialize(global_defines);
data.canvas_shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_create();
- GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
shadow_render.shader.initialize();
shadow_render.shader_version = shadow_render.shader.version_create();
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index d672d05e14..0a03d43d07 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -254,7 +254,7 @@ public:
uint32_t start = 0;
uint32_t instance_count = 0;
- RID tex = RID();
+ RID tex;
RS::CanvasItemTextureFilter filter = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX;
RS::CanvasItemTextureRepeat repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX;
@@ -263,7 +263,7 @@ public:
Item *clip = nullptr;
- RID material = RID();
+ RID material;
GLES3::CanvasMaterialData *material_data = nullptr;
CanvasShaderGLES3::ShaderVariant shader_variant = CanvasShaderGLES3::MODE_QUAD;
@@ -303,7 +303,7 @@ public:
bool using_directional_lights = false;
- RID current_tex = RID();
+ RID current_tex;
RS::CanvasItemTextureFilter current_filter_mode = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX;
RS::CanvasItemTextureRepeat current_repeat_mode = RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX;
@@ -352,9 +352,9 @@ public:
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override;
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool p_to_backbuffer = false);
- void _record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch);
+ void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch);
void _render_batch(Light *p_lights, uint32_t p_index);
- void _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
+ bool _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
void _new_batch(bool &r_batch_broken, uint32_t &r_index);
void _add_to_batch(uint32_t &r_index, bool &r_batch_broken);
void _allocate_instance_data_buffer();
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index b2d01b02fb..1b42b55425 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -199,7 +199,7 @@ void RasterizerGLES3::finalize() {
RasterizerGLES3::RasterizerGLES3() {
#ifdef GLAD_ENABLED
- if (!gladLoadGL()) {
+ if (!gladLoaderLoadGL()) {
ERR_PRINT("Error initializing GLAD");
// FIXME this is an early return from a constructor. Any other code using this instance will crash or the finalizer will crash, because none of
// the members of this instance are initialized, so this just makes debugging harder. It should either crash here intentionally,
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 734911ccdb..026ec85e6b 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -35,6 +35,7 @@
#include "servers/rendering/rendering_server_globals.h"
#include "storage/config.h"
#include "storage/mesh_storage.h"
+#include "storage/particles_storage.h"
#include "storage/texture_storage.h"
#ifdef GLES3_ENABLED
@@ -50,6 +51,9 @@ RenderGeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_bas
ginstance->data->base = p_base;
ginstance->data->base_type = type;
+ ginstance->data->dependency_tracker.userdata = ginstance;
+ ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
+ ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
ginstance->_mark_dirty();
@@ -314,6 +318,8 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface(GeometryInstanceGLES3
void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
+
GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -361,6 +367,26 @@ void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_g
} break;
case RS::INSTANCE_PARTICLES: {
+ int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);
+
+ for (int j = 0; j < draw_passes; j++) {
+ RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+ if (!mesh.is_valid()) {
+ continue;
+ }
+
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ for (uint32_t k = 0; k < surface_count; k++) {
+ _geometry_instance_add_surface(ginstance, k, materials[k], mesh);
+ }
+ }
+ }
+
+ ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base);
} break;
default: {
@@ -382,9 +408,17 @@ void RasterizerSceneGLES3::_geometry_instance_update(RenderGeometryInstance *p_g
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- //ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_globals.default_shader_rd, TRANSFORMS_UNIFORM_SET);
-
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_PARTICLES;
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
+
+ if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {
+ store_transform = false;
+ }
+
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
}
@@ -751,12 +785,16 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
sky_transform.invert();
sky_transform = p_transform.basis * sky_transform;
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ if (!success) {
+ return;
+ }
+
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
glBindVertexArray(sky_globals.screen_triangle_array);
glDrawArrays(GL_TRIANGLES, 0, 3);
@@ -850,12 +888,15 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
correction.columns[1][1] = -1.0;
cm = correction * cm;
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ if (!success) {
+ return;
+ }
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.columns[2][0], cm.columns[0][0], cm.columns[2][1], cm.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.columns[2][0], cm.columns[0][0], cm.columns[2][1], cm.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
glBindVertexArray(sky_globals.screen_triangle_array);
@@ -864,7 +905,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, local_view, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, local_view, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, sky->raw_radiance, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
@@ -945,7 +986,10 @@ void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) {
glViewport(0, 0, size, size);
glBindVertexArray(sky_globals.screen_triangle_array);
- material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, mode);
+ bool success = material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, mode);
+ if (!success) {
+ return;
+ }
if (p_base_layer > 0) {
const uint32_t sample_counts[4] = { 1, sky_globals.ggx_samples / 4, sky_globals.ggx_samples / 2, sky_globals.ggx_samples };
@@ -1851,8 +1895,11 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
glColorMask(0, 0, 0, 0);
glClearDepth(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
+ uint32_t spec_constant = SceneShaderGLES3::DISABLE_FOG | SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL |
+ SceneShaderGLES3::DISABLE_LIGHTMAP | SceneShaderGLES3::DISABLE_LIGHT_OMNI |
+ SceneShaderGLES3::DISABLE_LIGHT_SPOT;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, 0, use_wireframe);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, spec_constant, use_wireframe);
_render_list_template<PASS_MODE_DEPTH>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_OPAQUE].elements.size());
glColorMask(1, 1, 1, 1);
@@ -1894,11 +1941,11 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
{
// Specialization Constants that apply for entire rendering pass.
if (render_data.directional_light_count == 0) {
- spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS;
+ spec_constant_base_flags |= SceneShaderGLES3::DISABLE_LIGHT_DIRECTIONAL;
}
if (render_data.environment.is_null() || (render_data.environment.is_valid() && !environment_get_fog_enabled(render_data.environment))) {
- spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG;
+ spec_constant_base_flags |= SceneShaderGLES3::DISABLE_FOG;
}
}
// Render Opaque Objects.
@@ -1947,6 +1994,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
template <PassMode p_pass_mode>
void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass) {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
@@ -1960,11 +2008,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
SceneShaderGLES3::ShaderVariant prev_variant = SceneShaderGLES3::ShaderVariant::MODE_COLOR;
SceneShaderGLES3::ShaderVariant shader_variant = SceneShaderGLES3::MODE_COLOR; // Assigned to silence wrong -Wmaybe-initialized
- // @todo Get this from p_params->spec_constant_base_flags instead of hardcoding it.
- uint32_t base_spec_constants = 0;
+ uint32_t base_spec_constants = p_params->spec_constant_base_flags;
if (p_render_data->view_count > 1) {
- base_spec_constants |= 1 << SPEC_CONSTANT_USE_MULTIVIEW;
+ base_spec_constants |= SceneShaderGLES3::USE_MULTIVIEW;
}
switch (p_pass_mode) {
@@ -1987,7 +2034,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
Sky *sky = sky_owner.get_or_null(environment_get_sky(p_render_data->environment));
if (sky && sky->radiance != 0) {
texture_to_bind = sky->radiance;
- // base_spec_constant |= USE_RADIANCE_MAP;
+ base_spec_constants |= SceneShaderGLES3::USE_RADIANCE_MAP;
}
glBindTexture(GL_TEXTURE_CUBE_MAP, texture_to_bind);
}
@@ -2157,7 +2204,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
bool use_index_buffer = index_array_gl != 0;
- if (prev_index_array_gl != index_array_gl) {
+ if (prev_index_array_gl != index_array_gl || prev_vertex_array_gl != vertex_array_gl) {
if (index_array_gl != 0) {
// Bind index each time so we can use LODs
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_gl);
@@ -2177,11 +2224,16 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
SceneShaderGLES3::ShaderVariant instance_variant = shader_variant;
if (inst->instance_count > 0) {
+ // Will need to use instancing to draw (either MultiMesh or Particles).
instance_variant = SceneShaderGLES3::ShaderVariant(1 + int(shader_variant));
}
if (prev_shader != shader || prev_variant != instance_variant) {
- material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant, base_spec_constants);
+ bool success = material_storage->shaders.scene_shader.version_bind_shader(shader->version, instance_variant, base_spec_constants);
+ if (!success) {
+ continue;
+ }
+
float opaque_prepass_threshold = 0.0;
if constexpr (p_pass_mode == PASS_MODE_DEPTH) {
opaque_prepass_threshold = 0.99;
@@ -2213,25 +2265,42 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, world_transform, shader->version, instance_variant, base_spec_constants);
if (inst->instance_count > 0) {
- // Using MultiMesh.
+ // Using MultiMesh or Particles.
// Bind instance buffers.
- GLuint multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(inst->data->base);
- glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
- uint32_t multimesh_stride = mesh_storage->multimesh_get_stride(inst->data->base);
+ GLuint instance_buffer = 0;
+ uint32_t stride = 0;
+ if (inst->flags_cache & INSTANCE_DATA_FLAG_PARTICLES) {
+ instance_buffer = particles_storage->particles_get_gl_buffer(inst->data->base);
+ stride = 16; // 12 bytes for instance transform and 4 bytes for packed color and custom.
+ } else {
+ instance_buffer = mesh_storage->multimesh_get_gl_buffer(inst->data->base);
+ stride = mesh_storage->multimesh_get_stride(inst->data->base);
+ }
+
+ if (instance_buffer == 0) {
+ // Instance buffer not initialized yet. Skip rendering for now.
+ continue;
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, instance_buffer);
+
glEnableVertexAttribArray(12);
- glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
+ glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
glVertexAttribDivisor(12, 1);
glEnableVertexAttribArray(13);
- glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
+ glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4));
glVertexAttribDivisor(13, 1);
- glEnableVertexAttribArray(14);
- glVertexAttribPointer(14, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 8));
- glVertexAttribDivisor(14, 1);
+ if (!(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D)) {
+ glEnableVertexAttribArray(14);
+ glVertexAttribPointer(14, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(sizeof(float) * 8));
+ glVertexAttribDivisor(14, 1);
+ }
- if (mesh_storage->multimesh_uses_colors(inst->data->base) || mesh_storage->multimesh_uses_custom_data(inst->data->base)) {
+ if ((inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR) || (inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA)) {
+ uint32_t color_custom_offset = inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D ? 8 : 12;
glEnableVertexAttribArray(15);
- glVertexAttribIPointer(15, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(mesh_storage->multimesh_get_color_offset(inst->data->base) * sizeof(float)));
+ glVertexAttribIPointer(15, 4, GL_UNSIGNED_INT, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(color_custom_offset * sizeof(float)));
glVertexAttribDivisor(15, 1);
}
if (use_index_buffer) {
@@ -2265,6 +2334,72 @@ void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, c
}
void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
+ GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
+
+ ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider));
+ Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
+ Projection cm;
+ cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
+
+ Vector3 cam_pos = p_transform.origin;
+ cam_pos.y += extents.y;
+
+ Transform3D cam_xform;
+ cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_column(Vector3::AXIS_Y), -p_transform.basis.get_column(Vector3::AXIS_Z).normalized());
+
+ GLuint fb = particles_storage->particles_collision_get_heightfield_framebuffer(p_collider);
+ Size2i fb_size = particles_storage->particles_collision_get_heightfield_size(p_collider);
+
+ RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
+
+ RenderDataGLES3 render_data;
+
+ render_data.cam_projection = cm;
+ render_data.cam_transform = cam_xform;
+ render_data.view_projection[0] = cm;
+ render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
+ render_data.cam_orthogonal = true;
+ render_data.z_near = 0.0;
+ render_data.z_far = cm.get_z_far();
+
+ render_data.instances = &p_instances;
+
+ _setup_environment(&render_data, true, Vector2(fb_size), true, Color(), false);
+
+ PassMode pass_mode = PASS_MODE_SHADOW;
+
+ _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
+ render_list[RENDER_LIST_SECONDARY].sort_by_key();
+
+ RENDER_TIMESTAMP("Render Collider Heightfield");
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
+ glViewport(0, 0, fb_size.width, fb_size.height);
+
+ GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_parameters_get_uniform_buffer();
+
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_GLOBALS_UNIFORM_LOCATION, global_buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glDisable(GL_SCISSOR_TEST);
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+ scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
+
+ glColorMask(0, 0, 0, 0);
+ glClearDepth(1.0f);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, 31, false);
+
+ _render_list_template<PASS_MODE_SHADOW>(&render_list_params, &render_data, 0, render_list[RENDER_LIST_SECONDARY].elements.size());
+
+ glColorMask(1, 1, 1, 1);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void RasterizerSceneGLES3::set_time(double p_time, double p_step) {
@@ -2415,7 +2550,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
global_defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(config->max_renderable_lights) + "\n";
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n";
- global_defines += "\n#define MAX_FORWARD_LIGHTS " + itos(config->max_lights_per_object) + "\n";
+ global_defines += "\n#define MAX_FORWARD_LIGHTS uint(" + itos(config->max_lights_per_object) + ")\n";
material_storage->shaders.scene_shader.initialize(global_defines);
scene_globals.shader_default_version = material_storage->shaders.scene_shader.version_create();
material_storage->shaders.scene_shader.version_bind_shader(scene_globals.shader_default_version, SceneShaderGLES3::MODE_COLOR);
@@ -2455,7 +2590,6 @@ void fragment() {
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n";
material_storage->shaders.sky_shader.initialize(global_defines);
sky_globals.shader_default_version = material_storage->shaders.sky_shader.version_create();
- material_storage->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND);
}
{
@@ -2463,7 +2597,6 @@ void fragment() {
global_defines += "\n#define MAX_SAMPLE_COUNT " + itos(sky_globals.ggx_samples) + "\n";
material_storage->shaders.cubemap_filter_shader.initialize(global_defines);
scene_globals.cubemap_filter_shader_version = material_storage->shaders.cubemap_filter_shader.version_create();
- material_storage->shaders.cubemap_filter_shader.version_bind_shader(scene_globals.cubemap_filter_shader_version, CubemapFilterShaderGLES3::MODE_DEFAULT);
}
{
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 3a759425e2..6e1f1babf8 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -85,23 +85,13 @@ enum SkyUniformLocation {
SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
};
-enum {
- SPEC_CONSTANT_DISABLE_LIGHTMAP = 0,
- SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 1,
- SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 2,
- SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 3,
- SPEC_CONSTANT_DISABLE_FOG = 4,
- SPEC_CONSTANT_USE_RADIANCE_MAP = 5,
- SPEC_CONSTANT_USE_MULTIVIEW = 6,
-};
-
struct RenderDataGLES3 {
Ref<RenderSceneBuffersGLES3> render_buffers;
bool transparent_bg = false;
- Transform3D cam_transform = Transform3D();
- Transform3D inv_cam_transform = Transform3D();
- Projection cam_projection = Projection();
+ Transform3D cam_transform;
+ Transform3D inv_cam_transform;
+ Projection cam_projection;
bool cam_orthogonal = false;
// For stereo rendering
@@ -115,9 +105,9 @@ struct RenderDataGLES3 {
const PagedArray<RenderGeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
- RID environment = RID();
- RID camera_attributes = RID();
- RID reflection_probe = RID();
+ RID environment;
+ RID camera_attributes;
+ RID reflection_probe;
int reflection_probe_pass = 0;
float lod_distance_multiplier = 0.0;
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 2ff7f72180..1dcd17ea0e 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -92,7 +92,7 @@ void ShaderGLES3::_add_stage(const char *p_code, StageType p_stage_type) {
}
}
-void ShaderGLES3::_setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants) {
+void ShaderGLES3::_setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_feedback_count, const Feedback *p_feedback, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants) {
name = p_name;
if (p_vertex_code) {
@@ -118,6 +118,8 @@ void ShaderGLES3::_setup(const char *p_vertex_code, const char *p_fragment_code,
}
variant_defines = p_variants;
variant_count = p_variant_count;
+ feedbacks = p_feedback;
+ feedback_count = p_feedback_count;
StringBuilder tohash;
/*
@@ -339,9 +341,21 @@ void ShaderGLES3::_compile_specialization(Version::Specialization &spec, uint32_
glAttachShader(spec.id, spec.frag_id);
glAttachShader(spec.id, spec.vert_id);
- //for (int i = 0; i < attribute_pair_count; i++) {
- // glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name);
- //}
+ // If feedback exists, set it up.
+
+ if (feedback_count) {
+ Vector<const char *> feedback;
+ for (int i = 0; i < feedback_count; i++) {
+ if (feedbacks[i].specialization == 0 || (feedbacks[i].specialization & p_specialization)) {
+ // Specialization for this feedback is enabled
+ feedback.push_back(feedbacks[i].name);
+ }
+ }
+
+ if (feedback.size()) {
+ glTransformFeedbackVaryings(spec.id, feedback.size(), feedback.ptr(), GL_INTERLEAVED_ATTRIBS);
+ }
+ }
glLinkProgram(spec.id);
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 3ab7642357..83b950ef45 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -70,6 +70,11 @@ protected:
bool default_value = false;
};
+ struct Feedback {
+ const char *name;
+ uint64_t specialization;
+ };
+
private:
//versions
CharString general_defines;
@@ -165,6 +170,8 @@ private:
int uniform_count = 0;
const UBOPair *ubo_pairs = nullptr;
int ubo_count = 0;
+ const Feedback *feedbacks;
+ int feedback_count = 0;
const TexUnitPair *texunit_pairs = nullptr;
int texunit_pair_count = 0;
int specialization_count = 0;
@@ -178,13 +185,13 @@ private:
protected:
ShaderGLES3();
- void _setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants);
+ void _setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_feedback_count, const Feedback *p_feedback, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants);
- _FORCE_INLINE_ void _version_bind_shader(RID p_version, int p_variant, uint64_t p_specialization) {
- ERR_FAIL_INDEX(p_variant, variant_count);
+ _FORCE_INLINE_ bool _version_bind_shader(RID p_version, int p_variant, uint64_t p_specialization) {
+ ERR_FAIL_INDEX_V(p_variant, variant_count, false);
Version *version = version_owner.get_or_null(p_version);
- ERR_FAIL_COND(!version);
+ ERR_FAIL_COND_V(!version, false);
if (version->variants.size() == 0) {
_initialize_version(version); //may lack initialization
@@ -210,11 +217,12 @@ protected:
if (!spec || !spec->ok) {
WARN_PRINT_ONCE("shader failed to compile, unable to bind shader.");
- return;
+ return false;
}
glUseProgram(spec->id);
current_shader = spec;
+ return true;
}
_FORCE_INLINE_ int _version_get_uniform(int p_which, RID p_version, int p_variant, uint64_t p_specialization) {
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index b8bb08ec34..2686b1aa48 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -19,3 +19,5 @@ if "GLES3_GLSL" in env["BUILDERS"]:
env.GLES3_GLSL("cubemap_filter.glsl")
env.GLES3_GLSL("canvas_occlusion.glsl")
env.GLES3_GLSL("canvas_sdf.glsl")
+ env.GLES3_GLSL("particles.glsl")
+ env.GLES3_GLSL("particles_copy.glsl")
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index ca806304c5..cdae05a516 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -153,48 +153,6 @@ void main() {
uv += 1e-5;
}
-#ifdef USE_ATTRIBUTES
-#if 0
- if (bool(draw_data[draw_data_instance].flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
- //skeleton transform
- ivec4 bone_indicesi = ivec4(bone_indices);
-
- uvec2 tex_ofs = bone_indicesi.x * 2;
-
- mat2x4 m;
- m = mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.x;
-
- tex_ofs = bone_indicesi.y * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.y;
-
- tex_ofs = bone_indicesi.z * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.z;
-
- tex_ofs = bone_indicesi.w * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.w;
-
- mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse;
-
- //outvec = bone_matrix * outvec;
- }
-#endif
-#endif
-
vertex = (canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
vertex_interp = vertex;
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl
index 88464876f1..6fcb23204d 100644
--- a/drivers/gles3/shaders/cubemap_filter.glsl
+++ b/drivers/gles3/shaders/cubemap_filter.glsl
@@ -31,7 +31,7 @@ uniform samplerCube source_cube; //texunit:0
uniform int face_id;
#ifndef MODE_DIRECT_WRITE
-uniform int sample_count;
+uniform uint sample_count;
uniform vec4 sample_directions_mip[MAX_SAMPLE_COUNT];
uniform float weight;
#endif
@@ -105,7 +105,7 @@ void main() {
T[1] = cross(N, T[0]);
T[2] = N;
- for (int sample_num = 0; sample_num < sample_count; sample_num++) {
+ for (uint sample_num = 0u; sample_num < sample_count; sample_num++) {
vec4 sample_direction_mip = sample_directions_mip[sample_num];
vec3 L = T * sample_direction_mip.xyz;
vec3 val = textureLod(source_cube, L, sample_direction_mip.w).rgb;
diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl
new file mode 100644
index 0000000000..f8741a22ab
--- /dev/null
+++ b/drivers/gles3/shaders/particles.glsl
@@ -0,0 +1,501 @@
+/* clang-format off */
+#[modes]
+
+mode_default =
+
+#[specializations]
+
+MODE_3D = false
+USERDATA1_USED = false
+USERDATA2_USED = false
+USERDATA3_USED = false
+USERDATA4_USED = false
+USERDATA5_USED = false
+USERDATA6_USED = false
+
+#[vertex]
+
+#define SDF_MAX_LENGTH 16384.0
+
+layout(std140) uniform GlobalShaderUniformData { //ubo:1
+ vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
+};
+
+// This needs to be outside clang-format so the ubo comment is in the right place
+#ifdef MATERIAL_UNIFORMS_USED
+layout(std140) uniform MaterialUniforms{ //ubo:2
+
+#MATERIAL_UNIFORMS
+
+};
+#endif
+
+/* clang-format on */
+
+#define MAX_ATTRACTORS 32
+
+#define ATTRACTOR_TYPE_SPHERE uint(0)
+#define ATTRACTOR_TYPE_BOX uint(1)
+#define ATTRACTOR_TYPE_VECTOR_FIELD uint(2)
+
+struct Attractor {
+ mat4 transform;
+ vec4 extents; // Extents or radius. w-channel is padding.
+
+ uint type;
+ float strength;
+ float attenuation;
+ float directionality;
+};
+
+#define MAX_COLLIDERS 32
+
+#define COLLIDER_TYPE_SPHERE uint(0)
+#define COLLIDER_TYPE_BOX uint(1)
+#define COLLIDER_TYPE_SDF uint(2)
+#define COLLIDER_TYPE_HEIGHT_FIELD uint(3)
+#define COLLIDER_TYPE_2D_SDF uint(4)
+
+struct Collider {
+ mat4 transform;
+ vec4 extents; // Extents or radius. w-channel is padding.
+
+ uint type;
+ float scale;
+ float pad0;
+ float pad1;
+};
+
+layout(std140) uniform FrameData { //ubo:0
+ bool emitting;
+ uint cycle;
+ float system_phase;
+ float prev_system_phase;
+
+ float explosiveness;
+ float randomness;
+ float time;
+ float delta;
+
+ float particle_size;
+ float pad0;
+ float pad1;
+ float pad2;
+
+ uint random_seed;
+ uint attractor_count;
+ uint collider_count;
+ uint frame;
+
+ mat4 emission_transform;
+
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
+};
+
+#define PARTICLE_FLAG_ACTIVE uint(1)
+#define PARTICLE_FLAG_STARTED uint(2)
+#define PARTICLE_FLAG_TRAILED uint(4)
+#define PARTICLE_FRAME_MASK uint(0xFFFF)
+#define PARTICLE_FRAME_SHIFT uint(16)
+
+// ParticleData
+layout(location = 0) in highp vec4 color;
+layout(location = 1) in highp vec4 velocity_flags;
+layout(location = 2) in highp vec4 custom;
+layout(location = 3) in highp vec4 xform_1;
+layout(location = 4) in highp vec4 xform_2;
+#ifdef MODE_3D
+layout(location = 5) in highp vec4 xform_3;
+#endif
+#ifdef USERDATA1_USED
+layout(location = 6) in highp vec4 userdata1;
+#endif
+#ifdef USERDATA2_USED
+layout(location = 7) in highp vec4 userdata2;
+#endif
+#ifdef USERDATA3_USED
+layout(location = 8) in highp vec4 userdata3;
+#endif
+#ifdef USERDATA4_USED
+layout(location = 9) in highp vec4 userdata4;
+#endif
+#ifdef USERDATA5_USED
+layout(location = 10) in highp vec4 userdata5;
+#endif
+#ifdef USERDATA6_USED
+layout(location = 11) in highp vec4 userdata6;
+#endif
+
+out highp vec4 out_color; //tfb:
+out highp vec4 out_velocity_flags; //tfb:
+out highp vec4 out_custom; //tfb:
+out highp vec4 out_xform_1; //tfb:
+out highp vec4 out_xform_2; //tfb:
+#ifdef MODE_3D
+out highp vec4 out_xform_3; //tfb:MODE_3D
+#endif
+#ifdef USERDATA1_USED
+out highp vec4 out_userdata1; //tfb:USERDATA1_USED
+#endif
+#ifdef USERDATA2_USED
+out highp vec4 out_userdata2; //tfb:USERDATA2_USED
+#endif
+#ifdef USERDATA3_USED
+out highp vec4 out_userdata3; //tfb:USERDATA3_USED
+#endif
+#ifdef USERDATA4_USED
+out highp vec4 out_userdata4; //tfb:USERDATA4_USED
+#endif
+#ifdef USERDATA5_USED
+out highp vec4 out_userdata5; //tfb:USERDATA5_USED
+#endif
+#ifdef USERDATA6_USED
+out highp vec4 out_userdata6; //tfb:USERDATA6_USED
+#endif
+
+uniform sampler2D height_field_texture; //texunit:0
+
+uniform float lifetime;
+uniform bool clear;
+uniform uint total_particles;
+uniform bool use_fractional_delta;
+
+uint hash(uint x) {
+ x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
+ x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b);
+ x = (x >> uint(16)) ^ x;
+ return x;
+}
+
+vec3 safe_normalize(vec3 direction) {
+ const float EPSILON = 0.001;
+ if (length(direction) < EPSILON) {
+ return vec3(0.0);
+ }
+ return normalize(direction);
+}
+
+// Needed whenever 2D sdf texture is read from as it is packed in RGBA8.
+float vec4_to_float(vec4 p_vec) {
+ return dot(p_vec, vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0)) * 2.0 - 1.0;
+}
+
+#GLOBALS
+
+void main() {
+ bool apply_forces = true;
+ bool apply_velocity = true;
+ float local_delta = delta;
+
+ float mass = 1.0;
+
+ bool restart = false;
+
+ bool restart_position = false;
+ bool restart_rotation_scale = false;
+ bool restart_velocity = false;
+ bool restart_color = false;
+ bool restart_custom = false;
+
+ mat4 xform = mat4(1.0);
+ uint flags = 0u;
+
+ if (clear) {
+ out_color = vec4(1.0);
+ out_custom = vec4(0.0);
+ out_velocity_flags = vec4(0.0);
+ } else {
+ out_color = color;
+ out_velocity_flags = velocity_flags;
+ out_custom = custom;
+ xform[0] = xform_1;
+ xform[1] = xform_2;
+#ifdef MODE_3D
+ xform[2] = xform_3;
+#endif
+ xform = transpose(xform);
+ flags = floatBitsToUint(velocity_flags.w);
+ }
+
+ //clear started flag if set
+ flags &= ~PARTICLE_FLAG_STARTED;
+
+ bool collided = false;
+ vec3 collision_normal = vec3(0.0);
+ float collision_depth = 0.0;
+
+ vec3 attractor_force = vec3(0.0);
+
+#if !defined(DISABLE_VELOCITY)
+
+ if (bool(flags & PARTICLE_FLAG_ACTIVE)) {
+ xform[3].xyz += out_velocity_flags.xyz * local_delta;
+ }
+#endif
+ uint index = uint(gl_VertexID);
+ if (emitting) {
+ float restart_phase = float(index) / float(total_particles);
+
+ if (randomness > 0.0) {
+ uint seed = cycle;
+ if (restart_phase >= system_phase) {
+ seed -= uint(1);
+ }
+ seed *= uint(total_particles);
+ seed += index;
+ float random = float(hash(seed) % uint(65536)) / 65536.0;
+ restart_phase += randomness * random * 1.0 / float(total_particles);
+ }
+
+ restart_phase *= (1.0 - explosiveness);
+
+ if (system_phase > prev_system_phase) {
+ // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed
+
+ if (restart_phase >= prev_system_phase && restart_phase < system_phase) {
+ restart = true;
+ if (use_fractional_delta) {
+ local_delta = (system_phase - restart_phase) * lifetime;
+ }
+ }
+
+ } else if (delta > 0.0) {
+ if (restart_phase >= prev_system_phase) {
+ restart = true;
+ if (use_fractional_delta) {
+ local_delta = (1.0 - restart_phase + system_phase) * lifetime;
+ }
+
+ } else if (restart_phase < system_phase) {
+ restart = true;
+ if (use_fractional_delta) {
+ local_delta = (system_phase - restart_phase) * lifetime;
+ }
+ }
+ }
+
+ if (restart) {
+ flags = emitting ? (PARTICLE_FLAG_ACTIVE | PARTICLE_FLAG_STARTED | (cycle << PARTICLE_FRAME_SHIFT)) : 0u;
+ restart_position = true;
+ restart_rotation_scale = true;
+ restart_velocity = true;
+ restart_color = true;
+ restart_custom = true;
+ }
+ }
+
+ bool particle_active = bool(flags & PARTICLE_FLAG_ACTIVE);
+
+ uint particle_number = (flags >> PARTICLE_FRAME_SHIFT) * uint(total_particles) + index;
+
+ if (restart && particle_active) {
+#CODE : START
+ }
+
+ if (particle_active) {
+ for (uint i = 0u; i < attractor_count; i++) {
+ vec3 dir;
+ float amount;
+ vec3 rel_vec = xform[3].xyz - attractors[i].transform[3].xyz;
+ vec3 local_pos = rel_vec * mat3(attractors[i].transform);
+
+ switch (attractors[i].type) {
+ case ATTRACTOR_TYPE_SPHERE: {
+ dir = safe_normalize(rel_vec);
+ float d = length(local_pos) / attractors[i].extents.x;
+ if (d > 1.0) {
+ continue;
+ }
+ amount = max(0.0, 1.0 - d);
+ } break;
+ case ATTRACTOR_TYPE_BOX: {
+ dir = safe_normalize(rel_vec);
+
+ vec3 abs_pos = abs(local_pos / attractors[i].extents.xyz);
+ float d = max(abs_pos.x, max(abs_pos.y, abs_pos.z));
+ if (d > 1.0) {
+ continue;
+ }
+ amount = max(0.0, 1.0 - d);
+
+ } break;
+ case ATTRACTOR_TYPE_VECTOR_FIELD: {
+ } break;
+ }
+ amount = pow(amount, attractors[i].attenuation);
+ dir = safe_normalize(mix(dir, attractors[i].transform[2].xyz, attractors[i].directionality));
+ attractor_force -= amount * dir * attractors[i].strength;
+ }
+
+ float particle_size = particle_size;
+
+#ifdef USE_COLLISION_SCALE
+
+ particle_size *= dot(vec3(length(xform[0].xyz), length(xform[1].xyz), length(xform[2].xyz)), vec3(0.33333333333));
+
+#endif
+
+ if (collider_count == 1u && colliders[0].type == COLLIDER_TYPE_2D_SDF) {
+ //2D collision
+
+ vec2 pos = xform[3].xy;
+ vec4 to_sdf_x = colliders[0].transform[0];
+ vec4 to_sdf_y = colliders[0].transform[1];
+ vec2 sdf_pos = vec2(dot(vec4(pos, 0, 1), to_sdf_x), dot(vec4(pos, 0, 1), to_sdf_y));
+
+ vec4 sdf_to_screen = vec4(colliders[0].extents.xyz, colliders[0].scale);
+
+ vec2 uv_pos = sdf_pos * sdf_to_screen.xy + sdf_to_screen.zw;
+
+ if (all(greaterThan(uv_pos, vec2(0.0))) && all(lessThan(uv_pos, vec2(1.0)))) {
+ vec2 pos2 = pos + vec2(0, particle_size);
+ vec2 sdf_pos2 = vec2(dot(vec4(pos2, 0, 1), to_sdf_x), dot(vec4(pos2, 0, 1), to_sdf_y));
+ float sdf_particle_size = distance(sdf_pos, sdf_pos2);
+
+ float d = vec4_to_float(texture(height_field_texture, uv_pos)) * SDF_MAX_LENGTH;
+
+ d -= sdf_particle_size;
+
+ if (d < 0.0) {
+ const float EPSILON = 0.001;
+ vec2 n = normalize(vec2(
+ vec4_to_float(texture(height_field_texture, uv_pos + vec2(EPSILON, 0.0))) - vec4_to_float(texture(height_field_texture, uv_pos - vec2(EPSILON, 0.0))),
+ vec4_to_float(texture(height_field_texture, uv_pos + vec2(0.0, EPSILON))) - vec4_to_float(texture(height_field_texture, uv_pos - vec2(0.0, EPSILON)))));
+
+ collided = true;
+ sdf_pos2 = sdf_pos + n * d;
+ pos2 = vec2(dot(vec4(sdf_pos2, 0, 1), colliders[0].transform[2]), dot(vec4(sdf_pos2, 0, 1), colliders[0].transform[3]));
+
+ n = pos - pos2;
+
+ collision_normal = normalize(vec3(n, 0.0));
+ collision_depth = length(n);
+ }
+ }
+
+ } else {
+ for (uint i = 0u; i < collider_count; i++) {
+ vec3 normal;
+ float depth;
+ bool col = false;
+
+ vec3 rel_vec = xform[3].xyz - colliders[i].transform[3].xyz;
+ vec3 local_pos = rel_vec * mat3(colliders[i].transform);
+
+ switch (colliders[i].type) {
+ case COLLIDER_TYPE_SPHERE: {
+ float d = length(rel_vec) - (particle_size + colliders[i].extents.x);
+
+ if (d < 0.0) {
+ col = true;
+ depth = -d;
+ normal = normalize(rel_vec);
+ }
+
+ } break;
+ case COLLIDER_TYPE_BOX: {
+ vec3 abs_pos = abs(local_pos);
+ vec3 sgn_pos = sign(local_pos);
+
+ if (any(greaterThan(abs_pos, colliders[i].extents.xyz))) {
+ //point outside box
+
+ vec3 closest = min(abs_pos, colliders[i].extents.xyz);
+ vec3 rel = abs_pos - closest;
+ depth = length(rel) - particle_size;
+ if (depth < 0.0) {
+ col = true;
+ normal = mat3(colliders[i].transform) * (normalize(rel) * sgn_pos);
+ depth = -depth;
+ }
+ } else {
+ //point inside box
+ vec3 axis_len = colliders[i].extents.xyz - abs_pos;
+ // there has to be a faster way to do this?
+ if (all(lessThan(axis_len.xx, axis_len.yz))) {
+ normal = vec3(1, 0, 0);
+ } else if (all(lessThan(axis_len.yy, axis_len.xz))) {
+ normal = vec3(0, 1, 0);
+ } else {
+ normal = vec3(0, 0, 1);
+ }
+
+ col = true;
+ depth = dot(normal * axis_len, vec3(1)) + particle_size;
+ normal = mat3(colliders[i].transform) * (normal * sgn_pos);
+ }
+
+ } break;
+ case COLLIDER_TYPE_SDF: {
+ } break;
+ case COLLIDER_TYPE_HEIGHT_FIELD: {
+ vec3 local_pos_bottom = local_pos;
+ local_pos_bottom.y -= particle_size;
+
+ if (any(greaterThan(abs(local_pos_bottom), colliders[i].extents.xyz))) {
+ continue;
+ }
+ const float DELTA = 1.0 / 8192.0;
+
+ vec3 uvw_pos = vec3(local_pos_bottom / colliders[i].extents.xyz) * 0.5 + 0.5;
+
+ float y = 1.0 - texture(height_field_texture, uvw_pos.xz).r;
+
+ if (y > uvw_pos.y) {
+ //inside heightfield
+
+ vec3 pos1 = (vec3(uvw_pos.x, y, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
+ vec3 pos2 = (vec3(uvw_pos.x + DELTA, 1.0 - texture(height_field_texture, uvw_pos.xz + vec2(DELTA, 0)).r, uvw_pos.z) * 2.0 - 1.0) * colliders[i].extents.xyz;
+ vec3 pos3 = (vec3(uvw_pos.x, 1.0 - texture(height_field_texture, uvw_pos.xz + vec2(0, DELTA)).r, uvw_pos.z + DELTA) * 2.0 - 1.0) * colliders[i].extents.xyz;
+
+ normal = normalize(cross(pos1 - pos2, pos1 - pos3));
+ float local_y = (vec3(local_pos / colliders[i].extents.xyz) * 0.5 + 0.5).y;
+
+ col = true;
+ depth = dot(normal, pos1) - dot(normal, local_pos_bottom);
+ }
+
+ } break;
+ }
+
+ if (col) {
+ if (!collided) {
+ collided = true;
+ collision_normal = normal;
+ collision_depth = depth;
+ } else {
+ vec3 c = collision_normal * collision_depth;
+ c += normal * max(0.0, depth - dot(normal, c));
+ collision_normal = normalize(c);
+ collision_depth = length(c);
+ }
+ }
+ }
+ }
+ }
+
+ if (particle_active) {
+#CODE : PROCESS
+ }
+
+ flags &= ~PARTICLE_FLAG_ACTIVE;
+ if (particle_active) {
+ flags |= PARTICLE_FLAG_ACTIVE;
+ }
+
+ xform = transpose(xform);
+ out_xform_1 = xform[0];
+ out_xform_2 = xform[1];
+#ifdef MODE_3D
+ out_xform_3 = xform[2];
+#endif
+ out_velocity_flags.w = uintBitsToFloat(flags);
+}
+
+/* clang-format off */
+#[fragment]
+
+void main() {
+}
+/* clang-format on */
diff --git a/drivers/gles3/shaders/particles_copy.glsl b/drivers/gles3/shaders/particles_copy.glsl
new file mode 100644
index 0000000000..f273cb7b64
--- /dev/null
+++ b/drivers/gles3/shaders/particles_copy.glsl
@@ -0,0 +1,122 @@
+/* clang-format off */
+#[modes]
+
+mode_default =
+
+#[specializations]
+
+MODE_3D = false
+
+#[vertex]
+
+#include "stdlib_inc.glsl"
+
+// ParticleData
+layout(location = 0) in highp vec4 color;
+layout(location = 1) in highp vec4 velocity_flags;
+layout(location = 2) in highp vec4 custom;
+layout(location = 3) in highp vec4 xform_1;
+layout(location = 4) in highp vec4 xform_2;
+#ifdef MODE_3D
+layout(location = 5) in highp vec4 xform_3;
+#endif
+
+/* clang-format on */
+out highp vec4 out_xform_1; //tfb:
+out highp vec4 out_xform_2; //tfb:
+#ifdef MODE_3D
+out highp vec4 out_xform_3; //tfb:MODE_3D
+#endif
+flat out highp uvec4 instance_color_custom_data; //tfb:
+
+uniform lowp vec3 sort_direction;
+uniform highp float frame_remainder;
+
+uniform highp vec3 align_up;
+uniform highp uint align_mode;
+
+uniform highp mat4 inv_emission_transform;
+
+#define TRANSFORM_ALIGN_DISABLED uint(0)
+#define TRANSFORM_ALIGN_Z_BILLBOARD uint(1)
+#define TRANSFORM_ALIGN_Y_TO_VELOCITY uint(2)
+#define TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY uint(3)
+
+#define PARTICLE_FLAG_ACTIVE uint(1)
+
+void main() {
+ mat4 txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); // zero scale, becomes invisible.
+ if (bool(floatBitsToUint(velocity_flags.w) & PARTICLE_FLAG_ACTIVE)) {
+#ifdef MODE_3D
+ txform = transpose(mat4(xform_1, xform_2, xform_3, vec4(0.0, 0.0, 0.0, 1.0)));
+#else
+ txform = transpose(mat4(xform_1, xform_2, vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)));
+#endif
+
+ switch (align_mode) {
+ case TRANSFORM_ALIGN_DISABLED: {
+ } break; //nothing
+ case TRANSFORM_ALIGN_Z_BILLBOARD: {
+ mat3 local = mat3(normalize(cross(align_up, sort_direction)), align_up, sort_direction);
+ local = local * mat3(txform);
+ txform[0].xyz = local[0];
+ txform[1].xyz = local[1];
+ txform[2].xyz = local[2];
+
+ } break;
+ case TRANSFORM_ALIGN_Y_TO_VELOCITY: {
+ vec3 v = velocity_flags.xyz;
+ float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
+ if (length(v) > 0.0) {
+ txform[1].xyz = normalize(v);
+ } else {
+ txform[1].xyz = normalize(txform[1].xyz);
+ }
+
+ txform[0].xyz = normalize(cross(txform[1].xyz, txform[2].xyz));
+ txform[2].xyz = vec3(0.0, 0.0, 1.0) * s;
+ txform[0].xyz *= s;
+ txform[1].xyz *= s;
+ } break;
+ case TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY: {
+ vec3 sv = velocity_flags.xyz - sort_direction * dot(sort_direction, velocity_flags.xyz); //screen velocity
+ float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
+
+ if (length(sv) == 0.0) {
+ sv = align_up;
+ }
+
+ sv = normalize(sv);
+
+ txform[0].xyz = normalize(cross(sv, sort_direction)) * s;
+ txform[1].xyz = sv * s;
+ txform[2].xyz = sort_direction * s;
+
+ } break;
+ }
+
+ txform[3].xyz += velocity_flags.xyz * frame_remainder;
+
+#ifndef MODE_3D
+ // In global mode, bring 2D particles to local coordinates
+ // as they will be drawn with the node position as origin.
+ txform = inv_emission_transform * txform;
+#endif
+
+ txform = transpose(txform);
+ }
+
+ instance_color_custom_data = uvec4(packHalf2x16(color.xy), packHalf2x16(color.zw), packHalf2x16(custom.xy), packHalf2x16(custom.zw));
+ out_xform_1 = txform[0];
+ out_xform_2 = txform[1];
+#ifdef MODE_3D
+ out_xform_3 = txform[2];
+#endif
+}
+
+/* clang-format off */
+#[fragment]
+
+void main() {
+}
+/* clang-format on */
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index ed176c7829..01135a9bbd 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -102,7 +102,7 @@ vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
#ifdef USE_INSTANCING
@@ -197,7 +197,7 @@ out vec3 tangent_interp;
out vec3 binormal_interp;
#endif
-#if defined(MATERIAL_UNIFORMS_USED)
+#ifdef MATERIAL_UNIFORMS_USED
/* clang-format off */
layout(std140) uniform MaterialUniforms { // ubo:3
@@ -366,7 +366,9 @@ void main() {
#endif
#endif
+#ifndef MODE_RENDER_DEPTH
#include "tonemap_inc.glsl"
+#endif
#include "stdlib_inc.glsl"
/* texture unit usage, N is max_texture_unity-N
@@ -428,7 +430,7 @@ layout(std140) uniform GlobalShaderUniformData { //ubo:1
/* Material Uniforms */
-#if defined(MATERIAL_UNIFORMS_USED)
+#ifdef MATERIAL_UNIFORMS_USED
/* clang-format off */
layout(std140) uniform MaterialUniforms { // ubo:3
@@ -535,7 +537,7 @@ layout(std140) uniform OmniLightData { // ubo:5
LightData omni_lights[MAX_LIGHT_DATA_STRUCTS];
};
uniform uint omni_light_indices[MAX_FORWARD_LIGHTS];
-uniform int omni_light_count;
+uniform uint omni_light_count;
#endif
#ifndef DISABLE_LIGHT_SPOT
@@ -545,7 +547,7 @@ layout(std140) uniform SpotLightData { // ubo:6
LightData spot_lights[MAX_LIGHT_DATA_STRUCTS];
};
uniform uint spot_light_indices[MAX_FORWARD_LIGHTS];
-uniform int spot_light_count;
+uniform uint spot_light_count;
#endif
#ifdef USE_ADDITIVE_LIGHTING
@@ -1188,7 +1190,7 @@ void main() {
#endif //!DISABLE_LIGHT_DIRECTIONAL
#ifndef DISABLE_LIGHT_OMNI
- for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
+ for (uint i = 0u; i < MAX_FORWARD_LIGHTS; i++) {
if (i >= omni_light_count) {
break;
}
@@ -1211,7 +1213,7 @@ void main() {
#endif // !DISABLE_LIGHT_OMNI
#ifndef DISABLE_LIGHT_SPOT
- for (int i = 0; i < MAX_FORWARD_LIGHTS; i++) {
+ for (uint i = 0u; i < MAX_FORWARD_LIGHTS; i++) {
if (i >= spot_light_count) {
break;
}
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index 6748eb3676..d413c2b00e 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -34,6 +34,7 @@
#include "config.h"
#include "material_storage.h"
+#include "particles_storage.h"
#include "texture_storage.h"
#include "drivers/gles3/rasterizer_canvas_gles3.h"
@@ -1342,13 +1343,13 @@ MaterialStorage::MaterialStorage() {
shader_data_request_func[RS::SHADER_SPATIAL] = _create_scene_shader_func;
shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func;
- shader_data_request_func[RS::SHADER_PARTICLES] = nullptr;
+ shader_data_request_func[RS::SHADER_PARTICLES] = _create_particles_shader_func;
shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func;
shader_data_request_func[RS::SHADER_FOG] = nullptr;
material_data_request_func[RS::SHADER_SPATIAL] = _create_scene_material_func;
material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func;
- material_data_request_func[RS::SHADER_PARTICLES] = nullptr;
+ material_data_request_func[RS::SHADER_PARTICLES] = _create_particles_material_func;
material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
material_data_request_func[RS::SHADER_FOG] = nullptr;
@@ -1613,32 +1614,32 @@ MaterialStorage::MaterialStorage() {
{
// Setup Particles compiler
- /*
-ShaderCompiler::DefaultIdentifierActions actions;
- actions.renames["COLOR"] = "PARTICLE.color";
- actions.renames["VELOCITY"] = "PARTICLE.velocity";
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["COLOR"] = "out_color";
+ actions.renames["VELOCITY"] = "out_velocity_flags.xyz";
//actions.renames["MASS"] = "mass"; ?
actions.renames["ACTIVE"] = "particle_active";
actions.renames["RESTART"] = "restart";
- actions.renames["CUSTOM"] = "PARTICLE.custom";
- for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ actions.renames["CUSTOM"] = "out_custom";
+ for (int i = 0; i < PARTICLES_MAX_USERDATAS; i++) {
String udname = "USERDATA" + itos(i + 1);
- actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
+ actions.renames[udname] = "out_userdata" + itos(i + 1);
actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n";
}
- actions.renames["TRANSFORM"] = "PARTICLE.xform";
- actions.renames["TIME"] = "frame_history.data[0].time";
+ actions.renames["TRANSFORM"] = "xform";
+ actions.renames["TIME"] = "time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
- actions.renames["LIFETIME"] = "params.lifetime";
+ actions.renames["LIFETIME"] = "lifetime";
actions.renames["DELTA"] = "local_delta";
actions.renames["NUMBER"] = "particle_number";
actions.renames["INDEX"] = "index";
//actions.renames["GRAVITY"] = "current_gravity";
- actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
- actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
+ actions.renames["EMISSION_TRANSFORM"] = "emission_transform";
+ actions.renames["RANDOM_SEED"] = "random_seed";
actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY";
@@ -1660,18 +1661,10 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISION_SCALE\n";
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = 3;
- actions.base_uniform_string = "material.";
- actions.base_varying_index = 10;
-
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_shader_uniforms.data";
- particles_shader.compiler.initialize(actions);
- */
+ shaders.compiler_particles.initialize(actions);
}
{
@@ -2470,8 +2463,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
RS::ShaderMode new_mode;
if (mode_string == "canvas_item") {
new_mode = RS::SHADER_CANVAS_ITEM;
- //} else if (mode_string == "particles") {
- // new_mode = RS::SHADER_PARTICLES;
+ } else if (mode_string == "particles") {
+ new_mode = RS::SHADER_PARTICLES;
} else if (mode_string == "spatial") {
new_mode = RS::SHADER_SPATIAL;
} else if (mode_string == "sky") {
@@ -2542,6 +2535,9 @@ void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) {
ERR_FAIL_COND(!shader);
shader->path_hint = p_path;
+ if (shader->data) {
+ shader->data->set_path_hint(p_path);
+ }
}
String MaterialStorage::shader_get_code(RID p_shader) const {
@@ -2809,6 +2805,10 @@ void MaterialStorage::material_update_dependency(RID p_material, DependencyTrack
/* Canvas Shader Data */
+void CanvasShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void CanvasShaderData::set_code(const String &p_code) {
// compile the shader
@@ -3007,7 +3007,7 @@ GLES3::ShaderData *GLES3::_create_canvas_shader_func() {
}
void CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
+ update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
}
void CanvasMaterialData::bind_uniforms() {
@@ -3043,6 +3043,10 @@ GLES3::MaterialData *GLES3::_create_canvas_material_func(ShaderData *p_shader) {
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
+void SkyShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SkyShaderData::set_code(const String &p_code) {
//compile
@@ -3251,7 +3255,7 @@ GLES3::ShaderData *GLES3::_create_sky_shader_func() {
void SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
uniform_set_updated = true;
- return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
+ update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
}
SkyMaterialData::~SkyMaterialData() {
@@ -3286,6 +3290,10 @@ void SkyMaterialData::bind_uniforms() {
////////////////////////////////////////////////////////////////////////////////
// Scene SHADER
+void SceneShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SceneShaderData::set_code(const String &p_code) {
//compile
@@ -3358,6 +3366,9 @@ void SceneShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
+ // Use alpha clip pipeline for alpha hash/dither.
+ // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows.
+ actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -3418,6 +3429,8 @@ void SceneShaderData::set_code(const String &p_code) {
vertex_input_mask |= uses_bones << 9;
vertex_input_mask |= uses_weights << 10;
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+ uses_vertex_time = gen_code.uses_vertex_time;
+ uses_fragment_time = gen_code.uses_fragment_time;
#if 0
print_line("**compiling shader:");
@@ -3538,11 +3551,15 @@ bool SceneShaderData::is_parameter_texture(const StringName &p_param) const {
}
bool SceneShaderData::is_animated() const {
- return false;
+ return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
}
bool SceneShaderData::casts_shadows() const {
- return false;
+ bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
+ bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
+ bool has_alpha = has_base_alpha || uses_blend_alpha;
+
+ return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
}
Variant SceneShaderData::get_default_parameter(const StringName &p_parameter) const {
@@ -3583,7 +3600,7 @@ void SceneMaterialData::set_next_pass(RID p_pass) {
}
void SceneMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
+ update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
}
SceneMaterialData::~SceneMaterialData() {
@@ -3616,4 +3633,209 @@ void SceneMaterialData::bind_uniforms() {
}
}
+/* Particles SHADER */
+
+void ParticlesShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
+void ParticlesShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+ uses_collision = false;
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["start"] = ShaderCompiler::STAGE_VERTEX;
+ actions.entry_point_stages["process"] = ShaderCompiler::STAGE_VERTEX;
+
+ actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
+
+ userdata_count = 0;
+ for (uint32_t i = 0; i < PARTICLES_MAX_USERDATAS; i++) {
+ userdatas_used[i] = false;
+ actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i];
+ }
+
+ actions.uniforms = &uniforms;
+
+ Error err = MaterialStorage::get_singleton()->shaders.compiler_particles.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+
+ if (version.is_null()) {
+ version = MaterialStorage::get_singleton()->shaders.particles_process_shader.version_create();
+ }
+
+ for (uint32_t i = 0; i < PARTICLES_MAX_USERDATAS; i++) {
+ if (userdatas_used[i]) {
+ userdata_count++;
+ }
+ }
+
+ Vector<StringName> texture_uniform_names;
+ for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
+ texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
+ }
+
+ MaterialStorage::get_singleton()->shaders.particles_process_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.particles_process_shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ valid = true;
+}
+
+void ParticlesShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = HashMap<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void ParticlesShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
+ HashMap<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ String last_group;
+ for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool ParticlesShaderData::is_parameter_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool ParticlesShaderData::is_animated() const {
+ return false;
+}
+
+bool ParticlesShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode ParticlesShaderData::get_native_source_code() const {
+ return MaterialStorage::get_singleton()->shaders.particles_process_shader.version_get_native_source_code(version);
+}
+
+ParticlesShaderData::~ParticlesShaderData() {
+ if (version.is_valid()) {
+ MaterialStorage::get_singleton()->shaders.particles_process_shader.version_free(version);
+ }
+}
+
+GLES3::ShaderData *GLES3::_create_particles_shader_func() {
+ ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
+ return shader_data;
+}
+
+void ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
+}
+
+ParticleProcessMaterialData::~ParticleProcessMaterialData() {
+}
+
+GLES3::MaterialData *GLES3::_create_particles_material_func(ShaderData *p_shader) {
+ ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData);
+ material_data->shader_data = static_cast<ParticlesShaderData *>(p_shader);
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+void ParticleProcessMaterialData::bind_uniforms() {
+ // Bind Material Uniforms
+ glBindBufferBase(GL_UNIFORM_BUFFER, GLES3::PARTICLES_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
+
+ RID *textures = texture_cache.ptrw();
+ ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
+ for (int ti = 0; ti < texture_cache.size(); ti++) {
+ Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
+ glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 becuase texture slot 0 is reserved for the heightmap texture.
+ glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
+
+ // Set sampler state here as the same texture can be used in multiple places with different flags
+ // Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
+ RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX);
+ RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
+ texture->gl_set_filter(filter);
+ texture->gl_set_repeat(repeat);
+ }
+}
+
#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 24d9a0fee1..8ae5e5eb9c 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -44,6 +44,7 @@
#include "../shaders/canvas.glsl.gen.h"
#include "../shaders/cubemap_filter.glsl.gen.h"
+#include "../shaders/particles.glsl.gen.h"
#include "../shaders/scene.glsl.gen.h"
#include "../shaders/sky.glsl.gen.h"
@@ -53,6 +54,7 @@ namespace GLES3 {
struct ShaderData {
virtual void set_code(const String &p_Code) = 0;
+ virtual void set_path_hint(const String &p_hint) = 0;
virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) = 0;
virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0;
@@ -165,6 +167,7 @@ struct CanvasShaderData : public ShaderData {
bool uses_time = false;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -216,6 +219,7 @@ struct SkyShaderData : public ShaderData {
bool uses_light;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -318,6 +322,8 @@ struct SceneShaderData : public ShaderData {
bool uses_depth_texture;
bool uses_normal_texture;
bool uses_time;
+ bool uses_vertex_time;
+ bool uses_fragment_time;
bool writes_modelview_or_projection;
bool uses_world_coordinates;
bool uses_tangent;
@@ -337,6 +343,7 @@ struct SceneShaderData : public ShaderData {
uint32_t index = 0;
virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_hint);
virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
@@ -368,6 +375,62 @@ struct SceneMaterialData : public MaterialData {
MaterialData *_create_scene_material_func(ShaderData *p_shader);
+/* Particle Shader */
+
+enum {
+ PARTICLES_MAX_USERDATAS = 6
+};
+
+struct ParticlesShaderData : public ShaderData {
+ bool valid = false;
+ RID version;
+ bool uses_collision = false;
+
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size = 0;
+
+ String path;
+ String code;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
+
+ bool uses_time = false;
+
+ bool userdatas_used[PARTICLES_MAX_USERDATAS] = {};
+ uint32_t userdata_count = 0;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_path_hint(const String &p_hint);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_parameter_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ ParticlesShaderData() {}
+ virtual ~ParticlesShaderData();
+};
+
+ShaderData *_create_particles_shader_func();
+
+struct ParticleProcessMaterialData : public MaterialData {
+ ParticlesShaderData *shader_data = nullptr;
+ RID uniform_set;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual void bind_uniforms();
+ virtual ~ParticleProcessMaterialData();
+};
+
+MaterialData *_create_particles_material_func(ShaderData *p_shader);
+
/* Global shader uniform structs */
struct GlobalShaderUniforms {
enum {
@@ -504,6 +567,7 @@ public:
SkyShaderGLES3 sky_shader;
SceneShaderGLES3 scene_shader;
CubemapFilterShaderGLES3 cubemap_filter_shader;
+ ParticlesShaderGLES3 particles_process_shader;
ShaderCompiler compiler_canvas;
ShaderCompiler compiler_scene;
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 9ec0fc0286..a47df42500 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -87,8 +87,11 @@ void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count
ERR_FAIL_COND(!mesh);
ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
- WARN_PRINT_ONCE("blend shapes not supported by GLES3 renderer yet");
mesh->blend_shape_count = p_blend_shape_count;
+
+ if (p_blend_shape_count > 0) {
+ WARN_PRINT_ONCE("blend shapes not supported by GLES3 renderer yet");
+ }
}
bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index a31db24f2d..1aef3cbf78 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -327,6 +327,7 @@ public:
_FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t &r_index_count) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ ERR_FAIL_COND_V(!s, 0);
int32_t current_lod = -1;
r_index_count = s->index_count;
@@ -403,6 +404,8 @@ public:
virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
virtual void update_mesh_instances() override;
+ // TODO: considering hashing versions with multimesh buffer RID.
+ // Doing so would allow us to avoid specifying multimesh buffer pointers every frame and may improve performance.
_FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, GLuint &r_vertex_array_gl) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_COND(!mi);
diff --git a/drivers/gles3/storage/particles_storage.cpp b/drivers/gles3/storage/particles_storage.cpp
index 9ed9fedd5a..1a0d97df01 100644
--- a/drivers/gles3/storage/particles_storage.cpp
+++ b/drivers/gles3/storage/particles_storage.cpp
@@ -31,6 +31,12 @@
#ifdef GLES3_ENABLED
#include "particles_storage.h"
+#include "material_storage.h"
+#include "mesh_storage.h"
+#include "texture_storage.h"
+#include "utilities.h"
+
+#include "servers/rendering/rendering_server_default.h"
using namespace GLES3;
@@ -42,213 +48,1338 @@ ParticlesStorage *ParticlesStorage::get_singleton() {
ParticlesStorage::ParticlesStorage() {
singleton = this;
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
+ {
+ String global_defines;
+ global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
+ material_storage->shaders.particles_process_shader.initialize(global_defines);
+ }
+ {
+ // default material and shader for particles shader
+ particles_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(particles_shader.default_shader);
+ material_storage->shader_set_code(particles_shader.default_shader, R"(
+// Default particles shader.
+
+shader_type particles;
+
+void process() {
+ COLOR = vec4(1.0);
+}
+)");
+ particles_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(particles_shader.default_material);
+ material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
+ }
+ {
+ particles_shader.copy_shader.initialize();
+ particles_shader.copy_shader_version = particles_shader.copy_shader.version_create();
+ }
}
ParticlesStorage::~ParticlesStorage() {
singleton = nullptr;
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
+ material_storage->material_free(particles_shader.default_material);
+ material_storage->shader_free(particles_shader.default_shader);
+ particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
}
/* PARTICLES */
RID ParticlesStorage::particles_allocate() {
- return RID();
+ return particles_owner.allocate_rid();
}
void ParticlesStorage::particles_initialize(RID p_rid) {
+ particles_owner.initialize_rid(p_rid, Particles());
}
void ParticlesStorage::particles_free(RID p_rid) {
+ update_particles();
+ Particles *particles = particles_owner.get_or_null(p_rid);
+ particles->dependency.deleted_notify(p_rid);
+ _particles_free_data(particles);
+ particles_owner.free(p_rid);
}
void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ if (particles->mode == p_mode) {
+ return;
+ }
-void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+ _particles_free_data(particles);
+
+ particles->mode = p_mode;
}
void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->emitting = p_emitting;
+}
+
+bool ParticlesStorage::particles_get_emitting(RID p_particles) {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->emitting;
+}
+
+void ParticlesStorage::_particles_free_data(Particles *particles) {
+ particles->userdata_count = 0;
+ particles->instance_buffer_size_cache = 0;
+ particles->instance_buffer_stride_cache = 0;
+ particles->num_attrib_arrays_cache = 0;
+ particles->process_buffer_stride_cache = 0;
+
+ if (particles->front_process_buffer != 0) {
+ glDeleteVertexArrays(1, &particles->front_vertex_array);
+ glDeleteBuffers(1, &particles->front_process_buffer);
+ glDeleteBuffers(1, &particles->front_instance_buffer);
+ particles->front_vertex_array = 0;
+ particles->front_process_buffer = 0;
+ particles->front_instance_buffer = 0;
+
+ glDeleteVertexArrays(1, &particles->back_vertex_array);
+ glDeleteBuffers(1, &particles->back_process_buffer);
+ glDeleteBuffers(1, &particles->back_instance_buffer);
+ particles->back_vertex_array = 0;
+ particles->back_process_buffer = 0;
+ particles->back_instance_buffer = 0;
+ }
+
+ if (particles->sort_buffer != 0) {
+ glDeleteBuffers(1, &particles->last_frame_buffer);
+ glDeleteBuffers(1, &particles->sort_buffer);
+ particles->last_frame_buffer = 0;
+ particles->sort_buffer = 0;
+ particles->sort_buffer_filled = false;
+ particles->last_frame_buffer_filled = false;
+ }
+
+ if (particles->frame_params_ubo != 0) {
+ glDeleteBuffers(1, &particles->frame_params_ubo);
+ particles->frame_params_ubo = 0;
+ }
}
void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->amount == p_amount) {
+ return;
+ }
+
+ _particles_free_data(particles);
+
+ particles->amount = p_amount;
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->lifetime = p_lifetime;
}
void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->one_shot = p_one_shot;
}
void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->pre_process_time = p_time;
}
-
void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->explosiveness = p_ratio;
}
-
void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->randomness = p_ratio;
}
void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->custom_aabb = p_aabb;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
-}
-
-void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+ particles->speed_scale = p_scale;
}
+void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
- return RID();
+ particles->use_local_coords = p_enable;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fixed_fps = p_fps;
+
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->interpolate = p_enable;
}
void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fractional_delta = p_enable;
}
-void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+ if (p_enable) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support particle trails");
+ }
}
-void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+ if (p_bind_poses.size() != 0) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support particle trails");
+ }
}
void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->collision_base_size = p_size;
}
void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+ particles->transform_align = p_transform_align;
}
-void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->process_material = p_material;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
}
-void ParticlesStorage::particles_restart(RID p_particles) {
+RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+
+ return particles->process_material;
}
void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_order = p_order;
}
-void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_count) {
+void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_passes) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_passes.resize(p_passes);
}
void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
+ particles->draw_passes.write[p_pass] = p_mesh;
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_restart(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->restart_request = true;
+}
+
+void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+ if (p_subemitter_particles.is_valid()) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support particle sub emitters");
+ }
+}
+
+void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support manually emitting particles");
}
void ParticlesStorage::particles_request_process(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (!particles->dirty) {
+ particles->dirty = true;
+ particles->update_list = particle_update_list;
+ particle_update_list = particles;
+ }
}
AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
- return AABB();
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
+ }
+
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ int total_amount = particles->amount;
+
+ // If available, read from the sort buffer which should be 2 frames out of date.
+ // This will help alleviate GPU stalls.
+ GLuint read_buffer = particles->sort_buffer_filled ? particles->sort_buffer : particles->back_instance_buffer;
+
+ Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, read_buffer, total_amount * sizeof(ParticleInstanceData3D));
+ ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleInstanceData3D)), AABB());
+
+ Transform3D inv = particles->emission_transform.affine_inverse();
+
+ AABB aabb;
+ if (buffer.size()) {
+ bool first = true;
+
+ const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
+ uint32_t particle_data_size = sizeof(ParticleInstanceData3D) + sizeof(float) * particles->userdata_count;
+
+ for (int i = 0; i < total_amount; i++) {
+ const ParticleInstanceData3D &particle_data = *(const ParticleInstanceData3D *)&data_ptr[particle_data_size * i];
+ // If scale is 0.0, we assume the particle is inactive.
+ if (particle_data.xform[0] > 0.0) {
+ Vector3 pos = Vector3(particle_data.xform[3], particle_data.xform[7], particle_data.xform[11]);
+ if (!particles->use_local_coords) {
+ pos = inv.xform(pos);
+ }
+ if (first) {
+ aabb.position = pos;
+ first = false;
+ } else {
+ aabb.expand_to(pos);
+ }
+ }
+ }
+ }
+
+ float longest_axis_size = 0;
+ for (int i = 0; i < particles->draw_passes.size(); i++) {
+ if (particles->draw_passes[i].is_valid()) {
+ AABB maabb = MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID());
+ longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
+ }
+ }
+
+ aabb.grow_by(longest_axis_size);
+
+ return aabb;
}
AABB ParticlesStorage::particles_get_aabb(RID p_particles) const {
- return AABB();
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ return particles->custom_aabb;
}
void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
-}
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
-bool ParticlesStorage::particles_get_emitting(RID p_particles) {
- return false;
+ particles->emission_transform = p_transform;
}
int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
- return 0;
-}
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
-RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
- return RID();
+ return particles->draw_passes.size();
}
-void ParticlesStorage::particles_add_collision(RID p_particles, RID p_instance) {
+RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+ ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
+
+ return particles->draw_passes[p_pass];
}
-void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_instance) {
+void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.insert(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.erase(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, GLuint p_texture) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->has_sdf_collision = p_enable;
+ particles->sdf_collision_transform = p_xform;
+ particles->sdf_collision_to_screen = p_to_screen;
+ particles->sdf_collision_texture = p_texture;
+}
+
+// Does one step of processing particles by reading from back_process_buffer and writing to front_process_buffer.
+void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta) {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+
+ double new_phase = Math::fmod(p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
+
+ //update current frame
+ ParticlesFrameParams frame_params;
+
+ if (p_particles->clear) {
+ p_particles->cycle_number = 0;
+ p_particles->random_seed = Math::rand();
+ } else if (new_phase < p_particles->phase) {
+ if (p_particles->one_shot) {
+ p_particles->emitting = false;
+ }
+ p_particles->cycle_number++;
+ }
+
+ frame_params.emitting = p_particles->emitting;
+ frame_params.system_phase = new_phase;
+ frame_params.prev_system_phase = p_particles->phase;
+
+ p_particles->phase = new_phase;
+
+ frame_params.time = RSG::rasterizer->get_total_time();
+ frame_params.delta = p_delta * p_particles->speed_scale;
+ frame_params.random_seed = p_particles->random_seed;
+ frame_params.explosiveness = p_particles->explosiveness;
+ frame_params.randomness = p_particles->randomness;
+
+ if (p_particles->use_local_coords) {
+ GLES3::MaterialStorage::store_transform(Transform3D(), frame_params.emission_transform);
+ } else {
+ GLES3::MaterialStorage::store_transform(p_particles->emission_transform, frame_params.emission_transform);
+ }
+
+ frame_params.cycle = p_particles->cycle_number;
+ frame_params.frame = p_particles->frame_counter++;
+ frame_params.pad0 = 0;
+ frame_params.pad1 = 0;
+ frame_params.pad2 = 0;
+
+ { //collision and attractors
+
+ frame_params.collider_count = 0;
+ frame_params.attractor_count = 0;
+ frame_params.particle_size = p_particles->collision_base_size;
+
+ GLuint collision_heightmap_texture = 0;
+
+ Transform3D to_particles;
+ if (p_particles->use_local_coords) {
+ to_particles = p_particles->emission_transform.affine_inverse();
+ }
+
+ if (p_particles->has_sdf_collision && p_particles->sdf_collision_texture != 0) {
+ //2D collision
+
+ Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
+ Transform2D revert = xform.affine_inverse();
+ frame_params.collider_count = 1;
+ frame_params.colliders[0].transform[0] = xform.columns[0][0];
+ frame_params.colliders[0].transform[1] = xform.columns[0][1];
+ frame_params.colliders[0].transform[2] = 0;
+ frame_params.colliders[0].transform[3] = xform.columns[2][0];
+
+ frame_params.colliders[0].transform[4] = xform.columns[1][0];
+ frame_params.colliders[0].transform[5] = xform.columns[1][1];
+ frame_params.colliders[0].transform[6] = 0;
+ frame_params.colliders[0].transform[7] = xform.columns[2][1];
+
+ frame_params.colliders[0].transform[8] = revert.columns[0][0];
+ frame_params.colliders[0].transform[9] = revert.columns[0][1];
+ frame_params.colliders[0].transform[10] = 0;
+ frame_params.colliders[0].transform[11] = revert.columns[2][0];
+
+ frame_params.colliders[0].transform[12] = revert.columns[1][0];
+ frame_params.colliders[0].transform[13] = revert.columns[1][1];
+ frame_params.colliders[0].transform[14] = 0;
+ frame_params.colliders[0].transform[15] = revert.columns[2][1];
+
+ frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
+ frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
+ frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
+ frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
+ frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
+
+ collision_heightmap_texture = p_particles->sdf_collision_texture;
+ }
+
+ for (const RID &E : p_particles->collisions) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E);
+ if (!pci || !pci->active) {
+ continue;
+ }
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
+ ERR_CONTINUE(!pc);
+
+ Transform3D to_collider = pci->transform;
+ if (p_particles->use_local_coords) {
+ to_collider = to_particles * to_collider;
+ }
+ Vector3 scale = to_collider.basis.get_scale();
+ to_collider.basis.orthonormalize();
+
+ if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
+ //attractor
+ if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
+
+ GLES3::MaterialStorage::store_transform(to_collider, attr.transform);
+ attr.strength = pc->attractor_strength;
+ attr.attenuation = pc->attractor_attenuation;
+ attr.directionality = pc->attractor_directionality;
+
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ attr.extents[0] = radius;
+ attr.extents[1] = radius;
+ attr.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ attr.extents[0] = extents.x;
+ attr.extents[1] = extents.y;
+ attr.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
+ WARN_PRINT_ONCE("Vector field particle attractors are not available in the OpenGL2 renderer.");
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.attractor_count++;
+ } else {
+ //collider
+ if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
+
+ GLES3::MaterialStorage::store_transform(to_collider, col.transform);
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ col.extents[0] = radius;
+ col.extents[1] = radius;
+ col.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
+ WARN_PRINT_ONCE("SDF Particle Colliders are not available in the OpenGL 3 renderer.");
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
+ if (collision_heightmap_texture != 0) { //already taken
+ continue;
+ }
+
+ col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ collision_heightmap_texture = pc->heightfield_texture;
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.collider_count++;
+ }
+ }
+
+ // Bind heightmap or SDF texture.
+ GLuint heightmap = collision_heightmap_texture;
+ if (heightmap == 0) {
+ GLES3::Texture *tex = texture_storage->get_texture(texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_BLACK));
+ heightmap = tex->tex_id;
+ }
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, heightmap);
+ }
+
+ if (p_particles->frame_params_ubo == 0) {
+ glGenBuffers(1, &p_particles->frame_params_ubo);
+ }
+ // Update per-frame UBO.
+ glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLES_FRAME_UNIFORM_LOCATION, p_particles->frame_params_ubo);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(ParticlesFrameParams), &frame_params, GL_STREAM_DRAW);
+
+ // Get shader and set shader uniforms;
+ ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, RS::SHADER_PARTICLES));
+ if (!m) {
+ m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RS::SHADER_PARTICLES));
+ }
+
+ ERR_FAIL_COND(!m);
+
+ ParticlesShaderGLES3::ShaderVariant variant = ParticlesShaderGLES3::MODE_DEFAULT;
+
+ uint32_t specialization = 0;
+ for (uint32_t i = 0; i < p_particles->userdata_count; i++) {
+ specialization |= (1 << i);
+ }
+
+ if (p_particles->mode == RS::ParticlesMode::PARTICLES_MODE_3D) {
+ specialization |= ParticlesShaderGLES3::MODE_3D;
+ }
+
+ RID version = particles_shader.default_shader_version;
+ if (m->shader_data->version.is_valid() && m->shader_data->valid) {
+ // Bind material uniform buffer and textures.
+ m->bind_uniforms();
+ version = m->shader_data->version;
+ }
+
+ bool success = material_storage->shaders.particles_process_shader.version_bind_shader(version, variant, specialization);
+ if (!success) {
+ return;
+ }
+
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::LIFETIME, p_particles->lifetime, version, variant, specialization);
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::CLEAR, p_particles->clear, version, variant, specialization);
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::TOTAL_PARTICLES, uint32_t(p_particles->amount), version, variant, specialization);
+ material_storage->shaders.particles_process_shader.version_set_uniform(ParticlesShaderGLES3::USE_FRACTIONAL_DELTA, p_particles->fractional_delta, version, variant, specialization);
+
+ p_particles->clear = false;
+
+ p_particles->has_collision_cache = m->shader_data->uses_collision;
+
+ glBindVertexArray(p_particles->back_vertex_array);
+
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, p_particles->front_process_buffer);
+
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, p_particles->amount);
+ glEndTransformFeedback();
+
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
+ glBindVertexArray(0);
+
+ SWAP(p_particles->front_process_buffer, p_particles->back_process_buffer);
+ SWAP(p_particles->front_vertex_array, p_particles->back_vertex_array);
}
-void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ return;
+ }
+
+ if (particles->front_process_buffer == 0) {
+ return; //particles have not processed yet
+ }
+
+ Vector3 axis = -p_axis; // cameras look to z negative
+
+ if (particles->use_local_coords) {
+ axis = particles->emission_transform.basis.xform_inv(axis).normalized();
+ }
+
+ // Sort will be done on CPU since we don't have compute shaders.
+ // If the sort_buffer has valid data
+ // Use a buffer that is 2 frames out of date to avoid stalls.
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->sort_buffer_filled) {
+ glBindBuffer(GL_ARRAY_BUFFER, particles->sort_buffer);
+
+ ParticleInstanceData3D *particle_array;
+#ifndef __EMSCRIPTEN__
+ particle_array = static_cast<ParticleInstanceData3D *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(ParticleInstanceData3D), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
+ ERR_FAIL_NULL(particle_array);
+#else
+ LocalVector<ParticleInstanceData3D> particle_vector;
+ particle_vector.resize(particles->amount);
+ particle_array = particle_vector.ptr();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(ParticleInstanceData3D), particle_array);
+#endif
+ SortArray<ParticleInstanceData3D, ParticlesViewSort> sorter;
+ sorter.compare.z_dir = axis;
+ sorter.sort(particle_array, particles->amount);
+
+#ifndef __EMSCRIPTEN__
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#else
+ glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(ParticleInstanceData3D), particle_vector.ptr());
+#endif
+ }
+
+ glEnable(GL_RASTERIZER_DISCARD);
+ _particles_update_instance_buffer(particles, axis, p_up_axis);
+ glDisable(GL_RASTERIZER_DISCARD);
+}
+
+void ParticlesStorage::_particles_update_buffers(Particles *particles) {
+ GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
+ uint32_t userdata_count = 0;
+
+ if (particles->process_material.is_valid()) {
+ GLES3::ParticleProcessMaterialData *material_data = static_cast<GLES3::ParticleProcessMaterialData *>(material_storage->material_get_data(particles->process_material, RS::SHADER_PARTICLES));
+ if (material_data && material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
+ userdata_count = material_data->shader_data->userdata_count;
+ }
+ }
+
+ if (userdata_count != particles->userdata_count) {
+ // Mismatch userdata, re-create buffers.
+ _particles_free_data(particles);
+ }
+
+ if (particles->amount > 0 && particles->front_process_buffer == 0) {
+ int total_amount = particles->amount;
+
+ particles->userdata_count = userdata_count;
+
+ uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
+ particles->instance_buffer_stride_cache = sizeof(float) * 4 * (xform_size + 1);
+ particles->instance_buffer_size_cache = particles->instance_buffer_stride_cache * total_amount;
+ particles->num_attrib_arrays_cache = 5 + userdata_count + (xform_size - 2);
+ particles->process_buffer_stride_cache = sizeof(float) * 4 * particles->num_attrib_arrays_cache;
+
+ int process_data_amount = 4 * particles->num_attrib_arrays_cache * total_amount;
+ float *data = memnew_arr(float, process_data_amount);
+
+ for (int i = 0; i < process_data_amount; i++) {
+ data[i] = 0;
+ }
+
+ {
+ glGenVertexArrays(1, &particles->front_vertex_array);
+ glBindVertexArray(particles->front_vertex_array);
+ glGenBuffers(1, &particles->front_process_buffer);
+ glGenBuffers(1, &particles->front_instance_buffer);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->front_process_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY);
+
+ for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) {
+ glEnableVertexAttribArray(j);
+ glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, particles->process_buffer_stride_cache, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * j));
+ }
+ glBindVertexArray(0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->front_instance_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY);
+ }
+
+ {
+ glGenVertexArrays(1, &particles->back_vertex_array);
+ glBindVertexArray(particles->back_vertex_array);
+ glGenBuffers(1, &particles->back_process_buffer);
+ glGenBuffers(1, &particles->back_instance_buffer);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->back_process_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->process_buffer_stride_cache * total_amount, data, GL_DYNAMIC_COPY);
+
+ for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) {
+ glEnableVertexAttribArray(j);
+ glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, particles->process_buffer_stride_cache, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * j));
+ }
+ glBindVertexArray(0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->back_instance_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_COPY);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ memdelete_arr(data);
+ }
+}
+
+void ParticlesStorage::_particles_allocate_history_buffers(Particles *particles) {
+ if (particles->sort_buffer == 0) {
+ glGenBuffers(1, &particles->last_frame_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, particles->last_frame_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ);
+
+ glGenBuffers(1, &particles->sort_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, particles->sort_buffer);
+ glBufferData(GL_ARRAY_BUFFER, particles->instance_buffer_size_cache, nullptr, GL_DYNAMIC_READ);
+ particles->sort_buffer_filled = false;
+ particles->last_frame_buffer_filled = false;
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+}
+void ParticlesStorage::_particles_update_instance_buffer(Particles *particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+ ParticlesCopyShaderGLES3::ShaderVariant variant = ParticlesCopyShaderGLES3::MODE_DEFAULT;
+
+ uint64_t specialization = 0;
+ if (particles->mode == RS::ParticlesMode::PARTICLES_MODE_3D) {
+ specialization |= ParticlesCopyShaderGLES3::MODE_3D;
+ }
+
+ bool success = particles_shader.copy_shader.version_bind_shader(particles_shader.copy_shader_version, variant, specialization);
+ if (!success) {
+ return;
+ }
+
+ // Affect 2D only.
+ if (particles->use_local_coords) {
+ // In local mode, particle positions are calculated locally (relative to the node position)
+ // and they're also drawn locally.
+ // It works as expected, so we just pass an identity transform.
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::INV_EMISSION_TRANSFORM, Transform3D(), particles_shader.copy_shader_version, variant, specialization);
+ } else {
+ // In global mode, particle positions are calculated globally (relative to the canvas origin)
+ // but they're drawn locally.
+ // So, we need to pass the inverse of the emission transform to bring the
+ // particles to local coordinates before drawing.
+ Transform3D inv = particles->emission_transform.affine_inverse();
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::INV_EMISSION_TRANSFORM, inv, particles_shader.copy_shader_version, variant, specialization);
+ }
+
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::FRAME_REMAINDER, particles->interpolate ? particles->frame_remainder : 0.0, particles_shader.copy_shader_version, variant, specialization);
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_MODE, uint32_t(particles->transform_align), particles_shader.copy_shader_version, variant, specialization);
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::ALIGN_UP, p_up_axis, particles_shader.copy_shader_version, variant, specialization);
+ particles_shader.copy_shader.version_set_uniform(ParticlesCopyShaderGLES3::SORT_DIRECTION, p_axis, particles_shader.copy_shader_version, variant, specialization);
+
+ glBindVertexArray(particles->back_vertex_array);
+ glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->front_instance_buffer, 0, particles->instance_buffer_size_cache);
+ glBeginTransformFeedback(GL_POINTS);
+
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME) {
+ uint32_t lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ uint32_t stride = particles->process_buffer_stride_cache;
+
+ glBindBuffer(GL_ARRAY_BUFFER, particles->back_process_buffer);
+
+ // Offset VBO so you render starting at the newest particle.
+ if (particles->amount - lifetime_split > 0) {
+ glEnableVertexAttribArray(0); // Color.
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 0));
+ glEnableVertexAttribArray(1); // .xyz: velocity. .z: flags.
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 1));
+ glEnableVertexAttribArray(2); // Custom.
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 2));
+ glEnableVertexAttribArray(3); // Xform1.
+ glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 3));
+ glEnableVertexAttribArray(4); // Xform2.
+ glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 4));
+ if (particles->mode == RS::PARTICLES_MODE_3D) {
+ glEnableVertexAttribArray(5); // Xform3.
+ glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * lifetime_split + sizeof(float) * 4 * 5));
+ }
+
+ uint32_t to_draw = particles->amount - lifetime_split;
+ glDrawArrays(GL_POINTS, 0, to_draw);
+ }
+
+ // Then render from index 0 up intil the newest particle.
+ if (lifetime_split > 0) {
+ glEndTransformFeedback();
+ // Now output to the second portion of the instance buffer.
+ glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->front_instance_buffer, particles->instance_buffer_stride_cache * (particles->amount - lifetime_split), particles->instance_buffer_stride_cache * (lifetime_split));
+ glBeginTransformFeedback(GL_POINTS);
+ // Reset back to normal.
+ for (uint32_t j = 0; j < particles->num_attrib_arrays_cache; j++) {
+ glEnableVertexAttribArray(j);
+ glVertexAttribPointer(j, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * j));
+ }
+
+ glDrawArrays(GL_POINTS, 0, lifetime_split);
+ }
+ } else {
+ glDrawArrays(GL_POINTS, 0, particles->amount);
+ }
+
+ glEndTransformFeedback();
+ glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, 0, 0);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void ParticlesStorage::update_particles() {
+ glEnable(GL_RASTERIZER_DISCARD);
+
+ GLuint global_buffer = GLES3::MaterialStorage::get_singleton()->global_shader_parameters_get_uniform_buffer();
+
+ glBindBufferBase(GL_UNIFORM_BUFFER, PARTICLES_GLOBALS_UNIFORM_LOCATION, global_buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+ while (particle_update_list) {
+ // Use transform feedback to process particles.
+
+ Particles *particles = particle_update_list;
+
+ particle_update_list = particles->update_list;
+ particles->update_list = nullptr;
+ particles->dirty = false;
+
+ _particles_update_buffers(particles);
+
+ if (particles->restart_request) {
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ particles->restart_request = false;
+ }
+
+ if (particles->inactive && !particles->emitting) {
+ //go next
+ continue;
+ }
+
+ if (particles->emitting) {
+ if (particles->inactive) {
+ //restart system from scratch
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ }
+ particles->inactive = false;
+ particles->inactive_time = 0;
+ } else {
+ particles->inactive_time += particles->speed_scale * RSG::rasterizer->get_frame_delta_time();
+ if (particles->inactive_time > particles->lifetime * 1.2) {
+ particles->inactive = true;
+ continue;
+ }
+ }
+
+ // Copy the instance buffer that was last used into the last_frame buffer.
+ // sort_buffer should now be 2 frames out of date.
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME) {
+ _particles_allocate_history_buffers(particles);
+ SWAP(particles->last_frame_buffer, particles->sort_buffer);
+
+ glBindBuffer(GL_COPY_READ_BUFFER, particles->back_instance_buffer);
+ glBindBuffer(GL_COPY_WRITE_BUFFER, particles->last_frame_buffer);
+ glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, particles->instance_buffer_size_cache);
+
+ // Last frame's last_frame turned into this frame's sort buffer.
+ particles->sort_buffer_filled = particles->last_frame_buffer_filled;
+ particles->sort_buffer_phase = particles->last_frame_phase;
+ particles->last_frame_buffer_filled = true;
+ particles->last_frame_phase = particles->phase;
+ glBindBuffer(GL_COPY_READ_BUFFER, 0);
+ glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
+ }
+
+ int fixed_fps = 0;
+ if (particles->fixed_fps > 0) {
+ fixed_fps = particles->fixed_fps;
+ }
+
+ bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
+
+ if (particles->clear && particles->pre_process_time > 0.0) {
+ double frame_time;
+ if (fixed_fps > 0) {
+ frame_time = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / 30.0;
+ }
+
+ double todo = particles->pre_process_time;
+
+ while (todo >= 0) {
+ _particles_process(particles, frame_time);
+ todo -= frame_time;
+ }
+ }
+
+ if (fixed_fps > 0) {
+ double frame_time;
+ double decr;
+ if (zero_time_scale) {
+ frame_time = 0.0;
+ decr = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / fixed_fps;
+ decr = frame_time;
+ }
+ double delta = RSG::rasterizer->get_frame_delta_time();
+ if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
+ delta = 0.1;
+ } else if (delta <= 0.0) { //unlikely but..
+ delta = 0.001;
+ }
+ double todo = particles->frame_remainder + delta;
+
+ while (todo >= frame_time) {
+ _particles_process(particles, frame_time);
+ todo -= decr;
+ }
+
+ particles->frame_remainder = todo;
+
+ } else {
+ if (zero_time_scale) {
+ _particles_process(particles, 0.0);
+ } else {
+ _particles_process(particles, RSG::rasterizer->get_frame_delta_time());
+ }
+ }
+
+ // Copy particles to instance buffer and pack Color/Custom.
+ // We don't have camera information here, so don't copy here if we need camera information for view depth or align mode.
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ _particles_update_instance_buffer(particles, Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0));
+
+ if (particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME && particles->sort_buffer_filled) {
+ if (particles->mode == RS::ParticlesMode::PARTICLES_MODE_2D) {
+ _particles_reverse_lifetime_sort<ParticleInstanceData2D>(particles);
+ } else {
+ _particles_reverse_lifetime_sort<ParticleInstanceData3D>(particles);
+ }
+ }
+ }
+
+ SWAP(particles->front_instance_buffer, particles->back_instance_buffer);
+
+ // At the end of update, the back_buffer contains the most up-to-date-information to read from.
+
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+ }
+
+ glDisable(GL_RASTERIZER_DISCARD);
+}
+
+template <typename ParticleInstanceData>
+void ParticlesStorage::_particles_reverse_lifetime_sort(Particles *particles) {
+ glBindBuffer(GL_ARRAY_BUFFER, particles->sort_buffer);
+
+ ParticleInstanceData *particle_array;
+ uint32_t buffer_size = particles->amount * sizeof(ParticleInstanceData);
+#ifndef __EMSCRIPTEN__
+ particle_array = static_cast<ParticleInstanceData *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, buffer_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
+
+ ERR_FAIL_NULL(particle_array);
+#else
+ LocalVector<ParticleInstanceData> particle_vector;
+ particle_vector.resize(particles->amount);
+ particle_array = particle_vector.ptr();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, buffer_size, particle_array);
+#endif
+
+ uint32_t lifetime_split = MIN(particles->amount * particles->sort_buffer_phase, particles->amount - 1);
+
+ for (uint32_t i = 0; i < lifetime_split / 2; i++) {
+ SWAP(particle_array[i], particle_array[lifetime_split - i]);
+ }
+
+ for (uint32_t i = 0; i < (particles->amount - lifetime_split) / 2; i++) {
+ SWAP(particle_array[lifetime_split + i + 1], particle_array[particles->amount - 1 - i]);
+ }
+
+#ifndef __EMSCRIPTEN__
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#else
+ glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_size, particle_vector.ptr());
+#endif
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_NULL_V(particles, nullptr);
+
+ return &particles->dependency;
}
bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
- return false;
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+ return !particles->emitting && particles->inactive;
}
-/* PARTICLES COLLISION */
+/* PARTICLES COLLISION API */
RID ParticlesStorage::particles_collision_allocate() {
- return RID();
+ return particles_collision_owner.allocate_rid();
}
-
void ParticlesStorage::particles_collision_initialize(RID p_rid) {
+ particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
}
void ParticlesStorage::particles_collision_free(RID p_rid) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
+
+ if (particles_collision->heightfield_texture != 0) {
+ glDeleteTextures(1, &particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = 0;
+ glDeleteFramebuffers(1, &particles_collision->heightfield_fb);
+ particles_collision->heightfield_fb = 0;
+ }
+ particles_collision->dependency.deleted_notify(p_rid);
+ particles_collision_owner.free(p_rid);
+}
+
+GLuint ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, 0);
+ ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, 0);
+
+ if (particles_collision->heightfield_texture == 0) {
+ //create
+ const int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 };
+ Size2i size;
+ if (particles_collision->extents.x > particles_collision->extents.z) {
+ size.x = resolutions[particles_collision->heightfield_resolution];
+ size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x);
+ } else {
+ size.y = resolutions[particles_collision->heightfield_resolution];
+ size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y);
+ }
+
+ glGenTextures(1, &particles_collision->heightfield_texture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, particles_collision->heightfield_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, size.x, size.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
+ glGenFramebuffers(1, &particles_collision->heightfield_fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, particles_collision->heightfield_fb);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, particles_collision->heightfield_texture, 0);
+#ifdef DEBUG_ENABLED
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ WARN_PRINT("Could create heightmap texture status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));
+ }
+#endif
+ particles_collision->heightfield_fb_size = size;
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ return particles_collision->heightfield_fb;
}
void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ if (p_type == particles_collision->type) {
+ return;
+ }
+
+ if (particles_collision->heightfield_texture != 0) {
+ glDeleteTextures(1, &particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = 0;
+ glDeleteFramebuffers(1, &particles_collision->heightfield_fb);
+ particles_collision->heightfield_fb = 0;
+ }
+
+ particles_collision->type = p_type;
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ particles_collision->cull_mask = p_cull_mask;
}
void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->radius = p_radius;
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->extents = p_extents;
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_strength = p_strength;
}
void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_directionality = p_directionality;
}
void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_attenuation = p_curve;
}
void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
+ WARN_PRINT_ONCE("The OpenGL 3 renderer does not support SDF collisions in 3D particle shaders");
}
void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
+
+ if (particles_collision->heightfield_resolution == p_resolution) {
+ return;
+ }
+
+ particles_collision->heightfield_resolution = p_resolution;
+
+ if (particles_collision->heightfield_texture != 0) {
+ glDeleteTextures(1, &particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = 0;
+ glDeleteFramebuffers(1, &particles_collision->heightfield_fb);
+ particles_collision->heightfield_fb = 0;
+ }
}
AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const {
- return AABB();
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, AABB());
+
+ switch (particles_collision->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT:
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ AABB aabb;
+ aabb.position = -Vector3(1, 1, 1) * particles_collision->radius;
+ aabb.size = Vector3(2, 2, 2) * particles_collision->radius;
+ return aabb;
+ }
+ default: {
+ AABB aabb;
+ aabb.position = -particles_collision->extents;
+ aabb.size = particles_collision->extents * 2;
+ return aabb;
+ }
+ }
+}
+
+Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const {
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, Vector3());
+ return particles_collision->extents;
}
bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const {
- return false;
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, false);
+ return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
-RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
- return RID();
+Dependency *ParticlesStorage::particles_collision_get_dependency(RID p_particles_collision) const {
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_NULL_V(pc, nullptr);
+
+ return &pc->dependency;
}
+/* Particles collision instance */
+
RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
- return RID();
+ ParticlesCollisionInstance pci;
+ pci.collision = p_collision;
+ return particles_collision_instance_owner.make_rid(pci);
}
void ParticlesStorage::particles_collision_instance_free(RID p_rid) {
+ particles_collision_instance_owner.free(p_rid);
}
void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->transform = p_transform;
}
void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->active = p_active;
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h
index 84d1f94d8c..434718006e 100644
--- a/drivers/gles3/storage/particles_storage.h
+++ b/drivers/gles3/storage/particles_storage.h
@@ -33,25 +33,283 @@
#ifdef GLES3_ENABLED
+#include "../shaders/particles_copy.glsl.gen.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/storage/particles_storage.h"
+#include "servers/rendering/storage/utilities.h"
+
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
namespace GLES3 {
+enum ParticlesUniformLocation {
+ PARTICLES_FRAME_UNIFORM_LOCATION,
+ PARTICLES_GLOBALS_UNIFORM_LOCATION,
+ PARTICLES_MATERIAL_UNIFORM_LOCATION,
+};
+
class ParticlesStorage : public RendererParticlesStorage {
private:
static ParticlesStorage *singleton;
+ /* PARTICLES */
+
+ struct ParticleInstanceData3D {
+ float xform[12];
+ float color[2]; // Color and custom are packed together into one vec4;
+ float custom[2];
+ };
+
+ struct ParticleInstanceData2D {
+ float xform[8];
+ float color[2]; // Color and custom are packed together into one vec4;
+ float custom[2];
+ };
+
+ struct ParticlesViewSort {
+ Vector3 z_dir;
+ bool operator()(const ParticleInstanceData3D &p_a, const ParticleInstanceData3D &p_b) const {
+ return z_dir.dot(Vector3(p_a.xform[3], p_a.xform[7], p_a.xform[11])) < z_dir.dot(Vector3(p_b.xform[3], p_b.xform[7], p_b.xform[11]));
+ }
+ };
+
+ struct ParticlesFrameParams {
+ enum {
+ MAX_ATTRACTORS = 32,
+ MAX_COLLIDERS = 32,
+ MAX_3D_TEXTURES = 0 // GLES3 renderer doesn't support using 3D textures for flow field or collisions.
+ };
+
+ enum AttractorType {
+ ATTRACTOR_TYPE_SPHERE,
+ ATTRACTOR_TYPE_BOX,
+ ATTRACTOR_TYPE_VECTOR_FIELD,
+ };
+
+ struct Attractor {
+ float transform[16];
+ float extents[4]; // Extents or radius. w-channel is padding.
+
+ uint32_t type;
+ float strength;
+ float attenuation;
+ float directionality;
+ };
+
+ enum CollisionType {
+ COLLISION_TYPE_SPHERE,
+ COLLISION_TYPE_BOX,
+ COLLISION_TYPE_SDF,
+ COLLISION_TYPE_HEIGHT_FIELD,
+ COLLISION_TYPE_2D_SDF,
+
+ };
+
+ struct Collider {
+ float transform[16];
+ float extents[4]; // Extents or radius. w-channel is padding.
+
+ uint32_t type;
+ float scale;
+ float pad0;
+ float pad1;
+ };
+
+ uint32_t emitting;
+ uint32_t cycle;
+ float system_phase;
+ float prev_system_phase;
+
+ float explosiveness;
+ float randomness;
+ float time;
+ float delta;
+
+ float particle_size;
+ float pad0;
+ float pad1;
+ float pad2;
+
+ uint32_t random_seed;
+ uint32_t attractor_count;
+ uint32_t collider_count;
+ uint32_t frame;
+
+ float emission_transform[16];
+
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
+ };
+
+ struct Particles {
+ RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
+ bool inactive = true;
+ double inactive_time = 0.0;
+ bool emitting = false;
+ bool one_shot = false;
+ int amount = 0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
+ real_t explosiveness = 0.0;
+ real_t randomness = 0.0;
+ bool restart_request = false;
+ AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
+ bool use_local_coords = false;
+ bool has_collision_cache = false;
+
+ bool has_sdf_collision = false;
+ Transform2D sdf_collision_transform;
+ Rect2 sdf_collision_to_screen;
+ GLuint sdf_collision_texture = 0;
+
+ RID process_material;
+ uint32_t frame_counter = 0;
+ RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
+
+ RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
+
+ Vector<RID> draw_passes;
+
+ GLuint frame_params_ubo = 0;
+
+ // We may process particles multiple times each frame (if they have a fixed FPS higher than the game FPS).
+ // Unfortunately, this means we can't just use a round-robin system of 3 buffers.
+ // To ensure the sort buffer is accurate, we copy the last frame instance buffer just before processing.
+
+ // Transform Feedback buffer and VAO for rendering.
+ // Each frame we render to this one.
+ GLuint front_vertex_array = 0; // Binds process buffer. Used for processing.
+ GLuint front_process_buffer = 0; // Transform + color + custom data + userdata + velocity + flags. Only needed for processing.
+ GLuint front_instance_buffer = 0; // Transform + color + custom data. In packed format needed for rendering.
+
+ // VAO for transform feedback, contains last frame's data.
+ // Read from this one for particles process and then copy to last frame buffer.
+ GLuint back_vertex_array = 0; // Binds process buffer. Used for processing.
+ GLuint back_process_buffer = 0; // Transform + color + custom data + userdata + velocity + flags. Only needed for processing.
+ GLuint back_instance_buffer = 0; // Transform + color + custom data. In packed format needed for rendering.
+
+ uint32_t instance_buffer_size_cache = 0;
+ uint32_t instance_buffer_stride_cache = 0;
+ uint32_t num_attrib_arrays_cache = 0;
+ uint32_t process_buffer_stride_cache = 0;
+
+ // Only ever copied to, holds last frame's instance data, then swaps with sort_buffer.
+ GLuint last_frame_buffer = 0;
+ bool last_frame_buffer_filled = false;
+ float last_frame_phase = 0.0;
+
+ // The frame-before-last's instance buffer.
+ // Use this to copy data back for sorting or computing AABB.
+ GLuint sort_buffer = 0;
+ bool sort_buffer_filled = false;
+ float sort_buffer_phase = 0.0;
+
+ uint32_t userdata_count = 0;
+
+ bool dirty = false;
+ Particles *update_list = nullptr;
+
+ double phase = 0.0;
+ double prev_phase = 0.0;
+ uint64_t prev_ticks = 0;
+ uint32_t random_seed = 0;
+
+ uint32_t cycle_number = 0;
+
+ double speed_scale = 1.0;
+
+ int fixed_fps = 30;
+ bool interpolate = true;
+ bool fractional_delta = false;
+ double frame_remainder = 0;
+ real_t collision_base_size = 0.01;
+
+ bool clear = true;
+
+ Transform3D emission_transform;
+
+ HashSet<RID> collisions;
+
+ Dependency dependency;
+
+ double trail_length = 1.0;
+ bool trails_enabled = false;
+
+ Particles() {
+ }
+ };
+
+ void _particles_process(Particles *p_particles, double p_delta);
+ void _particles_free_data(Particles *particles);
+ void _particles_update_buffers(Particles *particles);
+ void _particles_allocate_history_buffers(Particles *particles);
+ void _particles_update_instance_buffer(Particles *particles, const Vector3 &p_axis, const Vector3 &p_up_axis);
+
+ template <typename T>
+ void _particles_reverse_lifetime_sort(Particles *particles);
+
+ struct ParticlesShader {
+ RID default_shader;
+ RID default_material;
+ RID default_shader_version;
+
+ ParticlesCopyShaderGLES3 copy_shader;
+ RID copy_shader_version;
+ } particles_shader;
+
+ Particles *particle_update_list = nullptr;
+
+ mutable RID_Owner<Particles, true> particles_owner;
+
+ /* Particles Collision */
+
+ struct ParticlesCollision {
+ RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ float radius = 1.0;
+ Vector3 extents = Vector3(1, 1, 1);
+ float attractor_strength = 1.0;
+ float attractor_attenuation = 1.0;
+ float attractor_directionality = 0.0;
+ GLuint field_texture = 0;
+ GLuint heightfield_texture = 0;
+ GLuint heightfield_fb = 0;
+ Size2i heightfield_fb_size;
+
+ RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+
+ Dependency dependency;
+ };
+
+ struct ParticlesCollisionInstance {
+ RID collision;
+ Transform3D transform;
+ bool active = false;
+ };
+
+ mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
+
+ mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+
public:
static ParticlesStorage *get_singleton();
ParticlesStorage();
virtual ~ParticlesStorage();
+ bool free(RID p_rid);
+
/* PARTICLES */
+ bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
+
virtual RID particles_allocate() override;
virtual void particles_initialize(RID p_rid) override;
virtual void particles_free(RID p_rid) override;
@@ -102,12 +360,51 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_instance) override;
virtual void particles_remove_collision(RID p_particles, RID p_instance) override;
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+ void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, GLuint p_texture);
virtual void update_particles() override;
virtual bool particles_is_inactive(RID p_particles) const override;
+ _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
+ return particles->mode;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->amount;
+ }
+
+ _FORCE_INLINE_ GLuint particles_get_gl_buffer(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+
+ if ((particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME) && particles->sort_buffer_filled) {
+ return particles->sort_buffer;
+ }
+ return particles->back_instance_buffer;
+ }
+
+ _FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->has_collision_cache;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->use_local_coords;
+ }
+
+ Dependency *particles_get_dependency(RID p_particles) const;
+
/* PARTICLES COLLISION */
+ bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
virtual RID particles_collision_allocate() override;
virtual void particles_collision_initialize(RID p_rid) override;
@@ -124,8 +421,22 @@ public:
virtual void particles_collision_height_field_update(RID p_particles_collision) override;
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override;
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
+ Vector3 particles_collision_get_extents(RID p_particles_collision) const;
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
- virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+ GLuint particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+
+ _FORCE_INLINE_ Size2i particles_collision_get_heightfield_size(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, Size2i());
+ ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, Size2i());
+
+ return particles_collision->heightfield_fb_size;
+ }
+
+ Dependency *particles_collision_get_dependency(RID p_particles) const;
+
+ /* PARTICLES COLLISION INSTANCE*/
+ bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); }
virtual RID particles_collision_instance_create(RID p_collision) override;
virtual void particles_collision_instance_free(RID p_rid) override;
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 2c2341e1cf..15743c2d78 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -251,6 +251,8 @@ void TextureStorage::canvas_texture_free(RID p_rid) {
void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
switch (p_channel) {
case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
ct->diffuse = p_texture;
@@ -266,6 +268,8 @@ void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::Canvas
void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
ct->specular_color.r = p_specular_color.r;
ct->specular_color.g = p_specular_color.g;
ct->specular_color.b = p_specular_color.b;
@@ -274,11 +278,15 @@ void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture,
void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
ct->texture_filter = p_filter;
}
void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
ct->texture_repeat = p_repeat;
}
@@ -647,7 +655,7 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
texture.height = p_image->get_height();
texture.alloc_width = texture.width;
texture.alloc_height = texture.height;
- texture.mipmaps = p_image->get_mipmap_count();
+ texture.mipmaps = p_image->get_mipmap_count() + 1;
texture.format = p_image->get_format();
texture.type = Texture::TYPE_2D;
texture.target = GL_TEXTURE_2D;
@@ -721,6 +729,26 @@ void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image,
}
void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND(!tex);
+ ERR_FAIL_COND(!tex->is_proxy);
+ Texture *proxy_to = texture_owner.get_or_null(p_proxy_to);
+ ERR_FAIL_COND(!proxy_to);
+ ERR_FAIL_COND(proxy_to->is_proxy);
+
+ if (tex->proxy_to.is_valid()) {
+ Texture *prev_tex = texture_owner.get_or_null(tex->proxy_to);
+ ERR_FAIL_COND(!prev_tex);
+ prev_tex->proxies.erase(p_texture);
+ }
+
+ *tex = *proxy_to;
+
+ tex->proxy_to = p_proxy_to;
+ tex->is_render_target = false;
+ tex->is_proxy = true;
+ tex->proxies.clear();
+ proxy_to->proxies.push_back(p_texture);
}
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
@@ -2195,7 +2223,11 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) {
// Load
CanvasSdfShaderGLES3::ShaderVariant variant = shrink ? CanvasSdfShaderGLES3::MODE_LOAD_SHRINK : CanvasSdfShaderGLES3::MODE_LOAD;
- sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ bool success = sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ if (!success) {
+ return;
+ }
+
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::BASE_SIZE, r.size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::SIZE, size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::STRIDE, 0, sdf_shader.shader_version, variant);
@@ -2216,7 +2248,11 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) {
int stride = nearest_power_of_2_templated(MAX(size.width, size.height) / 2);
variant = CanvasSdfShaderGLES3::MODE_PROCESS;
- sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ success = sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ if (!success) {
+ return;
+ }
+
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::BASE_SIZE, r.size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::SIZE, size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::STRIDE, stride, sdf_shader.shader_version, variant);
@@ -2240,7 +2276,11 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) {
// Store
variant = shrink ? CanvasSdfShaderGLES3::MODE_STORE_SHRINK : CanvasSdfShaderGLES3::MODE_STORE;
- sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ success = sdf_shader.shader.version_bind_shader(sdf_shader.shader_version, variant);
+ if (!success) {
+ return;
+ }
+
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::BASE_SIZE, r.size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::SIZE, size, sdf_shader.shader_version, variant);
sdf_shader.shader.version_set_uniform(CanvasSdfShaderGLES3::STRIDE, stride, sdf_shader.shader_version, variant);
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 7714e72f62..c465576347 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -129,7 +129,7 @@ struct Texture {
bool is_external = false;
bool is_render_target = false;
- RID proxy_to = RID();
+ RID proxy_to;
Vector<RID> proxies;
String path;
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 8e7e218bb9..393093c2a7 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -108,6 +108,10 @@ RS::InstanceType Utilities::get_base_type(RID p_rid) const {
return RS::INSTANCE_LIGHT;
} else if (GLES3::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
return RS::INSTANCE_LIGHTMAP;
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
+ return RS::INSTANCE_PARTICLES;
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
+ return RS::INSTANCE_PARTICLES_COLLISION;
}
return RS::INSTANCE_NONE;
}
@@ -143,53 +147,18 @@ bool Utilities::free(RID p_rid) {
} else if (GLES3::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
GLES3::LightStorage::get_singleton()->lightmap_free(p_rid);
return true;
- } else {
- return false;
- }
- /*
- else if (reflection_probe_owner.owns(p_rid)) {
- // delete the texture
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
- reflection_probe->instance_remove_deps();
-
- reflection_probe_owner.free(p_rid);
- memdelete(reflection_probe);
-
- return true;
- } else if (lightmap_capture_data_owner.owns(p_rid)) {
- // delete the texture
- LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get_or_null(p_rid);
- lightmap_capture->instance_remove_deps();
-
- lightmap_capture_data_owner.free(p_rid);
- memdelete(lightmap_capture);
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
+ GLES3::ParticlesStorage::get_singleton()->particles_free(p_rid);
return true;
-
- } else if (canvas_occluder_owner.owns(p_rid)) {
- CanvasOccluder *co = canvas_occluder_owner.get_or_null(p_rid);
- if (co->index_id) {
- glDeleteBuffers(1, &co->index_id);
- }
- if (co->vertex_id) {
- glDeleteBuffers(1, &co->vertex_id);
- }
-
- canvas_occluder_owner.free(p_rid);
- memdelete(co);
-
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
+ GLES3::ParticlesStorage::get_singleton()->particles_collision_free(p_rid);
return true;
-
- } else if (canvas_light_shadow_owner.owns(p_rid)) {
- CanvasLightShadow *cls = canvas_light_shadow_owner.get_or_null(p_rid);
- glDeleteFramebuffers(1, &cls->fbo);
- glDeleteRenderbuffers(1, &cls->depth);
- glDeleteTextures(1, &cls->distance);
- canvas_light_shadow_owner.free(p_rid);
- memdelete(cls);
-
+ } else if (GLES3::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) {
+ GLES3::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid);
return true;
+ } else {
+ return false;
}
- */
}
/* DEPENDENCIES */
@@ -207,6 +176,12 @@ void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance
} else if (LightStorage::get_singleton()->owns_light(p_base)) {
Light *l = LightStorage::get_singleton()->get_light(p_base);
p_instance->update_dependency(&l->dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) {
+ Dependency *dependency = ParticlesStorage::get_singleton()->particles_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
+ Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
}
}
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 749726c632..7e86679851 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -3826,7 +3826,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
vrs_reference.aspectMask = VK_IMAGE_ASPECT_NONE;
- Size2i texel_size = context->get_vrs_capabilities().max_texel_size;
+ Size2i texel_size = context->get_vrs_capabilities().texel_size;
VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i];
vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
@@ -9192,7 +9192,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
Texture *texture = &frames[p_frame].textures_to_dispose_of.front()->get();
if (texture->bound) {
- WARN_PRINT("Deleted a texture while it was bound..");
+ WARN_PRINT("Deleted a texture while it was bound.");
}
vkDestroyImageView(device, texture->view, nullptr);
if (texture->owner.is_null()) {
@@ -9730,6 +9730,12 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const {
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
return subgroup_capabilities.supported_operations_flags_rd();
}
+ case LIMIT_VRS_TEXEL_WIDTH: {
+ return context->get_vrs_capabilities().texel_size.x;
+ }
+ case LIMIT_VRS_TEXEL_HEIGHT: {
+ return context->get_vrs_capabilities().texel_size.y;
+ }
default:
ERR_FAIL_V(0);
}
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 464ab474e1..381df6d65e 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -625,6 +625,9 @@ Error VulkanContext::_check_capabilities() {
vrs_capabilities.pipeline_vrs_supported = false;
vrs_capabilities.primitive_vrs_supported = false;
vrs_capabilities.attachment_vrs_supported = false;
+ vrs_capabilities.min_texel_size = Size2i();
+ vrs_capabilities.max_texel_size = Size2i();
+ vrs_capabilities.texel_size = Size2i();
multiview_capabilities.is_supported = false;
multiview_capabilities.geometry_shader_is_supported = false;
multiview_capabilities.tessellation_shader_is_supported = false;
@@ -788,6 +791,10 @@ Error VulkanContext::_check_capabilities() {
vrs_capabilities.max_texel_size.x = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.width;
vrs_capabilities.max_texel_size.y = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.height;
+ // We'll attempt to default to a texel size of 16x16
+ vrs_capabilities.texel_size.x = CLAMP(16, vrs_capabilities.min_texel_size.x, vrs_capabilities.max_texel_size.x);
+ vrs_capabilities.texel_size.y = CLAMP(16, vrs_capabilities.min_texel_size.y, vrs_capabilities.max_texel_size.y);
+
print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")"));
}
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index d6a25c5cd7..8cf33fa463 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -76,6 +76,8 @@ public:
Size2i min_texel_size;
Size2i max_texel_size;
+
+ Size2i texel_size; // The texel size we'll use
};
struct ShaderCapabilities {
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 3b9d6c18eb..c376d5434f 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -443,7 +443,7 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
TreeItem *event_item = action_tree->create_item(action_item);
// First Column - Text
- event_item->set_text(0, event_config_dialog->get_event_text(event, true));
+ event_item->set_text(0, EventListenerLineEdit::get_event_text(event, true));
event_item->set_meta("__event", event);
event_item->set_meta("__index", evnt_idx);
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index d56ee6f9eb..ad9980c4ef 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -47,8 +47,8 @@ class ActionMapEditor : public Control {
public:
struct ActionInfo {
- String name = String();
- Dictionary action = Dictionary();
+ String name;
+ Dictionary action;
Ref<Texture2D> icon = Ref<Texture2D>();
bool editable = true;
@@ -67,8 +67,8 @@ private:
// Storing which action/event is currently being edited in the InputEventConfigurationDialog.
- Dictionary current_action = Dictionary();
- String current_action_name = String();
+ Dictionary current_action;
+ String current_action_name;
int current_action_event_index = -1;
// Popups
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 4c7ebca299..da75bf1f3b 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -903,11 +903,17 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
}
float zoom_value = timeline->get_zoom()->get_max() - zv;
- timeline->get_zoom()->set_value(zoom_value);
- timeline->call_deferred("set_value", minimum_time);
+ if (Math::is_finite(minimum_time) && Math::is_finite(maximum_time) && maximum_time - minimum_time > CMP_EPSILON) {
+ timeline->get_zoom()->set_value(zoom_value);
+ timeline->call_deferred("set_value", minimum_time);
+ }
- v_scroll = (maximum_value + minimum_value) / 2.0;
- v_zoom = (maximum_value - minimum_value) / ((get_size().height - timeline->get_size().height) * 0.9);
+ if (Math::is_finite(minimum_value) && Math::is_finite(maximum_value)) {
+ v_scroll = (maximum_value + minimum_value) / 2.0;
+ if (maximum_value - minimum_value > CMP_EPSILON) {
+ v_zoom = (maximum_value - minimum_value) / ((get_size().height - timeline->get_size().height) * 0.9);
+ }
+ }
queue_redraw();
accept_event();
@@ -938,9 +944,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
Vector2 popup_pos = get_screen_position() + mb->get_position();
menu->clear();
- if (!locked_tracks.has(selected_track) || locked_tracks.has(selected_track)) {
- menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
- }
+ menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT);
if (selection.size()) {
menu->add_separator();
menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 44ecda103e..8305baf0a1 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1678,6 +1678,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
}
draw_line(Vector2(0, get_size().height), get_size(), linecolor, Math::round(EDSCALE));
+ update_values();
} break;
}
}
@@ -1700,7 +1701,6 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation, boo
play_position->hide();
}
queue_redraw();
- update_values();
}
Size2 AnimationTimelineEdit::get_minimum_size() const {
@@ -1749,6 +1749,7 @@ void AnimationTimelineEdit::update_values() {
length->set_step(1);
length->set_tooltip_text(TTR("Animation length (frames)"));
time_icon->set_tooltip_text(TTR("Animation length (frames)"));
+ track_edit->editor->_update_key_edit();
} else {
length->set_value(animation->get_length());
length->set_step(0.001);
@@ -1893,7 +1894,6 @@ void AnimationTimelineEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origi
void AnimationTimelineEdit::set_use_fps(bool p_use_fps) {
use_fps = p_use_fps;
- update_values();
queue_redraw();
}
@@ -3446,8 +3446,7 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re
track_edits[_get_track_selected()]->release_focus();
}
if (animation.is_valid()) {
- animation->disconnect("tracks_changed", callable_mp(this, &AnimationTrackEditor::_animation_changed));
- animation->disconnect("changed", callable_mp(this, &AnimationTrackEditor::_sync_animation_change));
+ animation->disconnect("changed", callable_mp(this, &AnimationTrackEditor::_animation_changed));
_clear_selection();
}
animation = p_anim;
@@ -3458,8 +3457,7 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re
_update_tracks();
if (animation.is_valid()) {
- animation->connect("tracks_changed", callable_mp(this, &AnimationTrackEditor::_animation_changed), CONNECT_DEFERRED);
- animation->connect("changed", callable_mp(this, &AnimationTrackEditor::_sync_animation_change), CONNECT_DEFERRED);
+ animation->connect("changed", callable_mp(this, &AnimationTrackEditor::_animation_changed), CONNECT_DEFERRED);
hscroll->show();
edit->set_disabled(read_only);
@@ -3613,7 +3611,7 @@ void AnimationTrackEditor::_animation_track_remove_request(int p_track, Ref<Anim
}
int idx = p_track;
if (idx >= 0 && idx < p_from_animation->get_track_count()) {
- undo_redo->create_action(TTR("Remove Anim Track"));
+ undo_redo->create_action(TTR("Remove Anim Track"), UndoRedo::MERGE_DISABLE, p_from_animation.ptr());
// Remove corresponding reset tracks if they are no longer needed.
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
@@ -4650,10 +4648,6 @@ void AnimationTrackEditor::_redraw_groups() {
}
}
-void AnimationTrackEditor::_sync_animation_change() {
- bezier_edit->queue_redraw();
-}
-
void AnimationTrackEditor::_animation_changed() {
if (animation_changing_awaiting_update) {
return; // All will be updated, don't bother with anything.
@@ -4793,6 +4787,7 @@ void AnimationTrackEditor::_update_step(double p_new_step) {
if (step_value != 0.0) {
step_value = 1.0 / step_value;
}
+ timeline->queue_redraw();
}
undo_redo->add_do_method(animation.ptr(), "set_step", step_value);
undo_redo->add_undo_method(animation.ptr(), "set_step", animation->get_step());
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 5c51921d93..db2f8b32dc 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -135,6 +135,7 @@ class AnimationTrackEditor;
class AnimationTrackEdit : public Control {
GDCLASS(AnimationTrackEdit, Control);
+ friend class AnimationTimelineEdit;
enum {
MENU_CALL_MODE_CONTINUOUS,
@@ -293,6 +294,7 @@ public:
class AnimationTrackEditor : public VBoxContainer {
GDCLASS(AnimationTrackEditor, VBoxContainer);
+ friend class AnimationTimelineEdit;
Ref<Animation> animation;
bool read_only = false;
@@ -326,7 +328,6 @@ class AnimationTrackEditor : public VBoxContainer {
bool animation_changing_awaiting_update = false;
void _animation_update(); // Updated by AnimationTrackEditor(this)
int _get_track_selected();
- void _sync_animation_change();
void _animation_changed();
void _update_tracks();
void _redraw_tracks();
diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp
index b9e52ad7ad..b84e58125e 100644
--- a/editor/audio_stream_preview.cpp
+++ b/editor/audio_stream_preview.cpp
@@ -42,6 +42,10 @@ float AudioStreamPreview::get_max(float p_time, float p_time_next) const {
}
int max = preview.size() / 2;
+ if (max == 0) {
+ return 0;
+ }
+
int time_from = p_time / length * max;
int time_to = p_time_next / length * max;
time_from = CLAMP(time_from, 0, max - 1);
@@ -69,6 +73,10 @@ float AudioStreamPreview::get_min(float p_time, float p_time_next) const {
}
int max = preview.size() / 2;
+ if (max == 0) {
+ return 0;
+ }
+
int time_from = p_time / length * max;
int time_to = p_time_next / length * max;
time_from = CLAMP(time_from, 0, max - 1);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 212a46cb62..e907d5a281 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -91,10 +91,10 @@ void FindReplaceBar::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
- hide_button->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_hover_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_pressed_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size());
+ hide_button->set_texture_normal(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_hover(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_pressed(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_custom_minimum_size(hide_button->get_texture_normal()->get_size());
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -377,10 +377,12 @@ void FindReplaceBar::_update_results_count() {
if (is_whole_words()) {
if (col_pos > 0 && !is_symbol(line_text[col_pos - 1])) {
- break;
+ col_pos += searched.length();
+ continue;
}
- if (col_pos + line_text.length() < line_text.length() && !is_symbol(line_text[col_pos + searched.length()])) {
- break;
+ if (col_pos + searched.length() < line_text.length() && !is_symbol(line_text[col_pos + searched.length()])) {
+ col_pos += searched.length();
+ continue;
}
}
@@ -1872,7 +1874,7 @@ void CodeTextEditor::_apply_settings_change() {
}
fc->set_opentype_features(ftrs);
} break;
- default: { // Default.
+ default: { // Enabled.
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
fc->set_opentype_features(ftrs);
@@ -2106,7 +2108,7 @@ CodeTextEditor::CodeTextEditor() {
}
fc->set_opentype_features(ftrs);
} break;
- default: { // Default.
+ default: { // Enabled.
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
fc->set_opentype_features(ftrs);
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 545b0895b0..785476d75b 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -501,7 +501,7 @@ String CreateDialog::get_selected_type() {
return selected->get_text(0);
}
-Variant CreateDialog::instance_selected() {
+Variant CreateDialog::instantiate_selected() {
TreeItem *selected = search_options->get_selected();
if (!selected) {
@@ -519,7 +519,7 @@ Variant CreateDialog::instance_selected() {
n->set_name(custom);
}
} else {
- obj = EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom);
+ obj = EditorNode::get_editor_data().instantiate_custom_type(selected->get_text(0), custom);
}
} else {
obj = ClassDB::instantiate(selected->get_text(0));
@@ -752,8 +752,7 @@ CreateDialog::CreateDialog() {
favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected));
favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated));
favorites->add_theme_constant_override("draw_guides", 1);
- // Cannot forward drag data to a non control, must be fixed.
- //favorites->set_drag_forwarding(this);
+ favorites->set_drag_forwarding(this);
fav_vb->add_margin_child(TTR("Favorites:"), favorites, true);
VBoxContainer *rec_vb = memnew(VBoxContainer);
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index f2e741624f..961538d8b7 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -110,7 +110,7 @@ protected:
void _save_and_update_favorite_list();
public:
- Variant instance_selected();
+ Variant instantiate_selected();
String get_selected_type();
void set_base_type(const String &p_base) { base_type = p_base; }
diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp
index 371aaf8617..c64f23aba0 100644
--- a/editor/debugger/editor_debugger_inspector.cpp
+++ b/editor/debugger/editor_debugger_inspector.cpp
@@ -230,7 +230,7 @@ void EditorDebuggerInspector::add_stack_variable(const Array &p_array) {
Variant v = var.value;
PropertyHint h = PROPERTY_HINT_NONE;
- String hs = String();
+ String hs;
if (v.get_type() == Variant::OBJECT) {
v = Object::cast_to<EncodedObjectAsID>(v)->get_object_id();
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index 68aff328ed..150257a95c 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -119,8 +119,8 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
}
if (!debugger_plugins.is_empty()) {
- for (const Ref<Script> &i : debugger_plugins) {
- node->add_debugger_plugin(i);
+ for (Ref<EditorDebuggerPlugin> plugin : debugger_plugins) {
+ plugin->create_session(node);
}
}
@@ -167,7 +167,7 @@ void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_d
void EditorDebuggerNode::_bind_methods() {
// LiveDebug.
ClassDB::bind_method("live_debug_create_node", &EditorDebuggerNode::live_debug_create_node);
- ClassDB::bind_method("live_debug_instance_node", &EditorDebuggerNode::live_debug_instance_node);
+ ClassDB::bind_method("live_debug_instantiate_node", &EditorDebuggerNode::live_debug_instantiate_node);
ClassDB::bind_method("live_debug_remove_node", &EditorDebuggerNode::live_debug_remove_node);
ClassDB::bind_method("live_debug_remove_and_keep_node", &EditorDebuggerNode::live_debug_remove_and_keep_node);
ClassDB::bind_method("live_debug_restore_node", &EditorDebuggerNode::live_debug_restore_node);
@@ -676,9 +676,9 @@ void EditorDebuggerNode::live_debug_create_node(const NodePath &p_parent, const
});
}
-void EditorDebuggerNode::live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
+void EditorDebuggerNode::live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
- dbg->live_debug_instance_node(p_parent, p_path, p_name);
+ dbg->live_debug_instantiate_node(p_parent, p_path, p_name);
});
}
@@ -723,22 +723,36 @@ EditorDebuggerNode::CameraOverride EditorDebuggerNode::get_camera_override() {
return camera_override;
}
-void EditorDebuggerNode::add_debugger_plugin(const Ref<Script> &p_script) {
- ERR_FAIL_COND_MSG(debugger_plugins.has(p_script), "Debugger plugin already exists.");
- ERR_FAIL_COND_MSG(p_script.is_null(), "Debugger plugin script is null");
- ERR_FAIL_COND_MSG(p_script->get_instance_base_type() == StringName(), "Debugger plugin script has error.");
- ERR_FAIL_COND_MSG(String(p_script->get_instance_base_type()) != "EditorDebuggerPlugin", "Base type of debugger plugin is not 'EditorDebuggerPlugin'.");
- ERR_FAIL_COND_MSG(!p_script->is_tool(), "Debugger plugin script is not in tool mode.");
- debugger_plugins.insert(p_script);
+void EditorDebuggerNode::add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ ERR_FAIL_COND_MSG(p_plugin.is_null(), "Debugger plugin is null.");
+ ERR_FAIL_COND_MSG(debugger_plugins.has(p_plugin), "Debugger plugin already exists.");
+ debugger_plugins.insert(p_plugin);
+
+ Ref<EditorDebuggerPlugin> plugin = p_plugin;
for (int i = 0; get_debugger(i); i++) {
- get_debugger(i)->add_debugger_plugin(p_script);
+ plugin->create_session(get_debugger(i));
}
}
-void EditorDebuggerNode::remove_debugger_plugin(const Ref<Script> &p_script) {
- ERR_FAIL_COND_MSG(!debugger_plugins.has(p_script), "Debugger plugin doesn't exists.");
- debugger_plugins.erase(p_script);
- for (int i = 0; get_debugger(i); i++) {
- get_debugger(i)->remove_debugger_plugin(p_script);
+void EditorDebuggerNode::remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ ERR_FAIL_COND_MSG(p_plugin.is_null(), "Debugger plugin is null.");
+ ERR_FAIL_COND_MSG(!debugger_plugins.has(p_plugin), "Debugger plugin doesn't exists.");
+ debugger_plugins.erase(p_plugin);
+ Ref<EditorDebuggerPlugin>(p_plugin)->clear();
+}
+
+bool EditorDebuggerNode::plugins_capture(ScriptEditorDebugger *p_debugger, const String &p_message, const Array &p_data) {
+ int session_index = tabs->get_tab_idx_from_control(p_debugger);
+ ERR_FAIL_COND_V(session_index < 0, false);
+ int colon_index = p_message.find_char(':');
+ ERR_FAIL_COND_V_MSG(colon_index < 1, false, "Invalid message received.");
+
+ const String cap = p_message.substr(0, colon_index);
+ bool parsed = false;
+ for (Ref<EditorDebuggerPlugin> plugin : debugger_plugins) {
+ if (plugin->has_capture(cap)) {
+ parsed |= plugin->capture(p_message, p_data, session_index);
+ }
}
+ return parsed;
}
diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h
index 305f18a652..7f7279ae74 100644
--- a/editor/debugger/editor_debugger_node.h
+++ b/editor/debugger/editor_debugger_node.h
@@ -36,6 +36,7 @@
class Button;
class DebugAdapterParser;
+class EditorDebuggerPlugin;
class EditorDebuggerTree;
class EditorDebuggerRemoteObject;
class MenuButton;
@@ -113,7 +114,7 @@ private:
CameraOverride camera_override = OVERRIDE_NONE;
HashMap<Breakpoint, bool, Breakpoint> breakpoints;
- HashSet<Ref<Script>> debugger_plugins;
+ HashSet<Ref<EditorDebuggerPlugin>> debugger_plugins;
ScriptEditorDebugger *_add_debugger();
EditorDebuggerRemoteObject *get_inspected_remote_object();
@@ -190,7 +191,7 @@ public:
void set_live_debugging(bool p_enabled);
void update_live_edit_root();
void live_debug_create_node(const NodePath &p_parent, const String &p_type, const String &p_name);
- void live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name);
+ void live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name);
void live_debug_remove_node(const NodePath &p_at);
void live_debug_remove_and_keep_node(const NodePath &p_at, ObjectID p_keep_id);
void live_debug_restore_node(ObjectID p_id, const NodePath &p_at, int p_at_pos);
@@ -205,8 +206,9 @@ public:
Error start(const String &p_uri = "tcp://");
void stop();
- void add_debugger_plugin(const Ref<Script> &p_script);
- void remove_debugger_plugin(const Ref<Script> &p_script);
+ bool plugins_capture(ScriptEditorDebugger *p_debugger, const String &p_message, const Array &p_data);
+ void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
+ void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
};
#endif // EDITOR_DEBUGGER_NODE_H
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index e2fd462f3a..071eb583c0 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -234,6 +234,7 @@ TreeItem *EditorPerformanceProfiler::_get_monitor_base(const StringName &p_base_
base->set_editable(0, false);
base->set_selectable(0, false);
base->set_expand_right(0, true);
+ base->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
base_map.insert(p_base_name, base);
return base;
}
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index f1f34b8ebb..178010d852 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -37,7 +37,6 @@
#include "core/string/ustring.h"
#include "core/version.h"
#include "editor/debugger/debug_adapter/debug_adapter_protocol.h"
-#include "editor/debugger/editor_network_profiler.h"
#include "editor/debugger/editor_performance_profiler.h"
#include "editor/debugger/editor_profiler.h"
#include "editor/debugger/editor_visual_profiler.h"
@@ -52,6 +51,7 @@
#include "editor/plugins/node_3d_editor_plugin.h"
#include "main/performance.h"
#include "scene/3d/camera_3d.h"
+#include "scene/debugger/scene_debugger.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
@@ -713,17 +713,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
profiler->add_frame_metric(metric, true);
}
- } else if (p_msg == "multiplayer:rpc") {
- SceneDebugger::RPCProfilerFrame frame;
- frame.deserialize(p_data);
- for (int i = 0; i < frame.infos.size(); i++) {
- network_profiler->add_node_frame_data(frame.infos[i]);
- }
-
- } else if (p_msg == "multiplayer:bandwidth") {
- ERR_FAIL_COND(p_data.size() < 2);
- network_profiler->set_bandwidth(p_data[0], p_data[1]);
-
} else if (p_msg == "request_quit") {
emit_signal(SNAME("stop_requested"));
_stop_and_notify();
@@ -741,22 +730,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
int colon_index = p_msg.find_char(':');
ERR_FAIL_COND_MSG(colon_index < 1, "Invalid message received");
- bool parsed = false;
- const String cap = p_msg.substr(0, colon_index);
- HashMap<StringName, Callable>::Iterator element = captures.find(cap);
- if (element) {
- Callable &c = element->value;
- ERR_FAIL_COND_MSG(c.is_null(), "Invalid callable registered: " + cap);
- Variant cmd = p_msg.substr(colon_index + 1), cmd_data = p_data;
- const Variant *args[2] = { &cmd, &cmd_data };
- Variant retval;
- Callable::CallError err;
- c.callp(args, 2, retval, err);
- ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(c, args, 2, err));
- ERR_FAIL_COND_MSG(retval.get_type() != Variant::BOOL, "Error calling 'capture' to callable: " + String(c) + ". Return type is not bool.");
- parsed = retval;
- }
-
+ bool parsed = EditorDebuggerNode::get_singleton()->plugins_capture(this, p_msg, p_data);
if (!parsed) {
WARN_PRINT("unknown message " + p_msg);
}
@@ -982,10 +956,6 @@ void ScriptEditorDebugger::_profiler_activate(bool p_enable, int p_type) {
Array msg_data;
msg_data.push_back(p_enable);
switch (p_type) {
- case PROFILER_NETWORK:
- _put_msg("profiler:multiplayer", msg_data);
- _put_msg("profiler:rpc", msg_data);
- break;
case PROFILER_VISUAL:
_put_msg("profiler:visual", msg_data);
break;
@@ -1283,13 +1253,13 @@ void ScriptEditorDebugger::live_debug_create_node(const NodePath &p_parent, cons
}
}
-void ScriptEditorDebugger::live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
+void ScriptEditorDebugger::live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name) {
if (live_debug) {
Array msg;
msg.push_back(p_parent);
msg.push_back(p_path);
msg.push_back(p_name);
- _put_msg("scene:live_instance_node", msg);
+ _put_msg("scene:live_instantiate_node", msg);
}
}
@@ -1626,7 +1596,7 @@ void ScriptEditorDebugger::_tab_changed(int p_tab) {
void ScriptEditorDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("live_debug_create_node"), &ScriptEditorDebugger::live_debug_create_node);
- ClassDB::bind_method(D_METHOD("live_debug_instance_node"), &ScriptEditorDebugger::live_debug_instance_node);
+ ClassDB::bind_method(D_METHOD("live_debug_instantiate_node"), &ScriptEditorDebugger::live_debug_instantiate_node);
ClassDB::bind_method(D_METHOD("live_debug_remove_node"), &ScriptEditorDebugger::live_debug_remove_node);
ClassDB::bind_method(D_METHOD("live_debug_remove_and_keep_node"), &ScriptEditorDebugger::live_debug_remove_and_keep_node);
ClassDB::bind_method(D_METHOD("live_debug_restore_node"), &ScriptEditorDebugger::live_debug_restore_node);
@@ -1658,41 +1628,25 @@ void ScriptEditorDebugger::_bind_methods() {
ADD_SIGNAL(MethodInfo("errors_cleared"));
}
-void ScriptEditorDebugger::add_debugger_plugin(const Ref<Script> &p_script) {
- if (!debugger_plugins.has(p_script)) {
- EditorDebuggerPlugin *plugin = memnew(EditorDebuggerPlugin());
- plugin->attach_debugger(this);
- plugin->set_script(p_script);
- tabs->add_child(plugin);
- debugger_plugins.insert(p_script, plugin);
- }
+void ScriptEditorDebugger::add_debugger_tab(Control *p_control) {
+ tabs->add_child(p_control);
}
-void ScriptEditorDebugger::remove_debugger_plugin(const Ref<Script> &p_script) {
- if (debugger_plugins.has(p_script)) {
- tabs->remove_child(debugger_plugins[p_script]);
- debugger_plugins[p_script]->detach_debugger(false);
- memdelete(debugger_plugins[p_script]);
- debugger_plugins.erase(p_script);
- }
+void ScriptEditorDebugger::remove_debugger_tab(Control *p_control) {
+ int idx = tabs->get_tab_idx_from_control(p_control);
+ ERR_FAIL_COND(idx < 0);
+ p_control->queue_free();
}
void ScriptEditorDebugger::send_message(const String &p_message, const Array &p_args) {
_put_msg(p_message, p_args);
}
-void ScriptEditorDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) {
- ERR_FAIL_COND_MSG(has_capture(p_name), "Capture already registered: " + p_name);
- captures.insert(p_name, p_callable);
-}
-
-void ScriptEditorDebugger::unregister_message_capture(const StringName &p_name) {
- ERR_FAIL_COND_MSG(!has_capture(p_name), "Capture not registered: " + p_name);
- captures.erase(p_name);
-}
-
-bool ScriptEditorDebugger::has_capture(const StringName &p_name) {
- return captures.has(p_name);
+void ScriptEditorDebugger::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) {
+ Array msg_data;
+ msg_data.push_back(p_enable);
+ msg_data.append_array(p_data);
+ _put_msg("profiler:" + p_profiler, msg_data);
}
ScriptEditorDebugger::ScriptEditorDebugger() {
@@ -1904,13 +1858,6 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
visual_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_VISUAL));
}
- { //network profiler
- network_profiler = memnew(EditorNetworkProfiler);
- network_profiler->set_name(TTR("Network Profiler"));
- tabs->add_child(network_profiler);
- network_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_NETWORK));
- }
-
{ //monitors
performance_profiler = memnew(EditorPerformanceProfiler);
tabs->add_child(performance_profiler);
diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h
index aa0a50ff03..06bff39053 100644
--- a/editor/debugger/script_editor_debugger.h
+++ b/editor/debugger/script_editor_debugger.h
@@ -50,7 +50,6 @@ class ItemList;
class EditorProfiler;
class EditorFileDialog;
class EditorVisualProfiler;
-class EditorNetworkProfiler;
class EditorPerformanceProfiler;
class SceneDebuggerTree;
class EditorDebuggerPlugin;
@@ -72,7 +71,6 @@ private:
};
enum ProfilerType {
- PROFILER_NETWORK,
PROFILER_VISUAL,
PROFILER_SCRIPTS_SERVERS
};
@@ -151,7 +149,6 @@ private:
EditorProfiler *profiler = nullptr;
EditorVisualProfiler *visual_profiler = nullptr;
- EditorNetworkProfiler *network_profiler = nullptr;
EditorPerformanceProfiler *performance_profiler = nullptr;
OS::ProcessID remote_pid = 0;
@@ -163,10 +160,6 @@ private:
EditorDebuggerNode::CameraOverride camera_override;
- HashMap<Ref<Script>, EditorDebuggerPlugin *> debugger_plugins;
-
- HashMap<StringName, Callable> captures;
-
void _stack_dump_frame_selected();
void _file_selected(const String &p_file);
@@ -266,7 +259,7 @@ public:
void set_live_debugging(bool p_enable);
void live_debug_create_node(const NodePath &p_parent, const String &p_type, const String &p_name);
- void live_debug_instance_node(const NodePath &p_parent, const String &p_path, const String &p_name);
+ void live_debug_instantiate_node(const NodePath &p_parent, const String &p_path, const String &p_name);
void live_debug_remove_node(const NodePath &p_at);
void live_debug_remove_and_keep_node(const NodePath &p_at, ObjectID p_keep_id);
void live_debug_restore_node(ObjectID p_id, const NodePath &p_at, int p_at_pos);
@@ -286,14 +279,11 @@ public:
virtual Size2 get_minimum_size() const override;
- void add_debugger_plugin(const Ref<Script> &p_script);
- void remove_debugger_plugin(const Ref<Script> &p_script);
+ void add_debugger_tab(Control *p_control);
+ void remove_debugger_tab(Control *p_control);
void send_message(const String &p_message, const Array &p_args);
-
- void register_message_capture(const StringName &p_name, const Callable &p_callable);
- void unregister_message_capture(const StringName &p_name);
- bool has_capture(const StringName &p_name);
+ void toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data);
ScriptEditorDebugger();
~ScriptEditorDebugger();
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index 436b391ccd..97e94089cc 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -47,6 +47,7 @@
#include "scene/gui/tree.h"
class EditorAudioBuses;
+class EditorFileDialog;
class EditorAudioBus : public PanelContainer {
GDCLASS(EditorAudioBus, PanelContainer);
diff --git a/editor/editor_build_profile.h b/editor/editor_build_profile.h
index 606c415429..9624f7e44b 100644
--- a/editor/editor_build_profile.h
+++ b/editor/editor_build_profile.h
@@ -117,6 +117,7 @@ public:
VARIANT_ENUM_CAST(EditorBuildProfile::BuildOption)
VARIANT_ENUM_CAST(EditorBuildProfile::BuildOptionCategory)
+class EditorFileDialog;
class EditorFileSystemDirectory;
class EditorBuildProfileManager : public AcceptDialog {
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index a3dd19bb67..48be0c9c00 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -486,7 +486,7 @@ void EditorData::add_custom_type(const String &p_type, const String &p_inherits,
custom_types[p_inherits].push_back(ct);
}
-Variant EditorData::instance_custom_type(const String &p_type, const String &p_inherits) {
+Variant EditorData::instantiate_custom_type(const String &p_type, const String &p_inherits) {
if (get_custom_types().has(p_inherits)) {
for (int i = 0; i < get_custom_types()[p_inherits].size(); i++) {
if (get_custom_types()[p_inherits][i].name == p_type) {
diff --git a/editor/editor_data.h b/editor/editor_data.h
index 4f1740d4f0..aad00f3ff8 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -181,7 +181,7 @@ public:
void restore_editor_global_states();
void add_custom_type(const String &p_type, const String &p_inherits, const Ref<Script> &p_script, const Ref<Texture2D> &p_icon);
- Variant instance_custom_type(const String &p_type, const String &p_inherits);
+ Variant instantiate_custom_type(const String &p_type, const String &p_inherits);
void remove_custom_type(const String &p_type);
const HashMap<String, Vector<CustomType>> &get_custom_types() const { return custom_types; }
const CustomType *get_custom_type_by_name(const String &p_name) const;
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
index 6868c54146..1d79844913 100644
--- a/editor/editor_feature_profile.h
+++ b/editor/editor_feature_profile.h
@@ -40,6 +40,8 @@
#include "scene/gui/split_container.h"
#include "scene/gui/tree.h"
+class EditorFileDialog;
+
class EditorFeatureProfile : public RefCounted {
GDCLASS(EditorFeatureProfile, RefCounted);
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 51ebc31df3..e7d4636ad9 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -335,7 +335,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
}
mono_fc->set_opentype_features(ftrs);
} break;
- default: { // Default.
+ default: { // Enabled.
Dictionary ftrs;
ftrs[TS->name_to_tag("calt")] = 1;
mono_fc->set_opentype_features(ftrs);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 89398409a2..676e4b0b33 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -54,10 +54,14 @@ void EditorHelp::_update_theme() {
qualifier_color = get_theme_color(SNAME("qualifier_color"), SNAME("EditorHelp"));
type_color = get_theme_color(SNAME("type_color"), SNAME("EditorHelp"));
+ class_desc->add_theme_style_override("normal", get_theme_stylebox(SNAME("background"), SNAME("EditorHelp")));
+ class_desc->add_theme_style_override("focus", get_theme_stylebox(SNAME("background"), SNAME("EditorHelp")));
class_desc->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp")));
class_desc->add_theme_constant_override("line_separation", get_theme_constant(SNAME("line_separation"), SNAME("EditorHelp")));
class_desc->add_theme_constant_override("table_h_separation", get_theme_constant(SNAME("table_h_separation"), SNAME("EditorHelp")));
class_desc->add_theme_constant_override("table_v_separation", get_theme_constant(SNAME("table_v_separation"), SNAME("EditorHelp")));
+ class_desc->add_theme_constant_override("text_highlight_h_padding", get_theme_constant(SNAME("text_highlight_h_padding"), SNAME("EditorHelp")));
+ class_desc->add_theme_constant_override("text_highlight_v_padding", get_theme_constant(SNAME("text_highlight_v_padding"), SNAME("EditorHelp")));
doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts"));
doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts"));
@@ -199,13 +203,20 @@ void EditorHelp::_class_desc_resized(bool p_force_update_theme) {
}
void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
- String t = p_type;
- if (t.is_empty()) {
- t = "void";
+ if (p_type.is_empty() || p_type == "void") {
+ class_desc->push_color(Color(type_color, 0.5));
+ class_desc->push_hint(TTR("No return value."));
+ class_desc->add_text("void");
+ class_desc->pop();
+ class_desc->pop();
+ return;
}
- bool can_ref = (t != "void" && !t.contains("*")) || !p_enum.is_empty();
- if (!p_enum.is_empty()) {
+ bool is_enum_type = !p_enum.is_empty();
+ bool can_ref = !p_type.contains("*") || is_enum_type;
+
+ String t = p_type;
+ if (is_enum_type) {
if (p_enum.get_slice_count(".") > 1) {
t = p_enum.get_slice(".", 1);
} else {
@@ -219,21 +230,24 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
if (t.ends_with("[]")) {
add_array = true;
t = t.replace("[]", "");
+
+ class_desc->push_meta("#Array"); //class
+ class_desc->add_text("Array");
+ class_desc->pop();
+ class_desc->add_text("[");
}
- if (p_enum.is_empty()) {
- class_desc->push_meta("#" + t); //class
- } else {
+
+ if (is_enum_type) {
class_desc->push_meta("$" + p_enum); //class
+ } else {
+ class_desc->push_meta("#" + t); //class
}
}
class_desc->add_text(t);
if (can_ref) {
- class_desc->pop();
+ class_desc->pop(); // Pushed meta above.
if (add_array) {
- class_desc->add_text(" ");
- class_desc->push_meta("#Array"); //class
- class_desc->add_text("[]");
- class_desc->pop();
+ class_desc->add_text("]");
}
}
class_desc->pop();
@@ -432,7 +446,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
return OK;
}
-void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods, bool &r_method_descrpitons) {
+void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods) {
Ref<Font> font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
class_desc->pop(); // title font size
class_desc->pop(); // title font
@@ -482,10 +496,6 @@ void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods,
class_desc->pop(); //cell
}
- if (!m[i].description.strip_edges().is_empty() || m[i].errors_returned.size() > 0) {
- r_method_descrpitons = true;
- }
-
_add_method(m[i], true);
}
@@ -703,11 +713,15 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
}
+ bool has_description = false;
+
class_desc->add_newline();
class_desc->add_newline();
// Brief description
if (!cd.brief_description.strip_edges().is_empty()) {
+ has_description = true;
+
class_desc->push_color(text_color);
class_desc->push_font(doc_bold_font);
class_desc->push_indent(1);
@@ -722,6 +736,8 @@ void EditorHelp::_update_doc() {
// Class description
if (!cd.description.strip_edges().is_empty()) {
+ has_description = true;
+
section_line.push_back(Pair<String, int>(TTR("Description"), class_desc->get_paragraph_count() - 2));
description_line = class_desc->get_paragraph_count() - 2;
class_desc->push_color(title_color);
@@ -746,6 +762,22 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
}
+ if (!has_description) {
+ class_desc->add_image(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ class_desc->add_text(" ");
+ class_desc->push_color(comment_color);
+
+ if (cd.is_script_doc) {
+ class_desc->append_text(TTR("There is currently no description for this class."));
+ } else {
+ class_desc->append_text(TTR("There is currently no description for this class. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ }
+
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
// Online tutorials
if (cd.tutorials.size()) {
class_desc->push_color(title_color);
@@ -782,7 +814,6 @@ void EditorHelp::_update_doc() {
// Properties overview
HashSet<String> skip_methods;
- bool property_descr = false;
bool has_properties = cd.properties.size() != 0;
if (cd.is_script_doc) {
@@ -860,7 +891,6 @@ void EditorHelp::_update_doc() {
if (describe) {
class_desc->pop();
- property_descr = true;
}
class_desc->pop();
@@ -945,9 +975,6 @@ void EditorHelp::_update_doc() {
}
// Methods overview
- bool constructor_descriptions = false;
- bool method_descriptions = false;
- bool operator_descriptions = false;
bool sort_methods = EDITOR_GET("text_editor/help/sort_functions_alphabetically");
Vector<DocData::MethodDoc> methods;
@@ -975,19 +1002,20 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Constructors"));
- _update_method_list(cd.constructors, constructor_descriptions);
+ _update_method_list(cd.constructors);
}
if (!methods.is_empty()) {
if (sort_methods) {
methods.sort();
}
+
section_line.push_back(Pair<String, int>(TTR("Methods"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Methods"));
- _update_method_list(methods, method_descriptions);
+ _update_method_list(methods);
}
if (!cd.operators.is_empty()) {
@@ -1000,7 +1028,7 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_title_font);
class_desc->push_font_size(doc_title_font_size);
class_desc->add_text(TTR("Operators"));
- _update_method_list(cd.operators, operator_descriptions);
+ _update_method_list(cd.operators);
}
// Theme properties
@@ -1335,7 +1363,7 @@ void EditorHelp::_update_doc() {
if (constants[i].value.begins_with("Color(") && constants[i].value.ends_with(")")) {
String stripped = constants[i].value.replace(" ", "").replace("Color(", "").replace(")", "");
- Vector<float> color = stripped.split_floats(",");
+ PackedFloat64Array color = stripped.split_floats(",");
if (color.size() >= 3) {
class_desc->push_color(Color(color[0], color[1], color[2]));
_add_bulletpoint();
@@ -1493,7 +1521,7 @@ void EditorHelp::_update_doc() {
}
// Property descriptions
- if (property_descr) {
+ if (has_properties) {
section_line.push_back(Pair<String, int>(TTR("Property Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1668,7 +1696,7 @@ void EditorHelp::_update_doc() {
}
// Constructor descriptions
- if (constructor_descriptions) {
+ if (!cd.constructors.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Constructor Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1678,7 +1706,7 @@ void EditorHelp::_update_doc() {
}
// Method descriptions
- if (method_descriptions) {
+ if (!methods.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Method Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1688,7 +1716,7 @@ void EditorHelp::_update_doc() {
}
// Operator descriptions
- if (operator_descriptions) {
+ if (!cd.operators.is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Operator Descriptions"), class_desc->get_paragraph_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -1696,6 +1724,8 @@ void EditorHelp::_update_doc() {
class_desc->add_text(TTR("Operator Descriptions"));
_update_method_descriptions(cd, cd.operators, "operator");
}
+
+ // Free the scroll.
scroll_locked = false;
}
@@ -1786,9 +1816,19 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
Ref<Font> doc_code_font = p_owner_node->get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
Ref<Font> doc_kbd_font = p_owner_node->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts"));
- Color link_color = p_owner_node->get_theme_color(SNAME("link_color"), SNAME("EditorHelp"));
- Color code_color = p_owner_node->get_theme_color(SNAME("code_color"), SNAME("EditorHelp"));
- Color kbd_color = p_owner_node->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp"));
+ const Color type_color = p_owner_node->get_theme_color(SNAME("type_color"), SNAME("EditorHelp"));
+ const Color code_color = p_owner_node->get_theme_color(SNAME("code_color"), SNAME("EditorHelp"));
+ const Color kbd_color = p_owner_node->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp"));
+ const Color code_dark_color = Color(code_color, 0.8);
+
+ const Color link_color = p_owner_node->get_theme_color(SNAME("link_color"), SNAME("EditorHelp"));
+ const Color link_method_color = p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ const Color link_property_color = link_color.lerp(p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor")), 0.25);
+ const Color link_annotation_color = link_color.lerp(p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor")), 0.5);
+
+ const Color code_bg_color = p_owner_node->get_theme_color(SNAME("code_bg_color"), SNAME("EditorHelp"));
+ const Color kbd_bg_color = p_owner_node->get_theme_color(SNAME("kbd_bg_color"), SNAME("EditorHelp"));
+ const Color param_bg_color = p_owner_node->get_theme_color(SNAME("param_bg_color"), SNAME("EditorHelp"));
String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges();
@@ -1921,14 +1961,21 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
const String link_tag = tag.substr(0, tag_end);
const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" ");
- // Use monospace font with translucent colored background color to make clickable references
+ // Use monospace font to make clickable references
// easier to distinguish from inline code and other text.
p_rt->push_font(doc_code_font);
- p_rt->push_color(link_color);
- p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15));
+
+ Color target_color = link_color;
+ if (link_tag == "method") {
+ target_color = link_method_color;
+ } else if (link_tag == "member" || link_tag == "signal" || link_tag == "theme property") {
+ target_color = link_property_color;
+ } else if (link_tag == "annotation") {
+ target_color = link_annotation_color;
+ }
+ p_rt->push_color(target_color);
p_rt->push_meta("@" + link_tag + " " + link_target);
- p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : ""));
- p_rt->pop();
+ p_rt->add_text(link_target + (link_tag == "method" ? "()" : ""));
p_rt->pop();
p_rt->pop();
p_rt->pop();
@@ -1940,7 +1987,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
// Use monospace font with translucent background color to make code easier to distinguish from other text.
p_rt->push_font(doc_code_font);
- p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15));
+ p_rt->push_bgcolor(param_bg_color);
p_rt->push_color(code_color);
p_rt->add_text(param_name);
p_rt->pop();
@@ -1951,17 +1998,15 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
} else if (doc->class_list.has(tag)) {
// Class reference tag such as [Node2D] or [SceneTree].
- // Use monospace font with translucent colored background color to make clickable references
+ // Use monospace font to make clickable references
// easier to distinguish from inline code and other text.
p_rt->push_font(doc_code_font);
- p_rt->push_color(link_color);
- p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15));
+ p_rt->push_color(type_color);
p_rt->push_meta("#" + tag);
p_rt->add_text(tag);
p_rt->pop();
p_rt->pop();
p_rt->pop();
- p_rt->pop();
pos = brk_end + 1;
} else if (tag == "b") {
@@ -1975,30 +2020,30 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code") {
- // Use monospace font with translucent background color to make code easier to distinguish from other text.
+ // Use monospace font with darkened background color to make code easier to distinguish from other text.
p_rt->push_font(doc_code_font);
- p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15));
- p_rt->push_color(code_color);
+ p_rt->push_bgcolor(code_bg_color);
+ p_rt->push_color(code_color.lerp(p_owner_node->get_theme_color(SNAME("error_color"), SNAME("Editor")), 0.6));
code_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "codeblock") {
- // Use monospace font with translucent background color to make code easier to distinguish from other text.
+ // Use monospace font with darkened background color to make code easier to distinguish from other text.
// Use a single-column table with cell row background color instead of `[bgcolor]`.
// This makes the background color highlight cover the entire block, rather than individual lines.
p_rt->push_font(doc_code_font);
p_rt->push_table(1);
p_rt->push_cell();
- p_rt->set_cell_row_background_color(Color(0.5, 0.5, 0.5, 0.15), Color(0.5, 0.5, 0.5, 0.15));
+ p_rt->set_cell_row_background_color(code_bg_color, Color(code_bg_color, 0.99));
p_rt->set_cell_padding(Rect2(10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE));
- p_rt->push_color(code_color);
+ p_rt->push_color(code_dark_color);
codeblock_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "kbd") {
// Use keyboard font with custom color and background color.
p_rt->push_font(doc_kbd_font);
- p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15));
+ p_rt->push_bgcolor(kbd_bg_color);
p_rt->push_color(kbd_color);
code_tag = true; // Though not strictly a code tag, logic is similar.
pos = brk_end + 1;
@@ -2390,10 +2435,10 @@ void FindBar::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
- hide_button->set_normal_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_hover_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_pressed_texture(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
- hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size());
+ hide_button->set_texture_normal(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_hover(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_texture_pressed(get_theme_icon(SNAME("Close"), SNAME("EditorIcons")));
+ hide_button->set_custom_minimum_size(hide_button->get_texture_normal()->get_size());
matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color(SNAME("font_color"), SNAME("Label")) : get_theme_color(SNAME("error_color"), SNAME("Editor")));
} break;
diff --git a/editor/editor_help.h b/editor/editor_help.h
index c9c1afb51b..15bfdc7c91 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -167,7 +167,7 @@ class EditorHelp : public VBoxContainer {
Error _goto_desc(const String &p_class, int p_vscr = -1);
//void _update_history_buttons();
- void _update_method_list(const Vector<DocData::MethodDoc> p_methods, bool &r_method_descrpitons);
+ void _update_method_list(const Vector<DocData::MethodDoc> p_methods);
void _update_method_descriptions(const DocData::ClassDoc p_classdoc, const Vector<DocData::MethodDoc> p_methods, const String &p_method_type);
void _update_doc();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 1bca1b3c87..f277bf6467 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -70,7 +70,6 @@
#include "servers/physics_server_2d.h"
#include "servers/rendering/rendering_device.h"
-#include "editor/animation_track_editor.h"
#include "editor/audio_stream_preview.h"
#include "editor/debugger/debug_adapter/debug_adapter_server.h"
#include "editor/debugger/editor_debugger_node.h"
@@ -82,7 +81,6 @@
#include "editor/editor_data.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_file_dialog.h"
-#include "editor/editor_file_system.h"
#include "editor/editor_folding.h"
#include "editor/editor_help.h"
#include "editor/editor_inspector.h"
@@ -92,12 +90,8 @@
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_quick_open.h"
-#include "editor/editor_resource_picker.h"
-#include "editor/editor_resource_preview.h"
#include "editor/editor_run.h"
#include "editor/editor_run_native.h"
-#include "editor/editor_run_script.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_settings_dialog.h"
@@ -114,6 +108,7 @@
#include "editor/import/audio_stream_import_settings.h"
#include "editor/import/dynamic_font_import_settings.h"
#include "editor/import/editor_import_collada.h"
+#include "editor/import/editor_import_plugin.h"
#include "editor/import/resource_importer_bitmask.h"
#include "editor/import/resource_importer_bmfont.h"
#include "editor/import/resource_importer_csv_translation.h"
@@ -122,7 +117,6 @@
#include "editor/import/resource_importer_imagefont.h"
#include "editor/import/resource_importer_layered_texture.h"
#include "editor/import/resource_importer_obj.h"
-#include "editor/import/resource_importer_scene.h"
#include "editor/import/resource_importer_shader_file.h"
#include "editor/import/resource_importer_texture.h"
#include "editor/import/resource_importer_texture_atlas.h"
@@ -132,78 +126,21 @@
#include "editor/multi_node_edit.h"
#include "editor/node_dock.h"
#include "editor/plugin_config_dialog.h"
-#include "editor/plugins/animation_blend_space_1d_editor.h"
-#include "editor/plugins/animation_blend_space_2d_editor.h"
-#include "editor/plugins/animation_blend_tree_editor_plugin.h"
#include "editor/plugins/animation_player_editor_plugin.h"
-#include "editor/plugins/animation_state_machine_editor.h"
-#include "editor/plugins/animation_tree_editor_plugin.h"
#include "editor/plugins/asset_library_editor_plugin.h"
-#include "editor/plugins/audio_stream_randomizer_editor_plugin.h"
-#include "editor/plugins/bit_map_editor_plugin.h"
-#include "editor/plugins/bone_map_editor_plugin.h"
-#include "editor/plugins/camera_3d_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
-#include "editor/plugins/cast_2d_editor_plugin.h"
-#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
-#include "editor/plugins/collision_shape_2d_editor_plugin.h"
-#include "editor/plugins/control_editor_plugin.h"
-#include "editor/plugins/cpu_particles_2d_editor_plugin.h"
-#include "editor/plugins/cpu_particles_3d_editor_plugin.h"
-#include "editor/plugins/curve_editor_plugin.h"
#include "editor/plugins/debugger_editor_plugin.h"
-#include "editor/plugins/editor_debugger_plugin.h"
-#include "editor/plugins/editor_preview_plugins.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
-#include "editor/plugins/font_config_plugin.h"
#include "editor/plugins/gdextension_export_plugin.h"
-#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
-#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
-#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
-#include "editor/plugins/gradient_editor_plugin.h"
-#include "editor/plugins/gradient_texture_2d_editor_plugin.h"
-#include "editor/plugins/input_event_editor_plugin.h"
-#include "editor/plugins/light_occluder_2d_editor_plugin.h"
-#include "editor/plugins/lightmap_gi_editor_plugin.h"
-#include "editor/plugins/line_2d_editor_plugin.h"
#include "editor/plugins/material_editor_plugin.h"
-#include "editor/plugins/mesh_editor_plugin.h"
-#include "editor/plugins/mesh_instance_3d_editor_plugin.h"
#include "editor/plugins/mesh_library_editor_plugin.h"
-#include "editor/plugins/multimesh_editor_plugin.h"
-#include "editor/plugins/navigation_link_2d_editor_plugin.h"
-#include "editor/plugins/navigation_polygon_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
-#include "editor/plugins/occluder_instance_3d_editor_plugin.h"
#include "editor/plugins/packed_scene_translation_parser_plugin.h"
-#include "editor/plugins/path_2d_editor_plugin.h"
-#include "editor/plugins/path_3d_editor_plugin.h"
-#include "editor/plugins/physical_bone_3d_editor_plugin.h"
-#include "editor/plugins/polygon_2d_editor_plugin.h"
-#include "editor/plugins/polygon_3d_editor_plugin.h"
-#include "editor/plugins/resource_preloader_editor_plugin.h"
#include "editor/plugins/root_motion_editor_plugin.h"
-#include "editor/plugins/script_editor_plugin.h"
#include "editor/plugins/script_text_editor.h"
-#include "editor/plugins/shader_editor_plugin.h"
-#include "editor/plugins/shader_file_editor_plugin.h"
-#include "editor/plugins/skeleton_2d_editor_plugin.h"
-#include "editor/plugins/skeleton_3d_editor_plugin.h"
-#include "editor/plugins/skeleton_ik_3d_editor_plugin.h"
-#include "editor/plugins/sprite_2d_editor_plugin.h"
-#include "editor/plugins/sprite_frames_editor_plugin.h"
-#include "editor/plugins/style_box_editor_plugin.h"
-#include "editor/plugins/sub_viewport_preview_editor_plugin.h"
#include "editor/plugins/text_editor.h"
-#include "editor/plugins/texture_3d_editor_plugin.h"
-#include "editor/plugins/texture_editor_plugin.h"
-#include "editor/plugins/texture_layered_editor_plugin.h"
-#include "editor/plugins/texture_region_editor_plugin.h"
-#include "editor/plugins/theme_editor_plugin.h"
-#include "editor/plugins/tiles/tiles_editor_plugin.h"
#include "editor/plugins/version_control_editor_plugin.h"
#include "editor/plugins/visual_shader_editor_plugin.h"
-#include "editor/plugins/voxel_gi_editor_plugin.h"
#include "editor/progress_dialog.h"
#include "editor/project_settings_editor.h"
#include "editor/register_exporters.h"
@@ -1763,7 +1700,7 @@ void EditorNode::_save_scene(String p_file, int idx) {
}
if (!scene->get_scene_file_path().is_empty() && _validate_scene_recursive(scene->get_scene_file_path(), scene)) {
- show_accept(TTR("This scene can't be saved because there is a cyclic instancing inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK"));
+ show_accept(TTR("This scene can't be saved because there is a cyclic instance inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK"));
return;
}
@@ -2331,7 +2268,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
if (get_edited_scene() && !get_edited_scene()->get_scene_file_path().is_empty()) {
String source_scene = get_edited_scene()->get_scene_file_path();
if (FileAccess::exists(source_scene + ".import")) {
- editable_info = TTR("This scene was imported, so changes to it won't be kept.\nInstancing it or inheriting will allow making changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow.");
+ editable_info = TTR("This scene was imported, so changes to it won't be kept.\nInstantiating or inheriting it will allow you to make changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow.");
info_is_warning = true;
}
}
@@ -3992,7 +3929,7 @@ bool EditorNode::is_resource_read_only(Ref<Resource> p_resource, bool p_foreign_
return false;
}
-void EditorNode::request_instance_scene(const String &p_path) {
+void EditorNode::request_instantiate_scene(const String &p_path) {
SceneTreeDock::get_singleton()->instantiate(p_path);
}
@@ -4128,62 +4065,6 @@ bool EditorNode::is_scene_in_use(const String &p_path) {
return false;
}
-void EditorNode::register_editor_types() {
- ResourceLoader::set_timestamp_on_load(true);
- ResourceSaver::set_timestamp_on_save(true);
-
- GDREGISTER_CLASS(EditorPaths);
- GDREGISTER_CLASS(EditorPlugin);
- GDREGISTER_CLASS(EditorTranslationParserPlugin);
- GDREGISTER_CLASS(EditorImportPlugin);
- GDREGISTER_CLASS(EditorScript);
- GDREGISTER_CLASS(EditorSelection);
- GDREGISTER_CLASS(EditorFileDialog);
- GDREGISTER_ABSTRACT_CLASS(EditorSettings);
- GDREGISTER_CLASS(EditorNode3DGizmo);
- GDREGISTER_CLASS(EditorNode3DGizmoPlugin);
- GDREGISTER_ABSTRACT_CLASS(EditorResourcePreview);
- GDREGISTER_CLASS(EditorResourcePreviewGenerator);
- GDREGISTER_ABSTRACT_CLASS(EditorFileSystem);
- GDREGISTER_CLASS(EditorFileSystemDirectory);
- GDREGISTER_CLASS(EditorVCSInterface);
- GDREGISTER_ABSTRACT_CLASS(ScriptEditor);
- GDREGISTER_ABSTRACT_CLASS(ScriptEditorBase);
- GDREGISTER_CLASS(EditorSyntaxHighlighter);
- GDREGISTER_ABSTRACT_CLASS(EditorInterface);
- GDREGISTER_CLASS(EditorExportPlugin);
- GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform);
- GDREGISTER_CLASS(EditorResourceConversionPlugin);
- GDREGISTER_CLASS(EditorSceneFormatImporter);
- GDREGISTER_CLASS(EditorScenePostImportPlugin);
- GDREGISTER_CLASS(EditorInspector);
- GDREGISTER_CLASS(EditorInspectorPlugin);
- GDREGISTER_CLASS(EditorProperty);
- GDREGISTER_CLASS(AnimationTrackEditPlugin);
- GDREGISTER_CLASS(ScriptCreateDialog);
- GDREGISTER_CLASS(EditorFeatureProfile);
- GDREGISTER_CLASS(EditorSpinSlider);
- GDREGISTER_CLASS(EditorResourcePicker);
- GDREGISTER_CLASS(EditorScriptPicker);
- GDREGISTER_ABSTRACT_CLASS(EditorUndoRedoManager);
-
- GDREGISTER_ABSTRACT_CLASS(FileSystemDock);
- GDREGISTER_VIRTUAL_CLASS(EditorFileSystemImportFormatSupportQuery);
-
- GDREGISTER_CLASS(EditorScenePostImport);
- GDREGISTER_CLASS(EditorCommandPalette);
- GDREGISTER_CLASS(EditorDebuggerPlugin);
-}
-
-void EditorNode::unregister_editor_types() {
- _init_callbacks.clear();
- if (EditorPaths::get_singleton()) {
- EditorPaths::free();
- }
-
- EditorResourcePicker::clear_caches();
-}
-
void EditorNode::stop_child_process(OS::ProcessID p_pid) {
if (has_child_process(p_pid)) {
editor_run.stop_child_process(p_pid);
@@ -5233,6 +5114,10 @@ bool EditorNode::immediate_confirmation_dialog(const String &p_text, const Strin
return singleton->immediate_dialog_confirmed;
}
+void EditorNode::cleanup() {
+ _init_callbacks.clear();
+}
+
int EditorNode::get_current_tab() {
return scene_tabs->get_current_tab();
}
@@ -5761,7 +5646,7 @@ void EditorNode::_global_menu_new_window(const Variant &p_tag) {
}
void EditorNode::_dropped_files(const Vector<String> &p_files) {
- String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_selected_path());
+ String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_current_directory());
_add_dropped_files_recursive(p_files, to_path);
@@ -7100,7 +6985,7 @@ EditorNode::EditorNode() {
FileSystemDock *filesystem_dock = memnew(FileSystemDock);
filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request));
- filesystem_dock->connect("instance", callable_mp(this, &EditorNode::_instantiate_request));
+ filesystem_dock->connect("instantiate", callable_mp(this, &EditorNode::_instantiate_request));
filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks));
get_project_settings()->connect_filesystem_dock_signals(filesystem_dock);
@@ -7323,7 +7208,6 @@ EditorNode::EditorNode() {
add_child(audio_preview_gen);
add_editor_plugin(memnew(DebuggerEditorPlugin(debug_menu)));
- add_editor_plugin(memnew(DebugAdapterServer()));
disk_changed = memnew(ConfirmationDialog);
{
@@ -7373,63 +7257,7 @@ EditorNode::EditorNode() {
raise_bottom_panel_item(AnimationPlayerEditor::get_singleton());
add_editor_plugin(VersionControlEditorPlugin::get_singleton());
-
- // This list is alphabetized, and plugins that depend on Node2D are in their own section below.
- add_editor_plugin(memnew(AnimationTreeEditorPlugin));
add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor)));
- add_editor_plugin(memnew(AudioStreamRandomizerEditorPlugin));
- add_editor_plugin(memnew(BitMapEditorPlugin));
- add_editor_plugin(memnew(BoneMapEditorPlugin));
- add_editor_plugin(memnew(Camera3DEditorPlugin));
- add_editor_plugin(memnew(ControlEditorPlugin));
- add_editor_plugin(memnew(CPUParticles3DEditorPlugin));
- add_editor_plugin(memnew(CurveEditorPlugin));
- add_editor_plugin(memnew(FontEditorPlugin));
- add_editor_plugin(memnew(GPUParticles3DEditorPlugin));
- add_editor_plugin(memnew(GPUParticlesCollisionSDF3DEditorPlugin));
- add_editor_plugin(memnew(GradientEditorPlugin));
- add_editor_plugin(memnew(GradientTexture2DEditorPlugin));
- add_editor_plugin(memnew(InputEventEditorPlugin));
- add_editor_plugin(memnew(LightmapGIEditorPlugin));
- add_editor_plugin(memnew(MaterialEditorPlugin));
- add_editor_plugin(memnew(MeshEditorPlugin));
- add_editor_plugin(memnew(MeshInstance3DEditorPlugin));
- add_editor_plugin(memnew(MeshLibraryEditorPlugin));
- add_editor_plugin(memnew(MultiMeshEditorPlugin));
- add_editor_plugin(memnew(OccluderInstance3DEditorPlugin));
- add_editor_plugin(memnew(Path3DEditorPlugin));
- add_editor_plugin(memnew(PhysicalBone3DEditorPlugin));
- add_editor_plugin(memnew(Polygon3DEditorPlugin));
- add_editor_plugin(memnew(ResourcePreloaderEditorPlugin));
- add_editor_plugin(memnew(ShaderEditorPlugin));
- add_editor_plugin(memnew(ShaderFileEditorPlugin));
- add_editor_plugin(memnew(Skeleton3DEditorPlugin));
- add_editor_plugin(memnew(SkeletonIK3DEditorPlugin));
- add_editor_plugin(memnew(SpriteFramesEditorPlugin));
- add_editor_plugin(memnew(StyleBoxEditorPlugin));
- add_editor_plugin(memnew(SubViewportPreviewEditorPlugin));
- add_editor_plugin(memnew(Texture3DEditorPlugin));
- add_editor_plugin(memnew(TextureEditorPlugin));
- add_editor_plugin(memnew(TextureLayeredEditorPlugin));
- add_editor_plugin(memnew(TextureRegionEditorPlugin));
- add_editor_plugin(memnew(ThemeEditorPlugin));
- add_editor_plugin(memnew(VoxelGIEditorPlugin));
-
- // 2D
- add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin));
- add_editor_plugin(memnew(CollisionShape2DEditorPlugin));
- add_editor_plugin(memnew(CPUParticles2DEditorPlugin));
- add_editor_plugin(memnew(GPUParticles2DEditorPlugin));
- add_editor_plugin(memnew(LightOccluder2DEditorPlugin));
- add_editor_plugin(memnew(Line2DEditorPlugin));
- add_editor_plugin(memnew(NavigationLink2DEditorPlugin));
- add_editor_plugin(memnew(NavigationPolygonEditorPlugin));
- add_editor_plugin(memnew(Path2DEditorPlugin));
- add_editor_plugin(memnew(Polygon2DEditorPlugin));
- add_editor_plugin(memnew(Cast2DEditorPlugin));
- add_editor_plugin(memnew(Skeleton2DEditorPlugin));
- add_editor_plugin(memnew(Sprite2DEditorPlugin));
- add_editor_plugin(memnew(TilesEditorPlugin));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {
add_editor_plugin(EditorPlugins::create(i));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index f27fe429b9..ff0338a794 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -713,9 +713,6 @@ public:
bool call_build();
- static void register_editor_types();
- static void unregister_editor_types();
-
static EditorNode *get_singleton() { return singleton; }
static EditorLog *get_log() { return singleton->log; }
@@ -749,6 +746,8 @@ public:
static bool immediate_confirmation_dialog(const String &p_text, const String &p_ok_text = TTR("Ok"), const String &p_cancel_text = TTR("Cancel"));
+ static void cleanup();
+
EditorPlugin *get_editor_plugin_screen() { return editor_plugin_screen; }
EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; }
EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; }
@@ -816,7 +815,7 @@ public:
void setup_color_picker(ColorPicker *picker);
- void request_instance_scene(const String &p_path);
+ void request_instantiate_scene(const String &p_path);
void request_instantiate_scenes(const Vector<String> &p_files);
void set_convert_old_scene(bool p_old) { convert_old = p_old; }
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 8fca21ae7b..e11bc3c252 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -30,15 +30,20 @@
#include "editor_plugin.h"
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_command_palette.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_settings.h"
+#include "editor/editor_translation_parser.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/export/editor_export.h"
#include "editor/filesystem_dock.h"
+#include "editor/import/editor_import_plugin.h"
+#include "editor/import/resource_importer_scene.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/project_settings_editor.h"
@@ -238,14 +243,18 @@ void EditorInterface::select_file(const String &p_file) {
FileSystemDock::get_singleton()->select_file(p_file);
}
-String EditorInterface::get_selected_path() const {
- return FileSystemDock::get_singleton()->get_selected_path();
+Vector<String> EditorInterface::get_selected_paths() const {
+ return FileSystemDock::get_singleton()->get_selected_paths();
}
String EditorInterface::get_current_path() const {
return FileSystemDock::get_singleton()->get_current_path();
}
+String EditorInterface::get_current_directory() const {
+ return FileSystemDock::get_singleton()->get_current_directory();
+}
+
void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property, bool p_inspector_only) {
EditorNode::get_singleton()->push_item(p_obj, p_for_property, p_inspector_only);
}
@@ -363,8 +372,9 @@ void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_editor_main_screen"), &EditorInterface::get_editor_main_screen);
ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews);
ClassDB::bind_method(D_METHOD("select_file", "file"), &EditorInterface::select_file);
- ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path);
+ ClassDB::bind_method(D_METHOD("get_selected_paths"), &EditorInterface::get_selected_paths);
ClassDB::bind_method(D_METHOD("get_current_path"), &EditorInterface::get_current_path);
+ ClassDB::bind_method(D_METHOD("get_current_directory"), &EditorInterface::get_current_directory);
ClassDB::bind_method(D_METHOD("get_file_system_dock"), &EditorInterface::get_file_system_dock);
ClassDB::bind_method(D_METHOD("get_editor_paths"), &EditorInterface::get_editor_paths);
ClassDB::bind_method(D_METHOD("get_command_palette"), &EditorInterface::get_command_palette);
@@ -837,12 +847,12 @@ ScriptCreateDialog *EditorPlugin::get_script_create_dialog() {
return SceneTreeDock::get_singleton()->get_script_create_dialog();
}
-void EditorPlugin::add_debugger_plugin(const Ref<Script> &p_script) {
- EditorDebuggerNode::get_singleton()->add_debugger_plugin(p_script);
+void EditorPlugin::add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ EditorDebuggerNode::get_singleton()->add_debugger_plugin(p_plugin);
}
-void EditorPlugin::remove_debugger_plugin(const Ref<Script> &p_script) {
- EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_script);
+void EditorPlugin::remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) {
+ EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_plugin);
}
void EditorPlugin::_editor_project_settings_changed() {
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 753ccedf70..d736675faf 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -32,32 +32,34 @@
#define EDITOR_PLUGIN_H
#include "core/io/config_file.h"
-#include "editor/debugger/editor_debugger_node.h"
-#include "editor/editor_inspector.h"
-#include "editor/editor_translation_parser.h"
-#include "editor/import/editor_import_plugin.h"
-#include "editor/import/resource_importer_scene.h"
-#include "editor/script_create_dialog.h"
#include "scene/3d/camera_3d.h"
-#include "scene/main/node.h"
-#include "scene/resources/texture.h"
+#include "scene/gui/control.h"
class Node3D;
-class Camera3D;
+class Button;
+class PopupMenu;
class EditorCommandPalette;
-class EditorSelection;
+class EditorDebuggerPlugin;
class EditorExport;
-class EditorSettings;
-class EditorImportPlugin;
class EditorExportPlugin;
+class EditorFileSystem;
+class EditorImportPlugin;
+class EditorInspector;
+class EditorInspectorPlugin;
class EditorNode3DGizmoPlugin;
+class EditorPaths;
class EditorResourcePreview;
-class EditorUndoRedoManager;
-class EditorFileSystem;
+class EditorSceneFormatImporter;
+class EditorScenePostImportPlugin;
+class EditorSelection;
+class EditorSettings;
class EditorToolAddons;
-class EditorPaths;
+class EditorTranslationParserPlugin;
+class EditorUndoRedoManager;
class FileSystemDock;
+class ScriptCreateDialog;
class ScriptEditor;
+class VBoxContainer;
class EditorInterface : public Node {
GDCLASS(EditorInterface, Node);
@@ -92,8 +94,9 @@ public:
EditorCommandPalette *get_command_palette() const;
void select_file(const String &p_file);
- String get_selected_path() const;
+ Vector<String> get_selected_paths() const;
String get_current_path() const;
+ String get_current_directory() const;
void inspect_object(Object *p_obj, const String &p_for_property = String(), bool p_inspector_only = false);
@@ -301,8 +304,8 @@ public:
void add_autoload_singleton(const String &p_name, const String &p_path);
void remove_autoload_singleton(const String &p_name);
- void add_debugger_plugin(const Ref<Script> &p_script);
- void remove_debugger_plugin(const Ref<Script> &p_script);
+ void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
+ void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin);
void enable_plugin();
void disable_plugin();
@@ -319,7 +322,7 @@ typedef EditorPlugin *(*EditorPluginCreateFunc)();
class EditorPlugins {
enum {
- MAX_CREATE_FUNCS = 64
+ MAX_CREATE_FUNCS = 128
};
static EditorPluginCreateFunc creation_funcs[MAX_CREATE_FUNCS];
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index d71976a1af..30e4710444 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -1169,9 +1169,9 @@ void EditorPropertyLayers::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- button->set_normal_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- button->set_pressed_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
- button->set_disabled_texture(get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons")));
+ button->set_texture_normal(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ button->set_texture_pressed(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ button->set_texture_disabled(get_theme_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons")));
} break;
}
}
@@ -1811,8 +1811,8 @@ void EditorPropertyVector2::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 2; i++) {
@@ -2089,8 +2089,8 @@ void EditorPropertyVector3::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 3; i++) {
@@ -2224,8 +2224,8 @@ void EditorPropertyVector2i::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 2; i++) {
@@ -2475,8 +2475,8 @@ void EditorPropertyVector3i::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
- linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ linked->set_texture_normal(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons")));
+ linked->set_texture_pressed(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
const Color *colors = _get_property_colors();
for (int i = 0; i < 3; i++) {
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 20b130f57f..ad36e01544 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -639,7 +639,7 @@ class EditorPropertyQuaternion : public EditorProperty {
EditorSpinSlider *euler[3];
Button *edit_button = nullptr;
- Vector3 edit_euler = Vector3();
+ Vector3 edit_euler;
void _value_changed(double p_val, const String &p_name);
void _edit_custom_value();
diff --git a/editor/editor_quick_open.cpp b/editor/editor_quick_open.cpp
index b4ec3bca15..50429878f9 100644
--- a/editor/editor_quick_open.cpp
+++ b/editor/editor_quick_open.cpp
@@ -33,7 +33,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-void EditorQuickOpen::popup_dialog(const StringName &p_base, bool p_enable_multi, bool p_dontclear) {
+void EditorQuickOpen::popup_dialog(const String &p_base, bool p_enable_multi, bool p_dontclear) {
base_type = p_base;
allow_multi_select = p_enable_multi;
search_options->set_select_mode(allow_multi_select ? Tree::SELECT_MULTI : Tree::SELECT_SINGLE);
@@ -56,7 +56,7 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) {
_build_search_cache(p_efsd->get_subdir(i));
}
- Vector<String> base_types = String(base_type).split(String(","));
+ Vector<String> base_types = base_type.split(",");
for (int i = 0; i < p_efsd->get_file_count(); i++) {
String file = p_efsd->get_file_path(i);
String engine_type = p_efsd->get_file_type(i);
@@ -80,7 +80,7 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) {
// Store refs to used icons.
String ext = file.get_extension();
if (!icons.has(ext)) {
- icons.insert(ext, get_theme_icon((has_theme_icon(actual_type, SNAME("EditorIcons")) ? actual_type : String("Object")), SNAME("EditorIcons")));
+ icons.insert(ext, get_theme_icon((has_theme_icon(actual_type, SNAME("EditorIcons")) ? actual_type : "Object"), SNAME("EditorIcons")));
}
// Stop testing base types as soon as we got a match.
@@ -231,7 +231,7 @@ Vector<String> EditorQuickOpen::get_selected_files() const {
return selected_files;
}
-StringName EditorQuickOpen::get_base_type() const {
+String EditorQuickOpen::get_base_type() const {
return base_type;
}
diff --git a/editor/editor_quick_open.h b/editor/editor_quick_open.h
index 83cbbd7cac..3b7e8136ef 100644
--- a/editor/editor_quick_open.h
+++ b/editor/editor_quick_open.h
@@ -41,7 +41,7 @@ class EditorQuickOpen : public ConfirmationDialog {
LineEdit *search_box = nullptr;
Tree *search_options = nullptr;
- StringName base_type;
+ String base_type;
bool allow_multi_select = false;
bool _load_resources = false; // Prohibitively slow for now.
@@ -77,12 +77,12 @@ protected:
static void _bind_methods();
public:
- StringName get_base_type() const;
+ String get_base_type() const;
String get_selected() const;
Vector<String> get_selected_files() const;
- void popup_dialog(const StringName &p_base, bool p_enable_multi = false, bool p_dontclear = false);
+ void popup_dialog(const String &p_base, bool p_enable_multi = false, bool p_dontclear = false);
EditorQuickOpen();
};
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 0b38996b2d..acc8b3b6a2 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -256,7 +256,7 @@ void EditorResourcePicker::_update_menu_items() {
paste_valid = ClassDB::is_parent_class(res_type, base) || EditorNode::get_editor_data().script_class_is_parent(res_type, base);
- if (!paste_valid) {
+ if (paste_valid) {
break;
}
}
@@ -438,7 +438,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
}
if (!obj) {
- obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource");
+ obj = EditorNode::get_editor_data().instantiate_custom_type(intype, "Resource");
}
Resource *resp = Object::cast_to<Resource>(obj);
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 41d5d1b0d2..913a0ba104 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -31,6 +31,7 @@
#include "editor_run.h"
#include "core/config/project_settings.h"
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "main/main.h"
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index a4e907b46f..bc186c7a16 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -412,7 +412,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/custom_display_scale", 1.0, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/main_font_size", 14, "8,48,1")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/code_font_size", 14, "8,48,1")
- EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 0, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set")
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 1, "Enabled,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set")
_initial_set("interface/editor/code_font_custom_opentype_features", "");
_initial_set("interface/editor/code_font_custom_variations", "");
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_antialiasing", 1, "None,Grayscale,LCD Subpixel")
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index a72c545b2f..77a0d9f85c 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -487,6 +487,7 @@ void EditorSettingsDialog::_update_shortcuts() {
TreeItem *section = E.value;
if (section->get_first_child() == nullptr) {
root->remove_child(section);
+ memdelete(section);
}
}
}
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 1cdfceebc8..11a8fce9c3 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -619,11 +619,9 @@ bool EditorSpinSlider::is_grabbing() const {
void EditorSpinSlider::_focus_entered() {
_ensure_input_popup();
- Rect2 gr = get_screen_rect();
value_input->set_text(get_text_value());
- value_input_popup->set_position(gr.position);
- value_input_popup->set_size(gr.size);
- value_input_popup->call_deferred(SNAME("popup"));
+ value_input_popup->set_size(get_size());
+ value_input_popup->call_deferred(SNAME("show"));
value_input->call_deferred(SNAME("grab_focus"));
value_input->call_deferred(SNAME("select_all"));
value_input->set_focus_next(find_next_valid_focus()->get_path());
@@ -658,14 +656,13 @@ void EditorSpinSlider::_ensure_input_popup() {
return;
}
- value_input_popup = memnew(Popup);
+ value_input_popup = memnew(Control);
add_child(value_input_popup);
value_input = memnew(LineEdit);
value_input_popup->add_child(value_input);
- value_input_popup->set_wrap_controls(true);
value_input->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
- value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
+ value_input_popup->connect("hidden", callable_mp(this, &EditorSpinSlider::_value_input_closed));
value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted));
value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
value_input->connect("gui_input", callable_mp(this, &EditorSpinSlider::_value_input_gui_input));
diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h
index afcaa3e4b6..fd5c3dc5df 100644
--- a/editor/editor_spin_slider.h
+++ b/editor/editor_spin_slider.h
@@ -63,7 +63,7 @@ class EditorSpinSlider : public Range {
Vector2 grabbing_spinner_mouse_pos;
double pre_grab_value = 0.0;
- Popup *value_input_popup = nullptr;
+ Control *value_input_popup = nullptr;
LineEdit *value_input = nullptr;
bool value_input_just_closed = false;
bool value_input_dirty = false;
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 17b5eb3314..692deb3beb 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1491,6 +1491,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("normal", "RichTextLabel", style_tree_bg);
// Editor help.
+ Ref<StyleBoxFlat> style_editor_help = style_default->duplicate();
+ style_editor_help->set_bg_color(dark_color_2);
+ style_editor_help->set_border_color(dark_color_3);
+ theme->set_stylebox("background", "EditorHelp", style_editor_help);
+
theme->set_color("title_color", "EditorHelp", accent_color);
theme->set_color("headline_color", "EditorHelp", mono_color);
theme->set_color("text_color", "EditorHelp", font_color);
@@ -1503,9 +1508,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8));
theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6));
theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6));
+ theme->set_color("code_bg_color", "EditorHelp", dark_color_3);
+ theme->set_color("kbd_bg_color", "EditorHelp", dark_color_1);
+ theme->set_color("param_bg_color", "EditorHelp", dark_color_1);
theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE));
theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE);
theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE);
+ theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE);
+ theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE);
// Panel
theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width));
diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp
index 09b567fc68..4bfa9b686c 100644
--- a/editor/editor_undo_redo_manager.cpp
+++ b/editor/editor_undo_redo_manager.cpp
@@ -33,6 +33,7 @@
#include "core/io/resource.h"
#include "core/os/os.h"
#include "core/templates/local_vector.h"
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "scene/main/node.h"
@@ -109,9 +110,14 @@ EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Ob
}
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode) {
- pending_action.action_name = p_name;
- pending_action.timestamp = OS::get_singleton()->get_unix_time();
- pending_action.merge_mode = p_mode;
+ if (pending_action.history_id != INVALID_HISTORY) {
+ // Nested action.
+ p_history_id = pending_action.history_id;
+ } else {
+ pending_action.action_name = p_name;
+ pending_action.timestamp = OS::get_singleton()->get_unix_time();
+ pending_action.merge_mode = p_mode;
+ }
if (p_history_id != INVALID_HISTORY) {
pending_action.history_id = p_history_id;
@@ -228,6 +234,12 @@ void EditorUndoRedoManager::commit_action(bool p_execute) {
history.undo_redo->commit_action(p_execute);
history.redo_stack.clear();
+ if (history.undo_redo->get_action_level() > 0) {
+ // Nested action.
+ is_committing = false;
+ return;
+ }
+
if (!history.undo_stack.is_empty()) {
const Action &prev_action = history.undo_stack.back()->get();
if (pending_action.merge_mode != UndoRedo::MERGE_DISABLE && pending_action.merge_mode == prev_action.merge_mode && pending_action.action_name == prev_action.action_name) {
diff --git a/editor/event_listener_line_edit.cpp b/editor/event_listener_line_edit.cpp
index e4c35a5b81..1b081f9091 100644
--- a/editor/event_listener_line_edit.cpp
+++ b/editor/event_listener_line_edit.cpp
@@ -30,6 +30,72 @@
#include "editor/event_listener_line_edit.h"
+#include "core/input/input_map.h"
+
+// Maps to 2*axis if value is neg, or 2*axis+1 if value is pos.
+static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = {
+ TTRC("Left Stick Left, Joystick 0 Left"),
+ TTRC("Left Stick Right, Joystick 0 Right"),
+ TTRC("Left Stick Up, Joystick 0 Up"),
+ TTRC("Left Stick Down, Joystick 0 Down"),
+ TTRC("Right Stick Left, Joystick 1 Left"),
+ TTRC("Right Stick Right, Joystick 1 Right"),
+ TTRC("Right Stick Up, Joystick 1 Up"),
+ TTRC("Right Stick Down, Joystick 1 Down"),
+ TTRC("Joystick 2 Left"),
+ TTRC("Left Trigger, Sony L2, Xbox LT, Joystick 2 Right"),
+ TTRC("Joystick 2 Up"),
+ TTRC("Right Trigger, Sony R2, Xbox RT, Joystick 2 Down"),
+ TTRC("Joystick 3 Left"),
+ TTRC("Joystick 3 Right"),
+ TTRC("Joystick 3 Up"),
+ TTRC("Joystick 3 Down"),
+ TTRC("Joystick 4 Left"),
+ TTRC("Joystick 4 Right"),
+ TTRC("Joystick 4 Up"),
+ TTRC("Joystick 4 Down"),
+};
+
+String EventListenerLineEdit::get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) {
+ ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
+
+ String text = p_event->as_text();
+
+ Ref<InputEventKey> key = p_event;
+ if (key.is_valid() && key->is_command_or_control_autoremap()) {
+#ifdef MACOS_ENABLED
+ text = text.replace("Command", "Command/Ctrl");
+#else
+ text = text.replace("Ctrl", "Command/Ctrl");
+#endif
+ }
+ Ref<InputEventMouse> mouse = p_event;
+ Ref<InputEventJoypadMotion> jp_motion = p_event;
+ Ref<InputEventJoypadButton> jp_button = p_event;
+ if (jp_motion.is_valid()) {
+ // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
+ String desc = TTR("Unknown Joypad Axis");
+ if (jp_motion->get_axis() < JoyAxis::MAX) {
+ desc = RTR(_joy_axis_descriptions[2 * (size_t)jp_motion->get_axis() + (jp_motion->get_axis_value() < 0 ? 0 : 1)]);
+ }
+
+ text = vformat("Joypad Axis %s %s (%s)", itos((int64_t)jp_motion->get_axis()), jp_motion->get_axis_value() < 0 ? "-" : "+", desc);
+ }
+ if (p_include_device && (mouse.is_valid() || jp_button.is_valid() || jp_motion.is_valid())) {
+ String device_string = get_device_string(p_event->get_device());
+ text += vformat(" - %s", device_string);
+ }
+
+ return text;
+}
+
+String EventListenerLineEdit::get_device_string(int p_device) {
+ if (p_device == InputMap::ALL_DEVICES) {
+ return TTR("All Devices");
+ }
+ return TTR("Device") + " " + itos(p_device);
+}
+
bool EventListenerLineEdit::_is_event_allowed(const Ref<InputEvent> &p_event) const {
const Ref<InputEventMouseButton> mb = p_event;
const Ref<InputEventKey> k = p_event;
@@ -71,7 +137,7 @@ void EventListenerLineEdit::gui_input(const Ref<InputEvent> &p_event) {
}
event = p_event;
- set_text(event->as_text());
+ set_text(get_event_text(event, false));
emit_signal("event_changed", event);
}
diff --git a/editor/event_listener_line_edit.h b/editor/event_listener_line_edit.h
index c4cd5e4511..487efbc368 100644
--- a/editor/event_listener_line_edit.h
+++ b/editor/event_listener_line_edit.h
@@ -61,6 +61,9 @@ protected:
static void _bind_methods();
public:
+ static String get_event_text(const Ref<InputEvent> &p_event, bool p_include_device);
+ static String get_device_string(int p_device);
+
Ref<InputEvent> get_event() const;
void clear_event();
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 62bcf0b193..8df5808b11 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -42,6 +42,7 @@
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/import/resource_importer_scene.h"
#include "editor/import_dock.h"
#include "editor/scene_create_dialog.h"
#include "editor/scene_tree_dock.h"
@@ -511,7 +512,15 @@ void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_s
}
}
-String FileSystemDock::get_selected_path() const {
+Vector<String> FileSystemDock::get_selected_paths() const {
+ return _tree_get_selected(false);
+}
+
+String FileSystemDock::get_current_path() const {
+ return path;
+}
+
+String FileSystemDock::get_current_directory() const {
if (path.ends_with("/")) {
return path;
} else {
@@ -519,10 +528,6 @@ String FileSystemDock::get_selected_path() const {
}
}
-String FileSystemDock::get_current_path() const {
- return path;
-}
-
void FileSystemDock::_set_current_path_text(const String &p_path) {
if (p_path == "Favorites") {
current_path->set_text(TTR("Favorites"));
@@ -1726,7 +1731,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove
}
}
-Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) {
+Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) const {
// Build a list of selected items with the active one at the first position.
Vector<String> selected_strings;
@@ -1847,8 +1852,8 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
}
} break;
- case FILE_INSTANCE: {
- // Instance all selected scenes.
+ case FILE_INSTANTIATE: {
+ // Instantiate all selected scenes.
Vector<String> paths;
for (int i = 0; i < p_selected.size(); i++) {
String fpath = p_selected[i];
@@ -1857,7 +1862,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
}
}
if (!paths.is_empty()) {
- emit_signal(SNAME("instance"), paths);
+ emit_signal(SNAME("instantiate"), paths);
}
} break;
@@ -2072,7 +2077,7 @@ void FileSystemDock::_resource_created() {
return;
}
- Variant c = new_resource_dialog->instance_selected();
+ Variant c = new_resource_dialog->instantiate_selected();
ERR_FAIL_COND(!c);
Resource *r = Object::cast_to<Resource>(c);
@@ -2535,7 +2540,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str
} else {
p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open Scenes"), FILE_OPEN);
}
- p_popup->add_icon_item(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instance"), FILE_INSTANCE);
+ p_popup->add_icon_item(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instantiate"), FILE_INSTANTIATE);
p_popup->add_separator();
} else if (filenames.size() == 1) {
p_popup->add_icon_item(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")), TTR("Open"), FILE_OPEN);
@@ -2989,7 +2994,7 @@ void FileSystemDock::_file_sort_popup(int p_id) {
MenuButton *FileSystemDock::_create_file_menu_button() {
MenuButton *button = memnew(MenuButton);
button->set_flat(true);
- button->set_tooltip_text(TTR("Sort files"));
+ button->set_tooltip_text(TTR("Sort Files"));
PopupMenu *p = button->get_popup();
p->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_sort_popup));
@@ -3018,7 +3023,7 @@ void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock);
ADD_SIGNAL(MethodInfo("inherit", PropertyInfo(Variant::STRING, "file")));
- ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
+ ADD_SIGNAL(MethodInfo("instantiate", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("file_removed", PropertyInfo(Variant::STRING, "file")));
ADD_SIGNAL(MethodInfo("folder_removed", PropertyInfo(Variant::STRING, "folder")));
@@ -3052,14 +3057,14 @@ FileSystemDock::FileSystemDock() {
button_hist_prev->set_flat(true);
button_hist_prev->set_disabled(true);
button_hist_prev->set_focus_mode(FOCUS_NONE);
- button_hist_prev->set_tooltip_text(TTR("Previous Folder/File"));
+ button_hist_prev->set_tooltip_text(TTR("Go to previous selected folder/file."));
toolbar_hbc->add_child(button_hist_prev);
button_hist_next = memnew(Button);
button_hist_next->set_flat(true);
button_hist_next->set_disabled(true);
button_hist_next->set_focus_mode(FOCUS_NONE);
- button_hist_next->set_tooltip_text(TTR("Next Folder/File"));
+ button_hist_next->set_tooltip_text(TTR("Go to next selected folder/file."));
toolbar_hbc->add_child(button_hist_next);
current_path = memnew(LineEdit);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index f39ca9e74d..c4ce500c1e 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -79,7 +79,7 @@ private:
FILE_OPEN,
FILE_INHERIT,
FILE_MAIN_SCENE,
- FILE_INSTANCE,
+ FILE_INSTANTIATE,
FILE_ADD_FAVORITE,
FILE_REMOVE_FAVORITE,
FILE_DEPENDENCIES,
@@ -297,12 +297,12 @@ private:
void _update_display_mode(bool p_force = false);
- Vector<String> _tree_get_selected(bool remove_self_inclusion = true);
+ Vector<String> _tree_get_selected(bool remove_self_inclusion = true) const;
bool _is_file_type_disabled_by_feature_profile(const StringName &p_class);
void _feature_profile_changed();
- Vector<String> _remove_self_included_paths(Vector<String> selected_strings);
+ static Vector<String> _remove_self_included_paths(Vector<String> selected_strings);
private:
static FileSystemDock *singleton;
@@ -315,9 +315,11 @@ protected:
static void _bind_methods();
public:
- String get_selected_path() const;
+ Vector<String> get_selected_paths() const;
String get_current_path() const;
+ String get_current_directory() const;
+
void navigate_to_path(const String &p_path);
void focus_on_filter();
diff --git a/editor/history_dock.cpp b/editor/history_dock.cpp
index 57088a76cb..47b7e9f5d7 100644
--- a/editor/history_dock.cpp
+++ b/editor/history_dock.cpp
@@ -219,6 +219,8 @@ void HistoryDock::_notification(int p_notification) {
}
HistoryDock::HistoryDock() {
+ set_name("History");
+
ur_manager = EditorNode::get_undo_redo();
ur_manager->connect("history_changed", callable_mp(this, &HistoryDock::on_history_changed));
ur_manager->connect("version_changed", callable_mp(this, &HistoryDock::on_version_changed));
diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp
index d94b517003..f635c74547 100644
--- a/editor/import/audio_stream_import_settings.cpp
+++ b/editor/import/audio_stream_import_settings.cpp
@@ -32,6 +32,7 @@
#include "editor/audio_stream_preview.h"
#include "editor/editor_file_system.h"
#include "editor/editor_scale.h"
+#include "scene/gui/check_box.h"
AudioStreamImportSettings *AudioStreamImportSettings::singleton = nullptr;
@@ -287,17 +288,15 @@ void AudioStreamImportSettings::_draw_indicator() {
float preview_len = zoom_bar->get_page();
float beat_size = 60 / float(stream->get_bpm());
int prev_beat = 0;
- int last_text_end_x = 0;
for (int i = 0; i < rect.size.width; i++) {
float ofs = preview_offset + i * preview_len / rect.size.width;
int beat = int(ofs / beat_size);
if (beat != prev_beat) {
String text = itos(beat);
int text_w = beat_font->get_string_size(text).width;
- if (i - text_w / 2 > last_text_end_x + 2 * EDSCALE && beat == _hovering_beat) {
+ if (i - text_w / 2 > 2 * EDSCALE && beat == _hovering_beat) {
int x_ofs = i - text_w / 2;
_indicator->draw_string(beat_font, Point2(x_ofs, 2 * EDSCALE + beat_font->get_ascent(main_size)), text, HORIZONTAL_ALIGNMENT_LEFT, rect.size.width - x_ofs, Font::DEFAULT_FONT_SIZE, color);
- last_text_end_x = i + text_w / 2;
break;
}
prev_beat = beat;
diff --git a/editor/import/audio_stream_import_settings.h b/editor/import/audio_stream_import_settings.h
index 5e399237ca..fc756c6524 100644
--- a/editor/import/audio_stream_import_settings.h
+++ b/editor/import/audio_stream_import_settings.h
@@ -34,9 +34,12 @@
#include "editor/editor_plugin.h"
#include "scene/audio/audio_stream_player.h"
#include "scene/gui/color_rect.h"
+#include "scene/gui/dialogs.h"
#include "scene/gui/spin_box.h"
#include "scene/resources/texture.h"
+class CheckBox;
+
class AudioStreamImportSettings : public ConfirmationDialog {
GDCLASS(AudioStreamImportSettings, ConfirmationDialog);
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index f61ff5182d..8f15becd95 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -30,6 +30,7 @@
#include "dynamic_font_import_settings.h"
+#include "core/config/project_settings.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_file_system.h"
#include "editor/editor_inspector.h"
@@ -528,6 +529,12 @@ void DynamicFontImportSettings::_variation_selected() {
label_glyphs->set_text(TTR("Preloaded glyphs: ") + itos(import_variation_data->selected_glyphs.size()));
_range_selected();
_change_text_opts();
+
+ btn_fill->set_disabled(false);
+ btn_fill_locales->set_disabled(false);
+ } else {
+ btn_fill->set_disabled(true);
+ btn_fill_locales->set_disabled(true);
}
}
@@ -551,6 +558,15 @@ void DynamicFontImportSettings::_variation_remove(Object *p_item, int p_column,
}
_variations_validate();
+
+ vars_item = vars_list->get_selected();
+ if (vars_item) {
+ btn_fill->set_disabled(false);
+ btn_fill_locales->set_disabled(false);
+ } else {
+ btn_fill->set_disabled(true);
+ btn_fill_locales->set_disabled(true);
+ }
}
void DynamicFontImportSettings::_variation_changed(const String &p_edited_property) {
@@ -623,6 +639,27 @@ void DynamicFontImportSettings::_change_text_opts() {
text_edit->add_theme_font_override("font", font_main_text);
}
+void DynamicFontImportSettings::_glyph_update_lbl() {
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
+ return;
+ }
+
+ int linked_glyphs = 0;
+ for (const char32_t &c : import_variation_data->selected_chars) {
+ if (import_variation_data->selected_glyphs.has(font_main->get_glyph_index(16, c))) {
+ linked_glyphs++;
+ }
+ }
+ int unlinked_glyphs = import_variation_data->selected_glyphs.size() - linked_glyphs;
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(unlinked_glyphs + import_variation_data->selected_chars.size()));
+}
+
void DynamicFontImportSettings::_glyph_clear() {
Ref<DynamicFontImportSettingsData> import_variation_data;
@@ -635,7 +672,7 @@ void DynamicFontImportSettings::_glyph_clear() {
}
import_variation_data->selected_glyphs.clear();
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
_range_selected();
}
@@ -662,7 +699,7 @@ void DynamicFontImportSettings::_glyph_text_selected() {
}
}
TS->free_rid(text_rid);
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
}
_range_selected();
}
@@ -699,7 +736,7 @@ void DynamicFontImportSettings::_glyph_selected() {
item->clear_custom_bg_color(glyph_table->get_selected_column());
}
}
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
item = glyph_tree->get_selected();
ERR_FAIL_NULL(item);
@@ -800,7 +837,7 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) {
col = 0;
}
}
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
+ _glyph_update_lbl();
}
bool DynamicFontImportSettings::_char_update(int32_t p_char) {
@@ -947,10 +984,73 @@ void DynamicFontImportSettings::_re_import() {
EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "font_data_dynamic", main_settings);
}
+void DynamicFontImportSettings::_locale_edited() {
+ TreeItem *item = locale_tree->get_selected();
+ ERR_FAIL_NULL(item);
+ item->set_checked(0, !item->is_checked(0));
+}
+
+void DynamicFontImportSettings::_process_locales() {
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
+ return;
+ }
+
+ for (int i = 0; i < locale_root->get_child_count(); i++) {
+ TreeItem *item = locale_root->get_child(i);
+ if (item) {
+ if (item->is_checked(0)) {
+ String locale = item->get_text(0);
+ Ref<Translation> tr = ResourceLoader::load(locale);
+ if (tr.is_valid()) {
+ Vector<String> messages = tr->get_translated_message_list();
+ for (const String &E : messages) {
+ RID text_rid = TS->create_shaped_text();
+ if (text_rid.is_valid()) {
+ TS->shaped_text_add_string(text_rid, E, font_main->get_rids(), 16, Dictionary(), tr->get_locale());
+ TS->shaped_text_shape(text_rid);
+ const Glyph *gl = TS->shaped_text_get_glyphs(text_rid);
+ const int gl_size = TS->shaped_text_get_glyph_count(text_rid);
+
+ for (int j = 0; j < gl_size; j++) {
+ if (gl[j].font_rid.is_valid() && gl[j].index != 0) {
+ import_variation_data->selected_glyphs.insert(gl[j].index);
+ }
+ }
+ TS->free_rid(text_rid);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ _glyph_update_lbl();
+ _range_selected();
+}
+
void DynamicFontImportSettings::open_settings(const String &p_path) {
// Load base font data.
Vector<uint8_t> font_data = FileAccess::get_file_as_array(p_path);
+ // Load project locale list.
+ locale_tree->clear();
+ locale_root = locale_tree->create_item();
+ ERR_FAIL_NULL(locale_root);
+
+ Vector<String> translations = GLOBAL_GET("internationalization/locale/translations");
+ for (const String &E : translations) {
+ TreeItem *item = locale_tree->create_item(locale_root);
+ ERR_FAIL_NULL(item);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_text(0, E);
+ }
+
// Load font for preview.
font_preview.instantiate();
font_preview->set_data(font_data);
@@ -1003,10 +1103,11 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
int gww = get_theme_font(SNAME("font"))->get_string_size("00000").x + 50;
glyph_table->set_column_custom_minimum_width(0, gww);
-
glyph_table->clear();
vars_list->clear();
+ glyph_tree->set_selected(glyph_root->get_child(0));
+
vars_list_root = vars_list->create_item();
import_settings_data->settings.clear();
@@ -1080,6 +1181,10 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
import_variation_data_custom->selected_glyphs.insert(c);
}
}
+ if (preload_configurations.is_empty()) {
+ _variation_add(); // Add default variation.
+ }
+ vars_list->set_selected(vars_list_root->get_child(0));
} else {
Variant value = config->get_value("params", key);
import_settings_data->defaults[key] = value;
@@ -1269,11 +1374,57 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
inspector_vars->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_variation_changed));
page2_side_vb->add_child(inspector_vars);
+ VBoxContainer *preload_pages_vb = memnew(VBoxContainer);
+ page2_hb->add_child(preload_pages_vb);
+
preload_pages = memnew(TabContainer);
preload_pages->set_tab_alignment(TabBar::ALIGNMENT_CENTER);
preload_pages->set_v_size_flags(Control::SIZE_EXPAND_FILL);
preload_pages->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- page2_hb->add_child(preload_pages);
+ preload_pages_vb->add_child(preload_pages);
+
+ HBoxContainer *gl_hb = memnew(HBoxContainer);
+ preload_pages_vb->add_child(gl_hb);
+ gl_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ label_glyphs = memnew(Label);
+ gl_hb->add_child(label_glyphs);
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(0));
+ label_glyphs->set_custom_minimum_size(Size2(50 * EDSCALE, 0));
+
+ Button *btn_clear = memnew(Button);
+ gl_hb->add_child(btn_clear);
+ btn_clear->set_text(TTR("Clear Glyph List"));
+ btn_clear->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_clear));
+
+ VBoxContainer *page2_0_vb = memnew(VBoxContainer);
+ page2_0_vb->set_name(TTR("Glyphs from the Translations"));
+ preload_pages->add_child(page2_0_vb);
+
+ page2_0_description = memnew(Label);
+ page2_0_description->set_text(TTR("Select translations to add all required glyphs to pre-render list:"));
+ page2_0_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page2_0_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
+ page2_0_vb->add_child(page2_0_description);
+
+ locale_tree = memnew(Tree);
+ page2_0_vb->add_child(locale_tree);
+ locale_tree->set_columns(1);
+ locale_tree->set_hide_root(true);
+ locale_tree->set_column_expand(0, true);
+ locale_tree->connect("item_activated", callable_mp(this, &DynamicFontImportSettings::_locale_edited));
+ locale_tree->set_column_custom_minimum_width(0, 120 * EDSCALE);
+ locale_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ locale_root = locale_tree->create_item();
+
+ HBoxContainer *locale_hb = memnew(HBoxContainer);
+ page2_0_vb->add_child(locale_hb);
+ locale_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ btn_fill_locales = memnew(Button);
+ locale_hb->add_child(btn_fill_locales);
+ btn_fill_locales->set_text(TTR("Shape all Strings in the Translations and Add Glyphs"));
+ btn_fill_locales->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_process_locales));
// Page 2.1 layout: Text to select glyphs
VBoxContainer *page2_1_vb = memnew(VBoxContainer);
@@ -1281,7 +1432,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
preload_pages->add_child(page2_1_vb);
page2_1_description = memnew(Label);
- page2_1_description->set_text(TTR("Enter a text to shape and add all required glyphs to pre-render list:"));
+ page2_1_description->set_text(TTR("Enter a text and select OpenType features to shape and add all required glyphs to pre-render list:"));
page2_1_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
page2_1_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
page2_1_vb->add_child(page2_1_description);
@@ -1307,21 +1458,11 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
page2_1_vb->add_child(text_hb);
text_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- label_glyphs = memnew(Label);
- text_hb->add_child(label_glyphs);
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(0));
- label_glyphs->set_custom_minimum_size(Size2(50 * EDSCALE, 0));
-
- Button *btn_fill = memnew(Button);
+ btn_fill = memnew(Button);
text_hb->add_child(btn_fill);
btn_fill->set_text(TTR("Shape Text and Add Glyphs"));
btn_fill->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_text_selected));
- Button *btn_clear = memnew(Button);
- text_hb->add_child(btn_clear);
- btn_clear->set_text(TTR("Clear Glyph List"));
- btn_clear->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_clear));
-
// Page 2.2 layout: Character map
VBoxContainer *page2_2_vb = memnew(VBoxContainer);
page2_2_vb->set_name(TTR("Glyphs from the Character Map"));
diff --git a/editor/import/dynamic_font_import_settings.h b/editor/import/dynamic_font_import_settings.h
index a1f763b445..386e9896dc 100644
--- a/editor/import/dynamic_font_import_settings.h
+++ b/editor/import/dynamic_font_import_settings.h
@@ -118,18 +118,30 @@ class DynamicFontImportSettings : public ConfirmationDialog {
TabContainer *preload_pages = nullptr;
+ Label *label_glyphs = nullptr;
+ void _glyph_clear();
+ void _glyph_update_lbl();
+
+ // Page 2.0 layout: Translations
+ Label *page2_0_description = nullptr;
+ Tree *locale_tree = nullptr;
+ TreeItem *locale_root = nullptr;
+ Button *btn_fill_locales = nullptr;
+
+ void _locale_edited();
+ void _process_locales();
+
// Page 2.1 layout: Text to select glyphs
Label *page2_1_description = nullptr;
- Label *label_glyphs = nullptr;
TextEdit *text_edit = nullptr;
EditorInspector *inspector_text = nullptr;
+ Button *btn_fill = nullptr;
List<ResourceImporter::ImportOption> options_text;
Ref<DynamicFontImportSettingsData> text_settings_data;
void _change_text_opts();
void _glyph_text_selected();
- void _glyph_clear();
// Page 2.2 layout: Character map
Label *page2_2_description = nullptr;
diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/post_import_plugin_skeleton_renamer.cpp
index 72ccb832c7..c2694329c2 100644
--- a/editor/import/post_import_plugin_skeleton_renamer.cpp
+++ b/editor/import/post_import_plugin_skeleton_renamer.cpp
@@ -44,100 +44,164 @@ void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImport
}
}
-void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) {
- if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
- // Prepare objects.
- Object *map = p_options["retarget/bone_map"].get_validated_object();
- if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) {
- return;
- }
- BoneMap *bone_map = Object::cast_to<BoneMap>(map);
- Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
+void PostImportPluginSkeletonRenamer::_internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, HashMap<String, String> p_rename_map) {
+ // Prepare objects.
+ Object *map = p_options["retarget/bone_map"].get_validated_object();
+ if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) {
+ return;
+ }
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
- // Rename bones in Skeleton3D.
- {
- int len = skeleton->get_bone_count();
- for (int i = 0; i < len; i++) {
- StringName bn = bone_map->find_profile_bone_name(skeleton->get_bone_name(i));
- if (bn) {
- skeleton->set_bone_name(i, bn);
- }
+ // Rename bones in Skeleton3D.
+ {
+ int len = skeleton->get_bone_count();
+ for (int i = 0; i < len; i++) {
+ StringName bn = p_rename_map[skeleton->get_bone_name(i)];
+ if (bn) {
+ skeleton->set_bone_name(i, bn);
}
}
+ }
- // Rename bones in Skin.
- {
- TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
- while (nodes.size()) {
- ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
- Ref<Skin> skin = mi->get_skin();
- if (skin.is_valid()) {
- Node *node = mi->get_node(mi->get_skeleton_path());
- if (node) {
- Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
- if (mesh_skeleton && node == skeleton) {
- int len = skin->get_bind_count();
- for (int i = 0; i < len; i++) {
- StringName bn = bone_map->find_profile_bone_name(skin->get_bind_name(i));
- if (bn) {
- skin->set_bind_name(i, bn);
- }
+ // Rename bones in Skin.
+ {
+ TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
+ while (nodes.size()) {
+ ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
+ Ref<Skin> skin = mi->get_skin();
+ if (skin.is_valid()) {
+ Node *node = mi->get_node(mi->get_skeleton_path());
+ if (node) {
+ Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (mesh_skeleton && node == skeleton) {
+ int len = skin->get_bind_count();
+ for (int i = 0; i < len; i++) {
+ StringName bn = p_rename_map[skin->get_bind_name(i)];
+ if (bn) {
+ skin->set_bind_name(i, bn);
}
}
}
}
}
}
+ }
- // Rename bones in AnimationPlayer.
- {
- TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
- while (nodes.size()) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for (const StringName &name : anims) {
- Ref<Animation> anim = ap->get_animation(name);
- int len = anim->get_track_count();
- for (int i = 0; i < len; i++) {
- if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) {
- continue;
- }
- String track_path = String(anim->track_get_path(i).get_concatenated_names());
- Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
- if (node) {
- Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
- if (track_skeleton && track_skeleton == skeleton) {
- StringName bn = bone_map->find_profile_bone_name(anim->track_get_path(i).get_subname(0));
- if (bn) {
- anim->track_set_path(i, track_path + ":" + bn);
- }
+ // Rename bones in AnimationPlayer.
+ {
+ TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
+ while (nodes.size()) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (const StringName &name : anims) {
+ Ref<Animation> anim = ap->get_animation(name);
+ int len = anim->get_track_count();
+ for (int i = 0; i < len; i++) {
+ if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) {
+ continue;
+ }
+ String track_path = String(anim->track_get_path(i).get_concatenated_names());
+ Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
+ if (node) {
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (track_skeleton && track_skeleton == skeleton) {
+ StringName bn = p_rename_map[anim->track_get_path(i).get_subname(0)];
+ if (bn) {
+ anim->track_set_path(i, track_path + ":" + bn);
}
}
}
}
}
}
+ }
+
+ // Rename bones in all Nodes by calling method.
+ {
+ Vector<Variant> vargs;
+ vargs.push_back(p_base_scene);
+ vargs.push_back(skeleton);
+ Dictionary rename_map_dict;
+ for (HashMap<String, String>::Iterator E = p_rename_map.begin(); E; ++E) {
+ rename_map_dict[E->key] = E->value;
+ }
+ vargs.push_back(rename_map_dict);
+ const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * vargs.size());
+ const Variant *args = vargs.ptr();
+ uint32_t argcount = vargs.size();
+ for (uint32_t i = 0; i < argcount; i++) {
+ argptrs[i] = &args[i];
+ }
+
+ TypedArray<Node> nodes = p_base_scene->find_children("*");
+ while (nodes.size()) {
+ Node *nd = Object::cast_to<Node>(nodes.pop_back());
+ Callable::CallError ce;
+ nd->callp("_notify_skeleton_bones_renamed", argptrs, argcount, ce);
+ }
+ }
+}
+
+void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) {
+ if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
+ // Prepare objects.
+ Object *map = p_options["retarget/bone_map"].get_validated_object();
+ if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) {
+ return;
+ }
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
+ BoneMap *bone_map = Object::cast_to<BoneMap>(map);
+ int len = skeleton->get_bone_count();
+
+ // First, prepare main rename map.
+ HashMap<String, String> main_rename_map;
+ for (int i = 0; i < len; i++) {
+ String bone_name = skeleton->get_bone_name(i);
+ String target_name = bone_map->find_profile_bone_name(bone_name);
+ if (target_name.is_empty()) {
+ continue;
+ }
+ main_rename_map.insert(bone_name, target_name);
+ }
- // Rename bones in all Nodes by calling method.
+ // Preprocess of renaming bones to avoid to conflict with original bone name.
+ HashMap<String, String> pre_rename_map; // HashMap<skeleton bone name, target(profile) bone name>
{
- Vector<Variant> vargs;
- vargs.push_back(p_base_scene);
- vargs.push_back(skeleton);
- vargs.push_back(bone_map);
- const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * vargs.size());
- const Variant *args = vargs.ptr();
- uint32_t argcount = vargs.size();
- for (uint32_t i = 0; i < argcount; i++) {
- argptrs[i] = &args[i];
+ Vector<String> solved_name_stack;
+ for (int i = 0; i < len; i++) {
+ String bone_name = skeleton->get_bone_name(i);
+ String target_name = bone_map->find_profile_bone_name(bone_name);
+ if (target_name.is_empty() || bone_name == target_name || skeleton->find_bone(target_name) == -1) {
+ continue; // No conflicting.
+ }
+
+ // Solve conflicting.
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ String solved_name = target_name;
+ for (int j = 2; skeleton->find_bone(solved_name) >= 0 || profile->find_bone(solved_name) >= 0 || solved_name_stack.has(solved_name); j++) {
+ solved_name = target_name + itos(j);
+ }
+ solved_name_stack.push_back(solved_name);
+ pre_rename_map.insert(target_name, solved_name);
}
+ _internal_process(p_category, p_base_scene, p_node, p_resource, p_options, pre_rename_map);
+ }
- TypedArray<Node> nodes = p_base_scene->find_children("*");
- while (nodes.size()) {
- Node *nd = Object::cast_to<Node>(nodes.pop_back());
- Callable::CallError ce;
- nd->callp("_notify_skeleton_bones_renamed", argptrs, argcount, ce);
+ // Main process of renaming bones.
+ {
+ // Apply pre-renaming result to prepared main rename map.
+ Vector<String> remove_queue;
+ for (HashMap<String, String>::Iterator E = main_rename_map.begin(); E; ++E) {
+ if (pre_rename_map.has(E->key)) {
+ remove_queue.push_back(E->key);
+ }
+ }
+ for (int i = 0; i < remove_queue.size(); i++) {
+ main_rename_map.insert(pre_rename_map[remove_queue[i]], main_rename_map[remove_queue[i]]);
+ main_rename_map.erase(remove_queue[i]);
}
+ _internal_process(p_category, p_base_scene, p_node, p_resource, p_options, main_rename_map);
}
// Make unique skeleton.
diff --git a/editor/import/post_import_plugin_skeleton_renamer.h b/editor/import/post_import_plugin_skeleton_renamer.h
index 73cbabd1c5..b430f49ff4 100644
--- a/editor/import/post_import_plugin_skeleton_renamer.h
+++ b/editor/import/post_import_plugin_skeleton_renamer.h
@@ -40,6 +40,8 @@ public:
virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) override;
virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) override;
+ void _internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options, HashMap<String, String> p_rename_map);
+
PostImportPluginSkeletonRenamer();
};
diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp
index 58c2061051..9d15854707 100644
--- a/editor/import/resource_importer_imagefont.cpp
+++ b/editor/import/resource_importer_imagefont.cpp
@@ -63,7 +63,8 @@ void ResourceImporterImageFont::get_import_options(const String &p_path, List<Im
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "character_ranges"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows"), 1));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "font_size"), 14));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::RECT2I, "image_margin"), Rect2i()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::RECT2I, "character_margin"), Rect2i()));
r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
@@ -93,33 +94,39 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
int columns = p_options["columns"];
int rows = p_options["rows"];
- int base_size = p_options["font_size"];
Vector<String> ranges = p_options["character_ranges"];
Array fallbacks = p_options["fallbacks"];
+ Rect2i img_margin = p_options["image_margin"];
+ Rect2i char_margin = p_options["character_margin"];
+
+ Ref<Image> img;
+ img.instantiate();
+ Error err = ImageLoader::load_image(p_source_file, img);
+ ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture:") + " \"" + p_source_file + "\".");
+
+ int count = columns * rows;
+ int chr_cell_width = (img->get_width() - img_margin.position.x - img_margin.size.x) / columns;
+ int chr_cell_height = (img->get_height() - img_margin.position.y - img_margin.size.y) / rows;
+ ERR_FAIL_COND_V_MSG(chr_cell_width <= 0 || chr_cell_height <= 0, ERR_FILE_CANT_READ, TTR("Image margin too big."));
+
+ int chr_width = chr_cell_width - char_margin.position.x - char_margin.size.x;
+ int chr_height = chr_cell_height - char_margin.position.y - char_margin.size.y;
+ ERR_FAIL_COND_V_MSG(chr_width <= 0 || chr_height <= 0, ERR_FILE_CANT_READ, TTR("Character margin too bit."));
Ref<FontFile> font;
font.instantiate();
font->set_antialiasing(TextServer::FONT_ANTIALIASING_NONE);
font->set_generate_mipmaps(false);
font->set_multichannel_signed_distance_field(false);
- font->set_fixed_size(base_size);
+ font->set_fixed_size(chr_height);
font->set_subpixel_positioning(TextServer::SUBPIXEL_POSITIONING_DISABLED);
font->set_force_autohinter(false);
font->set_hinting(TextServer::HINTING_NONE);
font->set_oversampling(1.0f);
font->set_fallbacks(fallbacks);
+ font->set_texture_image(0, Vector2i(chr_height, 0), 0, img);
- Ref<Image> img;
- img.instantiate();
- Error err = ImageLoader::load_image(p_source_file, img);
- ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture:") + " \"" + p_source_file + "\".");
- font->set_texture_image(0, Vector2i(base_size, 0), 0, img);
-
- int count = columns * rows;
- int chr_width = img->get_width() / columns;
- int chr_height = img->get_height() / rows;
int pos = 0;
-
for (int i = 0; i < ranges.size(); i++) {
int32_t start, end;
Vector<String> tokens = ranges[i].split("-");
@@ -141,17 +148,17 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
for (int32_t idx = start; idx <= end; idx++) {
int x = pos % columns;
int y = pos / columns;
- font->set_glyph_advance(0, base_size, idx, Vector2(chr_width, 0));
- font->set_glyph_offset(0, Vector2i(base_size, 0), idx, Vector2(0, -0.5 * chr_height));
- font->set_glyph_size(0, Vector2i(base_size, 0), idx, Vector2(chr_width, chr_height));
- font->set_glyph_uv_rect(0, Vector2i(base_size, 0), idx, Rect2(chr_width * x, chr_height * y, chr_width, chr_height));
- font->set_glyph_texture_idx(0, Vector2i(base_size, 0), idx, 0);
+ font->set_glyph_advance(0, chr_height, idx, Vector2(chr_width, 0));
+ font->set_glyph_offset(0, Vector2i(chr_height, 0), idx, Vector2(0, -0.5 * chr_height));
+ font->set_glyph_size(0, Vector2i(chr_height, 0), idx, Vector2(chr_width, chr_height));
+ font->set_glyph_uv_rect(0, Vector2i(chr_height, 0), idx, Rect2(img_margin.position.x + chr_cell_width * x + char_margin.position.x, img_margin.position.y + chr_cell_height * y + char_margin.position.y, chr_width, chr_height));
+ font->set_glyph_texture_idx(0, Vector2i(chr_height, 0), idx, 0);
pos++;
- ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range.");
+ ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range, should be " + itos(columns * rows));
}
}
- font->set_cache_ascent(0, base_size, 0.5 * chr_height);
- font->set_cache_descent(0, base_size, 0.5 * chr_height);
+ font->set_cache_ascent(0, chr_height, 0.5 * chr_height);
+ font->set_cache_descent(0, chr_height, 0.5 * chr_height);
int flg = 0;
if ((bool)p_options["compress"]) {
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index a6a0eef11b..f7a3ce2679 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -402,7 +402,7 @@ void _rescale_importer_mesh(Vector3 p_scale, Ref<ImporterMesh> p_mesh, bool is_s
const int fmt_compress_flags = p_mesh->get_surface_format(surf_idx);
Array arr = p_mesh->get_surface_arrays(surf_idx);
String name = p_mesh->get_surface_name(surf_idx);
- Dictionary lods = Dictionary();
+ Dictionary lods;
Ref<Material> mat = p_mesh->get_surface_material(surf_idx);
{
Vector<Vector3> vertex_array = arr[ArrayMesh::ARRAY_VERTEX];
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 1dcae2841b..f5a0f0abcf 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -107,7 +107,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
file->get_buffer((uint8_t *)&riff, 4); //RIFF
if (riff[0] != 'R' || riff[1] != 'I' || riff[2] != 'F' || riff[3] != 'F') {
- ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. File should start with 'RIFF', but found '%s', in file of size %d bytes", riff, file->get_length()));
}
/* GET FILESIZE */
@@ -115,12 +115,12 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
/* CHECK WAVE */
- char wave[4];
-
- file->get_buffer((uint8_t *)&wave, 4); //RIFF
+ char wave[5];
+ wave[4] = 0;
+ file->get_buffer((uint8_t *)&wave, 4); //WAVE
if (wave[0] != 'W' || wave[1] != 'A' || wave[2] != 'V' || wave[3] != 'E') {
- ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Not a WAV file (no WAVE RIFF header).");
+ ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. Header should contain 'WAVE', but found '%s', in file of size %d bytes", wave, file->get_length()));
}
// Let users override potential loop points from the WAV.
diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp
index c577c61db7..cb2a8205c2 100644
--- a/editor/input_event_configuration_dialog.cpp
+++ b/editor/input_event_configuration_dialog.cpp
@@ -38,63 +38,6 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
-// Maps to 2*axis if value is neg, or 2*axis+1 if value is pos.
-static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = {
- TTRC("Left Stick Left, Joystick 0 Left"),
- TTRC("Left Stick Right, Joystick 0 Right"),
- TTRC("Left Stick Up, Joystick 0 Up"),
- TTRC("Left Stick Down, Joystick 0 Down"),
- TTRC("Right Stick Left, Joystick 1 Left"),
- TTRC("Right Stick Right, Joystick 1 Right"),
- TTRC("Right Stick Up, Joystick 1 Up"),
- TTRC("Right Stick Down, Joystick 1 Down"),
- TTRC("Joystick 2 Left"),
- TTRC("Left Trigger, Sony L2, Xbox LT, Joystick 2 Right"),
- TTRC("Joystick 2 Up"),
- TTRC("Right Trigger, Sony R2, Xbox RT, Joystick 2 Down"),
- TTRC("Joystick 3 Left"),
- TTRC("Joystick 3 Right"),
- TTRC("Joystick 3 Up"),
- TTRC("Joystick 3 Down"),
- TTRC("Joystick 4 Left"),
- TTRC("Joystick 4 Right"),
- TTRC("Joystick 4 Up"),
- TTRC("Joystick 4 Down"),
-};
-
-String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const {
- ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
-
- String text = p_event->as_text();
-
- Ref<InputEventKey> key = p_event;
- if (key.is_valid() && key->is_command_or_control_autoremap()) {
-#ifdef MACOS_ENABLED
- text = text.replace("Command", "Command/Ctrl");
-#else
- text = text.replace("Ctrl", "Command/Ctrl");
-#endif
- }
- Ref<InputEventMouse> mouse = p_event;
- Ref<InputEventJoypadMotion> jp_motion = p_event;
- Ref<InputEventJoypadButton> jp_button = p_event;
- if (jp_motion.is_valid()) {
- // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
- String desc = TTR("Unknown Joypad Axis");
- if (jp_motion->get_axis() < JoyAxis::MAX) {
- desc = RTR(_joy_axis_descriptions[2 * (size_t)jp_motion->get_axis() + (jp_motion->get_axis_value() < 0 ? 0 : 1)]);
- }
-
- text = vformat("Joypad Axis %s %s (%s)", itos((int64_t)jp_motion->get_axis()), jp_motion->get_axis_value() < 0 ? "-" : "+", desc);
- }
- if (p_include_device && (mouse.is_valid() || jp_button.is_valid() || jp_motion.is_valid())) {
- String device_string = _get_device_string(p_event->get_device());
- text += vformat(" - %s", device_string);
- }
-
- return text;
-}
-
void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, bool p_update_input_list_selection) {
if (p_event.is_valid()) {
event = p_event;
@@ -107,7 +50,7 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, b
}
// Update Label
- event_as_text->set_text(get_event_text(event, true));
+ event_as_text->set_text(EventListenerLineEdit::get_event_text(event, true));
Ref<InputEventKey> k = p_event;
Ref<InputEventMouseButton> mb = p_event;
@@ -222,14 +165,7 @@ void InputEventConfigurationDialog::_on_listen_input_changed(const Ref<InputEven
}
if (joym.is_valid()) {
- float axis_value = joym->get_axis_value();
- if (ABS(axis_value) < 0.9) {
- // Ignore motion below 0.9 magnitude to avoid accidental touches
- return;
- } else {
- // Always make the value 1 or -1 for display consistency
- joym->set_axis_value(SIGN(axis_value));
- }
+ joym->set_axis_value(SIGN(joym->get_axis_value()));
}
if (k.is_valid()) {
@@ -305,7 +241,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventMouseButton> mb;
mb.instantiate();
mb->set_button_index(mouse_buttons[i]);
- String desc = get_event_text(mb, false);
+ String desc = EventListenerLineEdit::get_event_text(mb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -328,7 +264,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventJoypadButton> joyb;
joyb.instantiate();
joyb->set_button_index((JoyButton)i);
- String desc = get_event_text(joyb, false);
+ String desc = EventListenerLineEdit::get_event_text(joyb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -354,7 +290,7 @@ void InputEventConfigurationDialog::_update_input_list() {
joym.instantiate();
joym->set_axis((JoyAxis)axis);
joym->set_axis_value(direction);
- String desc = get_event_text(joym, false);
+ String desc = EventListenerLineEdit::get_event_text(joym, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -513,7 +449,7 @@ void InputEventConfigurationDialog::_device_selection_changed(int p_option_butto
// Subtract 1 as option index 0 corresponds to "All Devices" (value of -1)
// and option index 1 corresponds to device 0, etc...
event->set_device(p_option_button_index - 1);
- event_as_text->set_text(get_event_text(event, true));
+ event_as_text->set_text(EventListenerLineEdit::get_event_text(event, true));
}
void InputEventConfigurationDialog::_set_current_device(int p_device) {
@@ -524,13 +460,6 @@ int InputEventConfigurationDialog::_get_current_device() const {
return device_id_option->get_selected() - 1;
}
-String InputEventConfigurationDialog::_get_device_string(int p_device) const {
- if (p_device == InputMap::ALL_DEVICES) {
- return TTR("All Devices");
- }
- return TTR("Device") + " " + itos(p_device);
-}
-
void InputEventConfigurationDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -659,7 +588,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
device_id_option = memnew(OptionButton);
device_id_option->set_h_size_flags(Control::SIZE_EXPAND_FILL);
for (int i = -1; i < 8; i++) {
- device_id_option->add_item(_get_device_string(i));
+ device_id_option->add_item(EventListenerLineEdit::get_device_string(i));
}
device_id_option->connect("item_selected", callable_mp(this, &InputEventConfigurationDialog::_device_selection_changed));
_set_current_device(InputMap::ALL_DEVICES);
diff --git a/editor/input_event_configuration_dialog.h b/editor/input_event_configuration_dialog.h
index fc590cba26..eb6eb485ea 100644
--- a/editor/input_event_configuration_dialog.h
+++ b/editor/input_event_configuration_dialog.h
@@ -105,7 +105,6 @@ private:
void _device_selection_changed(int p_option_button_index);
void _set_current_device(int p_device);
int _get_current_device() const;
- String _get_device_string(int p_device) const;
protected:
void _notification(int p_what);
@@ -114,7 +113,6 @@ public:
// Pass an existing event to configure it. Alternatively, pass no event to start with a blank configuration.
void popup_and_configure(const Ref<InputEvent> &p_event = Ref<InputEvent>());
Ref<InputEvent> get_event() const;
- String get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const;
void set_allowed_input_types(int p_type_masks);
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index bd2eb5fd9e..8cb0e4e8d7 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -365,7 +365,7 @@ void InspectorDock::_select_history(int p_idx) {
}
void InspectorDock::_resource_created() {
- Variant c = new_resource_dialog->instance_selected();
+ Variant c = new_resource_dialog->instantiate_selected();
ERR_FAIL_COND(!c);
Resource *r = Object::cast_to<Resource>(c);
@@ -670,14 +670,14 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
backward_button = memnew(Button);
backward_button->set_flat(true);
general_options_hb->add_child(backward_button);
- backward_button->set_tooltip_text(TTR("Go to the previous edited object in history."));
+ backward_button->set_tooltip_text(TTR("Go to previous edited object in history."));
backward_button->set_disabled(true);
backward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_back));
forward_button = memnew(Button);
forward_button->set_flat(true);
general_options_hb->add_child(forward_button);
- forward_button->set_tooltip_text(TTR("Go to the next edited object in history."));
+ forward_button->set_tooltip_text(TTR("Go to next edited object in history."));
forward_button->set_disabled(true);
forward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_forward));
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index a7ebf21cd2..affb31945d 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -36,6 +36,7 @@
#include "editor/editor_plugin.h"
#include "editor/editor_scale.h"
#include "editor/project_settings_editor.h"
+#include "scene/gui/grid_container.h"
void PluginConfigDialog::_clear_fields() {
name_edit->set_text("");
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
index 8a3db9d837..8414945223 100644
--- a/editor/plugins/abstract_polygon_2d_editor.h
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -36,6 +36,7 @@
#include "scene/gui/box_container.h"
class CanvasItemEditor;
+class ConfirmationDialog;
class AbstractPolygon2DEditor : public HBoxContainer {
GDCLASS(AbstractPolygon2DEditor, HBoxContainer);
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index f16a6bfa88..d11217cc5e 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -69,7 +69,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
menu->add_submenu_item(TTR("Add Animation"), "animations");
- AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
+ AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_animation_tree();
ERR_FAIL_COND(!gp);
if (gp->has_node(gp->get_animation_player())) {
@@ -177,7 +177,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ AnimationTreeEditor::get_singleton()->get_animation_tree()->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
@@ -200,7 +200,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= blend_space->get_max_space() - blend_space->get_min_space();
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ AnimationTreeEditor::get_singleton()->get_animation_tree()->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
@@ -298,7 +298,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
color.a *= 0.5;
}
- float point = AnimationTreeEditor::get_singleton()->get_tree()->get(get_blend_position_path());
+ float point = AnimationTreeEditor::get_singleton()->get_animation_tree()->get(get_blend_position_path());
point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
point *= s.width;
@@ -568,10 +568,10 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
case NOTIFICATION_PROCESS: {
String error;
- if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ if (!AnimationTreeEditor::get_singleton()->get_animation_tree()->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (AnimationTreeEditor::get_singleton()->get_animation_tree()->is_state_invalid()) {
+ error = AnimationTreeEditor::get_singleton()->get_animation_tree()->get_invalid_state_reason();
}
if (error != error_label->get_text()) {
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index c8b01cb54b..54aa227c96 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -40,7 +40,8 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
-class EditorUndoRedoManager;
+class CheckBox;
+class PanelContainer;
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendSpace1DEditor, AnimationTreeNodeEditorPlugin);
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 6f206ff445..0adac598a6 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -42,6 +42,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
#include "scene/main/window.h"
@@ -114,7 +115,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
menu->add_submenu_item(TTR("Add Animation"), "animations");
- AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
+ AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_animation_tree();
ERR_FAIL_COND(!gp);
if (gp && gp->has_node(gp->get_animation_player())) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
@@ -269,7 +270,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ AnimationTreeEditor::get_singleton()->get_animation_tree()->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
@@ -305,7 +306,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space());
blend_pos += blend_space->get_min_space();
- AnimationTreeEditor::get_singleton()->get_tree()->set(get_blend_position_path(), blend_pos);
+ AnimationTreeEditor::get_singleton()->get_animation_tree()->set(get_blend_position_path(), blend_pos);
blend_space_draw->queue_redraw();
}
@@ -588,7 +589,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
color.a *= 0.5;
}
- Vector2 blend_pos = AnimationTreeEditor::get_singleton()->get_tree()->get(get_blend_position_path());
+ Vector2 blend_pos = AnimationTreeEditor::get_singleton()->get_animation_tree()->get(get_blend_position_path());
Vector2 point = blend_pos;
point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space());
@@ -796,12 +797,12 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
case NOTIFICATION_PROCESS: {
String error;
- if (!AnimationTreeEditor::get_singleton()->get_tree()) {
+ if (!AnimationTreeEditor::get_singleton()->get_animation_tree()) {
error = TTR("BlendSpace2D does not belong to an AnimationTree node.");
- } else if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ } else if (!AnimationTreeEditor::get_singleton()->get_animation_tree()->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (AnimationTreeEditor::get_singleton()->get_animation_tree()->is_state_invalid()) {
+ error = AnimationTreeEditor::get_singleton()->get_animation_tree()->get_invalid_state_reason();
} else if (blend_space->get_triangle_count() == 0) {
error = TTR("No triangles exist, so no blending can take place.");
}
diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h
index 1f015a1804..e4512b78a3 100644
--- a/editor/plugins/animation_blend_space_2d_editor.h
+++ b/editor/plugins/animation_blend_space_2d_editor.h
@@ -40,6 +40,10 @@
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
+class CheckBox;
+class OptionButton;
+class PanelContainer;
+
class EditorUndoRedoManager;
class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index 6d00e77a4b..1a4774b98b 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -96,7 +96,7 @@ Size2 AnimationNodeBlendTreeEditor::get_minimum_size() const {
}
void AnimationNodeBlendTreeEditor::_property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
- AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_tree();
+ AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_animation_tree();
updating = true;
undo_redo->create_action(TTR("Parameter Changed:") + " " + String(p_property), UndoRedo::MERGE_ENDS);
undo_redo->add_do_property(tree, p_property, p_value);
@@ -174,10 +174,10 @@ void AnimationNodeBlendTreeEditor::update_graph() {
continue;
}
String base_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E) + "/" + F.name;
- EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_tree(), F.type, base_path, F.hint, F.hint_string, F.usage);
+ EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_animation_tree(), F.type, base_path, F.hint, F.hint_string, F.usage);
if (prop) {
prop->set_read_only(read_only);
- prop->set_object_and_property(AnimationTreeEditor::get_singleton()->get_tree(), base_path);
+ prop->set_object_and_property(AnimationTreeEditor::get_singleton()->get_animation_tree(), base_path);
prop->update_property();
prop->set_name_split_ratio(0);
prop->connect("property_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_property_changed));
@@ -225,7 +225,7 @@ void AnimationNodeBlendTreeEditor::update_graph() {
ProgressBar *pb = memnew(ProgressBar);
- AnimationTree *player = AnimationTreeEditor::get_singleton()->get_tree();
+ AnimationTree *player = AnimationTreeEditor::get_singleton()->get_animation_tree();
if (player->has_node(player->get_animation_player())) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(player->get_node(player->get_animation_player()));
if (ap) {
@@ -589,14 +589,14 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
return false;
}
- NodePath player_path = AnimationTreeEditor::get_singleton()->get_tree()->get_animation_player();
+ NodePath player_path = AnimationTreeEditor::get_singleton()->get_animation_tree()->get_animation_player();
- if (!AnimationTreeEditor::get_singleton()->get_tree()->has_node(player_path)) {
+ if (!AnimationTreeEditor::get_singleton()->get_animation_tree()->has_node(player_path)) {
EditorNode::get_singleton()->show_warning(TTR("No animation player set, so unable to retrieve track names."));
return false;
}
- AnimationPlayer *player = Object::cast_to<AnimationPlayer>(AnimationTreeEditor::get_singleton()->get_tree()->get_node(player_path));
+ AnimationPlayer *player = Object::cast_to<AnimationPlayer>(AnimationTreeEditor::get_singleton()->get_animation_tree()->get_node(player_path));
if (!player) {
EditorNode::get_singleton()->show_warning(TTR("Player path set is invalid, so unable to retrieve track names."));
return false;
@@ -829,10 +829,10 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
case NOTIFICATION_PROCESS: {
String error;
- if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ if (!AnimationTreeEditor::get_singleton()->get_animation_tree()->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (AnimationTreeEditor::get_singleton()->get_animation_tree()->is_state_invalid()) {
+ error = AnimationTreeEditor::get_singleton()->get_animation_tree()->get_invalid_state_reason();
}
if (error != error_label->get_text()) {
@@ -849,13 +849,13 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
for (const AnimationNodeBlendTree::NodeConnection &E : conns) {
float activity = 0;
StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E.input_node;
- if (AnimationTreeEditor::get_singleton()->get_tree() && !AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- activity = AnimationTreeEditor::get_singleton()->get_tree()->get_connection_activity(path, E.input_index);
+ if (AnimationTreeEditor::get_singleton()->get_animation_tree() && !AnimationTreeEditor::get_singleton()->get_animation_tree()->is_state_invalid()) {
+ activity = AnimationTreeEditor::get_singleton()->get_animation_tree()->get_connection_activity(path, E.input_index);
}
graph->set_connection_activity(E.output_node, 0, E.input_node, E.input_index, activity);
}
- AnimationTree *graph_player = AnimationTreeEditor::get_singleton()->get_tree();
+ AnimationTree *graph_player = AnimationTreeEditor::get_singleton()->get_animation_tree();
AnimationPlayer *player = nullptr;
if (graph_player->has_node(graph_player->get_animation_player())) {
player = Object::cast_to<AnimationPlayer>(graph_player->get_node(graph_player->get_animation_player()));
@@ -871,7 +871,7 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
E.value->set_max(anim->get_length());
//StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E.input_node;
StringName time_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E.key) + "/time";
- E.value->set_value(AnimationTreeEditor::get_singleton()->get_tree()->get(time_path));
+ E.value->set_value(AnimationTreeEditor::get_singleton()->get_animation_tree()->get(time_path));
}
}
}
@@ -952,8 +952,8 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
undo_redo->create_action(TTR("Node Renamed"));
undo_redo->add_do_method(blend_tree.ptr(), "rename_node", prev_name, name);
undo_redo->add_undo_method(blend_tree.ptr(), "rename_node", name, prev_name);
- undo_redo->add_do_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + prev_name, base_path + name);
- undo_redo->add_undo_method(AnimationTreeEditor::get_singleton()->get_tree(), "rename_parameter", base_path + name, base_path + prev_name);
+ undo_redo->add_do_method(AnimationTreeEditor::get_singleton()->get_animation_tree(), "rename_parameter", base_path + prev_name, base_path + name);
+ undo_redo->add_undo_method(AnimationTreeEditor::get_singleton()->get_animation_tree(), "rename_parameter", base_path + name, base_path + prev_name);
undo_redo->add_do_method(this, "update_graph");
undo_redo->add_undo_method(this, "update_graph");
undo_redo->commit_action();
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h
index b55fc3b617..112c824d8e 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.h
+++ b/editor/plugins/animation_blend_tree_editor_plugin.h
@@ -31,17 +31,22 @@
#ifndef ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H
#define ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H
-#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
+#include "scene/gui/panel_container.h"
#include "scene/gui/popup.h"
#include "scene/gui/tree.h"
+class AcceptDialog;
+class CheckBox;
class ProgressBar;
class EditorFileDialog;
+class EditorProperty;
class EditorUndoRedoManager;
+class MenuButton;
+class PanelContainer;
class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 1ebe81c4b0..85739d0d8f 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -950,7 +950,7 @@ void AnimationPlayerEditor::_update_animation_list_icons() {
}
void AnimationPlayerEditor::_update_name_dialog_library_dropdown() {
- StringName current_library_name = StringName();
+ StringName current_library_name;
if (animation->has_selectable_items()) {
String current_animation_name = animation->get_item_text(animation->get_selected());
Ref<Animation> current_animation = player->get_animation(current_animation_name);
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index c32f9b1775..060e9d0d10 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -76,7 +76,7 @@ void AnimationNodeStateMachineEditor::edit(const Ref<AnimationNode> &p_node) {
}
void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEvent> &p_event) {
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_animation_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
if (playback.is_null()) {
return;
}
@@ -420,7 +420,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
if (mm.is_valid()) {
state_machine_draw->grab_focus();
- String new_over_node = StringName();
+ String new_over_node;
int new_over_node_what = -1;
if (tool_select->is_pressed()) {
for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order.
@@ -739,7 +739,7 @@ void AnimationNodeStateMachineEditor::_open_menu(const Vector2 &p_position) {
ClassDB::get_inheriters_from_class("AnimationRootNode", &classes);
menu->add_submenu_item(TTR("Add Animation"), "animations");
- AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree();
+ AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_animation_tree();
ERR_FAIL_COND(!gp);
if (gp && gp->has_node(gp->get_animation_player())) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player()));
@@ -1181,7 +1181,7 @@ void AnimationNodeStateMachineEditor::_clip_dst_line_to_rect(const Vector2 &p_fr
}
void AnimationNodeStateMachineEditor::_state_machine_draw() {
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_animation_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
Ref<StyleBoxFlat> style = get_theme_stylebox(SNAME("state_machine_frame"), SNAME("GraphNode"));
Ref<StyleBoxFlat> style_selected = get_theme_stylebox(SNAME("state_machine_selected_frame"), SNAME("GraphNode"));
@@ -1369,7 +1369,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
StringName fullpath = AnimationTreeEditor::get_singleton()->get_base_path() + String(tl.advance_condition_name);
- if (tl.advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_tree()->get(fullpath))) {
+ if (tl.advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_animation_tree()->get(fullpath))) {
tl.advance_condition_state = true;
tl.auto_advance = true;
}
@@ -1484,7 +1484,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_animation_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
if (!playback.is_valid() || !playback->is_playing()) {
return;
@@ -1578,15 +1578,15 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
case NOTIFICATION_PROCESS: {
String error;
- Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
+ Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_animation_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback");
if (error_time > 0) {
error = error_text;
error_time -= get_process_delta_time();
- } else if (!AnimationTreeEditor::get_singleton()->get_tree()->is_active()) {
+ } else if (!AnimationTreeEditor::get_singleton()->get_animation_tree()->is_active()) {
error = TTR("AnimationTree is inactive.\nActivate to enable playback, check node warnings if activation fails.");
- } else if (AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- error = AnimationTreeEditor::get_singleton()->get_tree()->get_invalid_state_reason();
+ } else if (AnimationTreeEditor::get_singleton()->get_animation_tree()->is_state_invalid()) {
+ error = AnimationTreeEditor::get_singleton()->get_animation_tree()->get_invalid_state_reason();
/*} else if (state_machine->get_parent().is_valid() && state_machine->get_parent()->is_class("AnimationNodeStateMachine")) {
if (state_machine->get_start_node() == StringName() || state_machine->get_end_node() == StringName()) {
error = TTR("Start and end nodes are needed for a sub-transition.");
@@ -1638,7 +1638,7 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
break;
}
- bool acstate = transition_lines[i].advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + String(transition_lines[i].advance_condition_name)));
+ bool acstate = transition_lines[i].advance_condition_name != StringName() && bool(AnimationTreeEditor::get_singleton()->get_animation_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + String(transition_lines[i].advance_condition_name)));
if (transition_lines[i].advance_condition_state != acstate) {
state_machine_draw->queue_redraw();
@@ -1693,7 +1693,7 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
Ref<AnimationNodeStateMachinePlayback> current_node_playback;
while (anodesm.is_valid()) {
- current_node_playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + next + "/playback");
+ current_node_playback = AnimationTreeEditor::get_singleton()->get_animation_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + next + "/playback");
next += "/" + current_node_playback->get_current_node();
anodesm = anodesm->get_node(current_node_playback->get_current_node());
}
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index d0828a5f52..180f238834 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -31,16 +31,17 @@
#ifndef ANIMATION_STATE_MACHINE_EDITOR_H
#define ANIMATION_STATE_MACHINE_EDITOR_H
-#include "editor/editor_plugin.h"
#include "editor/plugins/animation_tree_editor_plugin.h"
#include "scene/animation/animation_node_state_machine.h"
-#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
#include "scene/gui/popup.h"
#include "scene/gui/tree.h"
+class ConfirmationDialog;
class EditorFileDialog;
class EditorUndoRedoManager;
+class OptionButton;
+class PanelContainer;
class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeStateMachineEditor, AnimationTreeNodeEditorPlugin);
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 1de4fbaabc..61aa861a3f 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -74,6 +74,12 @@ void AnimationTreeEditor::edit(AnimationTree *p_tree) {
edit_path(path);
}
+void AnimationTreeEditor::_node_removed(Node *p_node) {
+ if (p_node == tree) {
+ tree = nullptr;
+ }
+}
+
void AnimationTreeEditor::_path_button_pressed(int p_path) {
edited_path.clear();
for (int i = 0; i <= p_path; i++) {
@@ -167,6 +173,9 @@ void AnimationTreeEditor::enter_editor(const String &p_path) {
void AnimationTreeEditor::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ get_tree()->connect("node_removed", callable_mp(this, &AnimationTreeEditor::_node_removed));
+ } break;
case NOTIFICATION_PROCESS: {
ObjectID root;
if (tree && tree->get_tree_root().is_valid()) {
@@ -181,6 +190,9 @@ void AnimationTreeEditor::_notification(int p_what) {
edit_path(edited_path);
}
} break;
+ case NOTIFICATION_EXIT_TREE: {
+ get_tree()->disconnect("node_removed", callable_mp(this, &AnimationTreeEditor::_node_removed));
+ } break;
}
}
diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h
index 9ef9fff8cd..e1d9536f03 100644
--- a/editor/plugins/animation_tree_editor_plugin.h
+++ b/editor/plugins/animation_tree_editor_plugin.h
@@ -35,8 +35,6 @@
#include "scene/animation/animation_tree.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
-#include "scene/gui/popup.h"
-#include "scene/gui/tree.h"
class EditorFileDialog;
@@ -71,12 +69,13 @@ class AnimationTreeEditor : public VBoxContainer {
protected:
void _notification(int p_what);
+ void _node_removed(Node *p_node);
static void _bind_methods();
static AnimationTreeEditor *singleton;
public:
- AnimationTree *get_tree() { return tree; }
+ AnimationTree *get_animation_tree() { return tree; }
void add_plugin(AnimationTreeNodeEditorPlugin *p_editor);
void remove_plugin(AnimationTreeNodeEditorPlugin *p_editor);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 51b65e8eb0..72bee901bf 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -65,13 +65,13 @@ void EditorAssetLibraryItem::set_image(int p_type, int p_index, const Ref<Textur
ERR_FAIL_COND(p_type != EditorAssetLibrary::IMAGE_QUEUE_ICON);
ERR_FAIL_COND(p_index != 0);
- icon->set_normal_texture(p_image);
+ icon->set_texture_normal(p_image);
}
void EditorAssetLibraryItem::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- icon->set_normal_texture(get_theme_icon(SNAME("ProjectIconLoading"), SNAME("EditorIcons")));
+ icon->set_texture_normal(get_theme_icon(SNAME("ProjectIconLoading"), SNAME("EditorIcons")));
category->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
author->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
price->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5));
@@ -402,7 +402,7 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("AssetLib")));
status->add_theme_color_override("font_color", get_theme_color(SNAME("status_color"), SNAME("AssetLib")));
- dismiss_button->set_normal_texture(get_theme_icon(SNAME("dismiss"), SNAME("AssetLib")));
+ dismiss_button->set_texture_normal(get_theme_icon(SNAME("dismiss"), SNAME("AssetLib")));
} break;
case NOTIFICATION_PROCESS: {
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 070d25e29f..2795892c2e 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -50,6 +50,9 @@
#include "scene/gui/texture_button.h"
#include "scene/main/http_request.h"
+class EditorFileDialog;
+class MenuButton;
+
class EditorAssetLibraryItem : public PanelContainer {
GDCLASS(EditorAssetLibraryItem, PanelContainer);
diff --git a/editor/plugins/bit_map_editor_plugin.h b/editor/plugins/bit_map_editor_plugin.h
index b045f8c751..8c65b1b6f1 100644
--- a/editor/plugins/bit_map_editor_plugin.h
+++ b/editor/plugins/bit_map_editor_plugin.h
@@ -31,9 +31,12 @@
#ifndef BIT_MAP_EDITOR_PLUGIN_H
#define BIT_MAP_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/resources/bit_map.h"
+class TextureRect;
+
class BitMapEditor : public VBoxContainer {
GDCLASS(BitMapEditor, VBoxContainer);
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
index c834e0e93e..9ceedb18b3 100644
--- a/editor/plugins/bone_map_editor_plugin.cpp
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -38,9 +38,9 @@
void BoneMapperButton::fetch_textures() {
if (selected) {
- set_normal_texture(get_theme_icon(SNAME("BoneMapperHandleSelected"), SNAME("EditorIcons")));
+ set_texture_normal(get_theme_icon(SNAME("BoneMapperHandleSelected"), SNAME("EditorIcons")));
} else {
- set_normal_texture(get_theme_icon(SNAME("BoneMapperHandle"), SNAME("EditorIcons")));
+ set_texture_normal(get_theme_icon(SNAME("BoneMapperHandle"), SNAME("EditorIcons")));
}
set_offset(SIDE_LEFT, 0);
set_offset(SIDE_RIGHT, 0);
@@ -742,7 +742,6 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
} else {
p_bone_map->_set_skeleton_bone_name("LeftEye", skeleton->get_bone_name(bone_idx));
}
- bone_idx = -1;
bone_idx = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_RIGHT, neck_or_head);
if (bone_idx == -1) {
@@ -750,7 +749,6 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
} else {
p_bone_map->_set_skeleton_bone_name("RightEye", skeleton->get_bone_name(bone_idx));
}
- bone_idx = -1;
picklist.clear();
// 4-2. Guess Jaw
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index baf335f5b4..0fe77ec400 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -412,7 +412,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
// Other nodes sides
if ((is_snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
- Transform2D to_snap_transform = Transform2D();
+ Transform2D to_snap_transform;
List<const CanvasItem *> exceptions = List<const CanvasItem *>();
for (const CanvasItem *E : p_other_nodes_exceptions) {
exceptions.push_back(E);
@@ -813,7 +813,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
Rect2 parent_rect = p_control->get_parent_anchorable_rect();
- Vector2 output = Vector2();
+ Vector2 output;
if (p_control->is_layout_rtl()) {
output.x = (parent_rect.size.x == 0) ? 0.0 : (parent_rect.size.x - p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
} else {
@@ -2268,7 +2268,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
}
- String suffix = String();
+ String suffix;
if (locked == 1) {
suffix = " (" + TTR("Locked") + ")";
} else if (locked == 2) {
@@ -2790,7 +2790,7 @@ void CanvasItemEditor::_draw_rulers() {
int font_size = get_theme_font_size(SNAME("rulers_size"), SNAME("EditorFonts"));
// The rule transform
- Transform2D ruler_transform = Transform2D();
+ Transform2D ruler_transform;
if (grid_snap_active || _is_grid_visible()) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (snap_relative && selection.size() > 0) {
@@ -2816,11 +2816,11 @@ void CanvasItemEditor::_draw_rulers() {
// Subdivisions
int major_subdivision = 2;
- Transform2D major_subdivide = Transform2D();
+ Transform2D major_subdivide;
major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision));
int minor_subdivision = 5;
- Transform2D minor_subdivide = Transform2D();
+ Transform2D minor_subdivide;
minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision));
// First and last graduations to draw (in the ruler space)
@@ -3032,7 +3032,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
- Point2 v_angle_text_pos = Point2();
+ Point2 v_angle_text_pos;
v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
viewport->draw_string_outline(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
@@ -3043,7 +3043,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
- Point2 h_angle_text_pos = Point2();
+ Point2 h_angle_text_pos;
h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
if (begin.y < end.y) {
h_angle_text_pos.y = end.y + text_height * 1.5;
@@ -5624,13 +5624,13 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
}
Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instantiated_scene) { // error on instancing
+ if (!instantiated_scene) { // Error on instantiation.
return false;
}
Node *edited_scene = EditorNode::get_singleton()->get_edited_scene();
- if (!edited_scene->get_scene_file_path().is_empty()) { // cyclical instancing
+ if (!edited_scene->get_scene_file_path().is_empty()) { // Cyclic instantiation.
if (_cyclical_dependency_exists(edited_scene->get_scene_file_path(), instantiated_scene)) {
memdelete(instantiated_scene);
return false;
@@ -5647,7 +5647,7 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- undo_redo->add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), path, new_name);
+ undo_redo->add_do_method(ed, "live_debug_instantiate_node", edited_scene->get_path_to(parent), path, new_name);
undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)) + "/" + new_name));
CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instantiated_scene);
@@ -5720,7 +5720,7 @@ void CanvasItemEditorViewport::_perform_drop_data() {
files_str += error_files[i].get_file().get_basename() + ",";
}
files_str = files_str.substr(0, files_str.length() - 1);
- accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data()));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), files_str.get_data()));
accept->popup_centered();
}
}
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index ba193a67b8..cc98aa8c51 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -42,8 +42,11 @@
#include "scene/gui/texture_rect.h"
#include "scene/main/canvas_item.h"
+class AcceptDialog;
+class ConfirmationDialog;
class EditorData;
class CanvasItemEditorViewport;
+class MenuButton;
class ViewPanner;
class CanvasItemEditorSelectedItem : public Object {
@@ -336,12 +339,12 @@ private:
Point2 drag_start_origin;
DragType drag_type = DRAG_NONE;
- Point2 drag_from = Vector2();
- Point2 drag_to = Vector2();
+ Point2 drag_from;
+ Point2 drag_to;
Point2 drag_rotation_center;
List<CanvasItem *> drag_selection;
int dragged_guide_index = -1;
- Point2 dragged_guide_pos = Point2();
+ Point2 dragged_guide_pos;
bool is_hovering_h_guide = false;
bool is_hovering_v_guide = false;
diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp
index 1791f7b420..00b7845cee 100644
--- a/editor/plugins/control_editor_plugin.cpp
+++ b/editor/plugins/control_editor_plugin.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/separator.h"
// Inspector controls.
@@ -815,7 +816,7 @@ Vector2 ControlEditorToolbar::_position_to_anchor(const Control *p_control, Vect
Rect2 parent_rect = p_control->get_parent_anchorable_rect();
- Vector2 output = Vector2();
+ Vector2 output;
if (p_control->is_layout_rtl()) {
output.x = (parent_rect.size.x == 0) ? 0.0 : (parent_rect.size.x - p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
} else {
diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h
index d78773a509..14886e77a4 100644
--- a/editor/plugins/control_editor_plugin.h
+++ b/editor/plugins/control_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef CONTROL_EDITOR_PLUGIN_H
#define CONTROL_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@@ -45,6 +46,7 @@
#include "scene/gui/texture_rect.h"
class EditorUndoRedoManager;
+class GridContainer;
// Inspector controls.
class ControlPositioningWarning : public MarginContainer {
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.h b/editor/plugins/cpu_particles_2d_editor_plugin.h
index 06ca208463..694162588b 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.h
@@ -36,10 +36,13 @@
#include "scene/2d/cpu_particles_2d.h"
#include "scene/gui/box_container.h"
-class EditorPlugin;
+class CheckBox;
+class ConfirmationDialog;
class SpinBox;
class EditorFileDialog;
class EditorUndoRedoManager;
+class MenuButton;
+class OptionButton;
class CPUParticles2DEditorPlugin : public EditorPlugin {
GDCLASS(CPUParticles2DEditorPlugin, EditorPlugin);
diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h
index 5cf3b16a06..5503ce96ff 100644
--- a/editor/plugins/curve_editor_plugin.h
+++ b/editor/plugins/curve_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef CURVE_EDITOR_PLUGIN_H
#define CURVE_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "editor/editor_resource_preview.h"
#include "scene/resources/curve.h"
diff --git a/editor/plugins/editor_debugger_plugin.cpp b/editor/plugins/editor_debugger_plugin.cpp
index 4ce3d7cfd5..5dd3038c0e 100644
--- a/editor/plugins/editor_debugger_plugin.cpp
+++ b/editor/plugins/editor_debugger_plugin.cpp
@@ -32,7 +32,7 @@
#include "editor/debugger/script_editor_debugger.h"
-void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) {
+void EditorDebuggerSession::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) {
if (p_really_did) {
emit_signal(SNAME("breaked"), p_can_debug);
} else {
@@ -40,22 +40,22 @@ void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String
}
}
-void EditorDebuggerPlugin::_started() {
+void EditorDebuggerSession::_started() {
emit_signal(SNAME("started"));
}
-void EditorDebuggerPlugin::_stopped() {
+void EditorDebuggerSession::_stopped() {
emit_signal(SNAME("stopped"));
}
-void EditorDebuggerPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerPlugin::send_message);
- ClassDB::bind_method(D_METHOD("register_message_capture", "name", "callable"), &EditorDebuggerPlugin::register_message_capture);
- ClassDB::bind_method(D_METHOD("unregister_message_capture", "name"), &EditorDebuggerPlugin::unregister_message_capture);
- ClassDB::bind_method(D_METHOD("has_capture", "name"), &EditorDebuggerPlugin::has_capture);
- ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerPlugin::is_breaked);
- ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerPlugin::is_debuggable);
- ClassDB::bind_method(D_METHOD("is_session_active"), &EditorDebuggerPlugin::is_session_active);
+void EditorDebuggerSession::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerSession::send_message, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("toggle_profiler", "profiler", "enable", "data"), &EditorDebuggerSession::toggle_profiler, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerSession::is_breaked);
+ ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerSession::is_debuggable);
+ ClassDB::bind_method(D_METHOD("is_active"), &EditorDebuggerSession::is_active);
+ ClassDB::bind_method(D_METHOD("add_session_tab", "control"), &EditorDebuggerSession::add_session_tab);
+ ClassDB::bind_method(D_METHOD("remove_session_tab", "control"), &EditorDebuggerSession::remove_session_tab);
ADD_SIGNAL(MethodInfo("started"));
ADD_SIGNAL(MethodInfo("stopped"));
@@ -63,62 +63,131 @@ void EditorDebuggerPlugin::_bind_methods() {
ADD_SIGNAL(MethodInfo("continued"));
}
-void EditorDebuggerPlugin::attach_debugger(ScriptEditorDebugger *p_debugger) {
- debugger = p_debugger;
- if (debugger) {
- debugger->connect("started", callable_mp(this, &EditorDebuggerPlugin::_started));
- debugger->connect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped));
- debugger->connect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked));
- }
+void EditorDebuggerSession::add_session_tab(Control *p_tab) {
+ ERR_FAIL_COND(!p_tab || !debugger);
+ debugger->add_debugger_tab(p_tab);
+ tabs.insert(p_tab);
}
-void EditorDebuggerPlugin::detach_debugger(bool p_call_debugger) {
- if (debugger) {
- debugger->disconnect("started", callable_mp(this, &EditorDebuggerPlugin::_started));
- debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped));
- debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked));
- if (p_call_debugger && get_script_instance()) {
- debugger->remove_debugger_plugin(get_script_instance()->get_script());
- }
- debugger = nullptr;
- }
+void EditorDebuggerSession::remove_session_tab(Control *p_tab) {
+ ERR_FAIL_COND(!p_tab || !debugger);
+ debugger->remove_debugger_tab(p_tab);
+ tabs.erase(p_tab);
}
-void EditorDebuggerPlugin::send_message(const String &p_message, const Array &p_args) {
+void EditorDebuggerSession::send_message(const String &p_message, const Array &p_args) {
ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
debugger->send_message(p_message, p_args);
}
-void EditorDebuggerPlugin::register_message_capture(const StringName &p_name, const Callable &p_callable) {
+void EditorDebuggerSession::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) {
ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
- debugger->register_message_capture(p_name, p_callable);
+ debugger->toggle_profiler(p_profiler, p_enable, p_data);
}
-void EditorDebuggerPlugin::unregister_message_capture(const StringName &p_name) {
- ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
- debugger->unregister_message_capture(p_name);
-}
-
-bool EditorDebuggerPlugin::has_capture(const StringName &p_name) {
- ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
- return debugger->has_capture(p_name);
-}
-
-bool EditorDebuggerPlugin::is_breaked() {
+bool EditorDebuggerSession::is_breaked() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_breaked();
}
-bool EditorDebuggerPlugin::is_debuggable() {
+bool EditorDebuggerSession::is_debuggable() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_debuggable();
}
-bool EditorDebuggerPlugin::is_session_active() {
+bool EditorDebuggerSession::is_active() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_session_active();
}
+void EditorDebuggerSession::detach_debugger() {
+ if (!debugger) {
+ return;
+ }
+ debugger->disconnect("started", callable_mp(this, &EditorDebuggerSession::_started));
+ debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
+ debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
+ debugger->disconnect("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away));
+ for (Control *tab : tabs) {
+ debugger->remove_debugger_tab(tab);
+ }
+ tabs.clear();
+ debugger = nullptr;
+}
+
+void EditorDebuggerSession::_debugger_gone_away() {
+ debugger = nullptr;
+ tabs.clear();
+}
+
+EditorDebuggerSession::EditorDebuggerSession(ScriptEditorDebugger *p_debugger) {
+ ERR_FAIL_COND(!p_debugger);
+ debugger = p_debugger;
+ debugger->connect("started", callable_mp(this, &EditorDebuggerSession::_started));
+ debugger->connect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
+ debugger->connect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
+ debugger->connect("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away), CONNECT_ONE_SHOT);
+}
+
+EditorDebuggerSession::~EditorDebuggerSession() {
+ detach_debugger();
+}
+
+/// EditorDebuggerPlugin
+
EditorDebuggerPlugin::~EditorDebuggerPlugin() {
- detach_debugger(true);
+ clear();
+}
+
+void EditorDebuggerPlugin::clear() {
+ for (int i = 0; i < sessions.size(); i++) {
+ sessions[i]->detach_debugger();
+ }
+ sessions.clear();
+}
+
+void EditorDebuggerPlugin::create_session(ScriptEditorDebugger *p_debugger) {
+ sessions.push_back(Ref<EditorDebuggerSession>(memnew(EditorDebuggerSession(p_debugger))));
+ setup_session(sessions.size() - 1);
+}
+
+void EditorDebuggerPlugin::setup_session(int p_idx) {
+ GDVIRTUAL_CALL(_setup_session, p_idx);
+}
+
+Ref<EditorDebuggerSession> EditorDebuggerPlugin::get_session(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx, sessions.size(), nullptr);
+ return sessions[p_idx];
+}
+
+Array EditorDebuggerPlugin::get_sessions() {
+ Array ret;
+ for (int i = 0; i < sessions.size(); i++) {
+ ret.push_back(sessions[i]);
+ }
+ return ret;
+}
+
+bool EditorDebuggerPlugin::has_capture(const String &p_message) const {
+ bool ret = false;
+ if (GDVIRTUAL_CALL(_has_capture, p_message, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+bool EditorDebuggerPlugin::capture(const String &p_message, const Array &p_data, int p_session_id) {
+ bool ret = false;
+ if (GDVIRTUAL_CALL(_capture, p_message, p_data, p_session_id, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void EditorDebuggerPlugin::_bind_methods() {
+ GDVIRTUAL_BIND(_setup_session, "session_id");
+ GDVIRTUAL_BIND(_has_capture, "capture");
+ GDVIRTUAL_BIND(_capture, "message", "data", "session_id");
+ ClassDB::bind_method(D_METHOD("get_session", "id"), &EditorDebuggerPlugin::get_session);
+ ClassDB::bind_method(D_METHOD("get_sessions"), &EditorDebuggerPlugin::get_sessions);
}
diff --git a/editor/plugins/editor_debugger_plugin.h b/editor/plugins/editor_debugger_plugin.h
index b602c36912..46f8f17cc2 100644
--- a/editor/plugins/editor_debugger_plugin.h
+++ b/editor/plugins/editor_debugger_plugin.h
@@ -35,29 +35,62 @@
class ScriptEditorDebugger;
-class EditorDebuggerPlugin : public Control {
- GDCLASS(EditorDebuggerPlugin, Control);
+class EditorDebuggerSession : public RefCounted {
+ GDCLASS(EditorDebuggerSession, RefCounted);
private:
+ HashSet<Control *> tabs;
+
ScriptEditorDebugger *debugger = nullptr;
void _breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump);
void _started();
void _stopped();
+ void _debugger_gone_away();
protected:
static void _bind_methods();
public:
- void attach_debugger(ScriptEditorDebugger *p_debugger);
- void detach_debugger(bool p_call_debugger);
- void send_message(const String &p_message, const Array &p_args);
- void register_message_capture(const StringName &p_name, const Callable &p_callable);
- void unregister_message_capture(const StringName &p_name);
- bool has_capture(const StringName &p_name);
+ void detach_debugger();
+
+ void add_session_tab(Control *p_tab);
+ void remove_session_tab(Control *p_tab);
+ void send_message(const String &p_message, const Array &p_args = Array());
+ void toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data = Array());
bool is_breaked();
bool is_debuggable();
- bool is_session_active();
+ bool is_active();
+
+ EditorDebuggerSession(ScriptEditorDebugger *p_debugger);
+ ~EditorDebuggerSession();
+};
+
+class EditorDebuggerPlugin : public RefCounted {
+ GDCLASS(EditorDebuggerPlugin, RefCounted);
+
+private:
+ List<Ref<EditorDebuggerSession>> sessions;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void create_session(ScriptEditorDebugger *p_debugger);
+ void clear();
+
+ virtual void setup_session(int p_idx);
+ virtual bool capture(const String &p_message, const Array &p_data, int p_session);
+ virtual bool has_capture(const String &p_capture) const;
+
+ Ref<EditorDebuggerSession> get_session(int p_session_id);
+ Array get_sessions();
+
+ GDVIRTUAL3R(bool, _capture, const String &, const Array &, int);
+ GDVIRTUAL1RC(bool, _has_capture, const String &);
+ GDVIRTUAL1(_setup_session, int);
+
+ EditorDebuggerPlugin() {}
~EditorDebuggerPlugin();
};
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h
index 0229b57c10..0a0ea21c1f 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.h
@@ -37,8 +37,12 @@
#include "scene/gui/box_container.h"
#include "scene/gui/spin_box.h"
+class CheckBox;
+class ConfirmationDialog;
class EditorFileDialog;
class EditorUndoRedoManager;
+class MenuButton;
+class OptionButton;
class GPUParticles2DEditorPlugin : public EditorPlugin {
GDCLASS(GPUParticles2DEditorPlugin, EditorPlugin);
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h
index 17bdfa6e3f..e5b264cfe4 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.h
@@ -35,6 +35,10 @@
#include "scene/3d/gpu_particles_3d.h"
#include "scene/gui/spin_box.h"
+class ConfirmationDialog;
+class HBoxContainer;
+class MenuButton;
+class OptionButton;
class SceneTreeDialog;
class GPUParticles3DEditorBase : public Control {
diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
index 684279039a..2c1f49df29 100644
--- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
+++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
@@ -37,6 +37,7 @@
struct EditorProgress;
class EditorFileDialog;
+class HBoxContainer;
class GPUParticlesCollisionSDF3DEditorPlugin : public EditorPlugin {
GDCLASS(GPUParticlesCollisionSDF3DEditorPlugin, EditorPlugin);
diff --git a/editor/plugins/gradient_editor.cpp b/editor/plugins/gradient_editor.cpp
index 7039ada10a..f6d5adcd68 100644
--- a/editor/plugins/gradient_editor.cpp
+++ b/editor/plugins/gradient_editor.cpp
@@ -203,6 +203,7 @@ void GradientEditor::gui_input(const Ref<InputEvent> &p_event) {
grabbed = _get_point_from_pos(mb->get_position().x);
_show_color_picker();
accept_event();
+ return;
}
// Delete point on right click.
diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h
index ab191d83e2..f3859e74d3 100644
--- a/editor/plugins/gradient_editor_plugin.h
+++ b/editor/plugins/gradient_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef GRADIENT_EDITOR_PLUGIN_H
#define GRADIENT_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "gradient_editor.h"
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.h b/editor/plugins/gradient_texture_2d_editor_plugin.h
index 9faf33152a..0737300498 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.h
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H
#define GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "editor/editor_spin_slider.h"
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index fe7713f175..759c1c967d 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -72,15 +72,15 @@ void MaterialEditor::_update_theme_item_cache() {
void MaterialEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- light_1_switch->set_normal_texture(theme_cache.light_1_on);
- light_1_switch->set_pressed_texture(theme_cache.light_1_off);
- light_2_switch->set_normal_texture(theme_cache.light_2_on);
- light_2_switch->set_pressed_texture(theme_cache.light_2_off);
-
- sphere_switch->set_normal_texture(theme_cache.sphere_off);
- sphere_switch->set_pressed_texture(theme_cache.sphere_on);
- box_switch->set_normal_texture(theme_cache.box_off);
- box_switch->set_pressed_texture(theme_cache.box_on);
+ light_1_switch->set_texture_normal(theme_cache.light_1_on);
+ light_1_switch->set_texture_pressed(theme_cache.light_1_off);
+ light_2_switch->set_texture_normal(theme_cache.light_2_on);
+ light_2_switch->set_texture_pressed(theme_cache.light_2_off);
+
+ sphere_switch->set_texture_normal(theme_cache.sphere_off);
+ sphere_switch->set_texture_pressed(theme_cache.sphere_on);
+ box_switch->set_texture_normal(theme_cache.box_off);
+ box_switch->set_texture_pressed(theme_cache.box_on);
} break;
case NOTIFICATION_DRAW: {
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index 8e64434d8b..076fd5e537 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef MATERIAL_EDITOR_PLUGIN_H
#define MATERIAL_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "scene/3d/camera_3d.h"
@@ -45,7 +46,7 @@ class SubViewportContainer;
class MaterialEditor : public Control {
GDCLASS(MaterialEditor, Control);
- Vector2 rot = Vector2();
+ Vector2 rot;
HBoxContainer *layout_2d = nullptr;
ColorRect *rect_instance = nullptr;
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index be26baaea5..57dc92a9ee 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -61,10 +61,10 @@ void MeshEditor::_update_theme_item_cache() {
void MeshEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- light_1_switch->set_normal_texture(theme_cache.light_1_on);
- light_1_switch->set_pressed_texture(theme_cache.light_1_off);
- light_2_switch->set_normal_texture(theme_cache.light_2_on);
- light_2_switch->set_pressed_texture(theme_cache.light_2_off);
+ light_1_switch->set_texture_normal(theme_cache.light_1_on);
+ light_1_switch->set_texture_pressed(theme_cache.light_1_off);
+ light_2_switch->set_texture_normal(theme_cache.light_2_on);
+ light_2_switch->set_texture_pressed(theme_cache.light_2_off);
} break;
}
}
diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h
index 6394cb1171..b8d6562c5c 100644
--- a/editor/plugins/mesh_editor_plugin.h
+++ b/editor/plugins/mesh_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef MESH_EDITOR_PLUGIN_H
#define MESH_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/light_3d.h"
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 88800227d1..81ba263be0 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -35,6 +35,10 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class ConfirmationDialog;
+class MenuButton;
+
class MeshInstance3DEditor : public Control {
GDCLASS(MeshInstance3DEditor, Control);
diff --git a/editor/plugins/multimesh_editor_plugin.h b/editor/plugins/multimesh_editor_plugin.h
index 5773989d0d..76f86cfa5d 100644
--- a/editor/plugins/multimesh_editor_plugin.h
+++ b/editor/plugins/multimesh_editor_plugin.h
@@ -36,6 +36,10 @@
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class ConfirmationDialog;
+class MenuButton;
+class OptionButton;
class SceneTreeDialog;
class MultiMeshEditor : public Control {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 7febb50f5c..ca6d65bd57 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -1329,7 +1329,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
}
}
- String suffix = String();
+ String suffix;
if (locked == 1) {
suffix = " (" + TTR("Locked") + ")";
} else if (locked == 2) {
@@ -3492,7 +3492,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
}
for (int i = 0; i < 3; i++) {
- Transform3D axis_angle = Transform3D();
+ Transform3D axis_angle;
if (xform.basis.get_column(i).normalized().dot(xform.basis.get_column((i + 1) % 3).normalized()) < 1.0) {
axis_angle = axis_angle.looking_at(xform.basis.get_column(i).normalized(), xform.basis.get_column((i + 1) % 3).normalized());
}
@@ -4039,7 +4039,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
return false;
}
- if (!EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path().is_empty()) { // cyclical instancing
+ if (!EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path().is_empty()) { // Cyclic instantiation.
if (_cyclical_dependency_exists(EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path(), instantiated_scene)) {
memdelete(instantiated_scene);
return false;
@@ -4058,7 +4058,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- undo_redo->add_do_method(ed, "live_debug_instance_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name);
+ undo_redo->add_do_method(ed, "live_debug_instantiate_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name);
undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
Node3D *node3d = Object::cast_to<Node3D>(instantiated_scene);
@@ -4129,7 +4129,7 @@ void Node3DEditorViewport::_perform_drop_data() {
files_str += error_files[i].get_file().get_basename() + ",";
}
files_str = files_str.substr(0, files_str.length() - 1);
- accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data()));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), files_str.get_data()));
accept->popup_centered();
}
}
@@ -6803,8 +6803,8 @@ void Node3DEditor::_init_grid() {
// Don't draw lines over the origin if it's enabled.
if (!(origin_enabled && Math::is_zero_approx(position_a))) {
- Vector3 line_bgn = Vector3();
- Vector3 line_end = Vector3();
+ Vector3 line_bgn;
+ Vector3 line_end;
line_bgn[a] = position_a;
line_end[a] = position_a;
line_bgn[b] = bgn_b;
@@ -6819,8 +6819,8 @@ void Node3DEditor::_init_grid() {
}
if (!(origin_enabled && Math::is_zero_approx(position_b))) {
- Vector3 line_bgn = Vector3();
- Vector3 line_end = Vector3();
+ Vector3 line_bgn;
+ Vector3 line_end;
line_bgn[b] = position_b;
line_end[b] = position_b;
line_bgn[a] = bgn_a;
@@ -6988,8 +6988,8 @@ void Node3DEditor::_snap_selected_nodes_to_floor() {
for (Node *E : selection) {
Node3D *sp = Object::cast_to<Node3D>(E);
if (sp) {
- Vector3 from = Vector3();
- Vector3 position_offset = Vector3();
+ Vector3 from;
+ Vector3 position_offset;
// Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin
HashSet<VisualInstance3D *> vi = _get_child_nodes<VisualInstance3D>(sp);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 5ea1bf6dc1..a8d3bfb70c 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -39,6 +39,7 @@
#include "scene/3d/light_3d.h"
#include "scene/3d/visual_instance_3d.h"
#include "scene/3d/world_environment.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/spin_box.h"
@@ -47,9 +48,14 @@
#include "scene/resources/fog_material.h"
#include "scene/resources/sky_material.h"
+class AcceptDialog;
+class CheckBox;
+class ConfirmationDialog;
class EditorData;
+class MenuButton;
class Node3DEditor;
class Node3DEditorViewport;
+class OptionButton;
class SubViewportContainer;
class DirectionalLight3D;
class WorldEnvironment;
@@ -569,7 +575,7 @@ private:
bool grid_enabled = false;
bool grid_init_draw = false;
Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
- Vector3 grid_camera_last_update_position = Vector3();
+ Vector3 grid_camera_last_update_position;
Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3];
Ref<StandardMaterial3D> gizmo_color[3];
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
index 13eca79010..d2015b2bb8 100644
--- a/editor/plugins/path_2d_editor_plugin.h
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -33,10 +33,12 @@
#include "editor/editor_plugin.h"
#include "scene/2d/path_2d.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/separator.h"
class CanvasItemEditor;
class EditorUndoRedoManager;
+class MenuButton;
class Path2DEditor : public HBoxContainer {
GDCLASS(Path2DEditor, HBoxContainer);
diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h
index 11a640b79f..a2816c89ae 100644
--- a/editor/plugins/path_3d_editor_plugin.h
+++ b/editor/plugins/path_3d_editor_plugin.h
@@ -37,6 +37,8 @@
#include "scene/3d/path_3d.h"
#include "scene/gui/separator.h"
+class MenuButton;
+
class Path3DGizmo : public EditorNode3DGizmo {
GDCLASS(Path3DGizmo, EditorNode3DGizmo);
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index d878d3f9af..6021401e4f 100644
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -33,11 +33,17 @@
#include "editor/plugins/abstract_polygon_2d_editor.h"
+class AcceptDialog;
+class ButtonGroup;
+class HScrollBar;
class HSlider;
+class MenuButton;
class Panel;
class ScrollContainer;
class SpinBox;
+class TextureRect;
class ViewPanner;
+class VScrollBar;
class Polygon2DEditor : public AbstractPolygon2DEditor {
GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor);
diff --git a/editor/plugins/polygon_3d_editor_plugin.h b/editor/plugins/polygon_3d_editor_plugin.h
index 918072b429..fe8e2ce36d 100644
--- a/editor/plugins/polygon_3d_editor_plugin.h
+++ b/editor/plugins/polygon_3d_editor_plugin.h
@@ -34,10 +34,12 @@
#include "editor/editor_plugin.h"
#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/mesh_instance_3d.h"
+#include "scene/gui/box_container.h"
#include "scene/resources/immediate_mesh.h"
class CanvasItemEditor;
class EditorUndoRedoManager;
+class MenuButton;
class Polygon3DEditor : public HBoxContainer {
GDCLASS(Polygon3DEditor, HBoxContainer);
diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h
index ef80283dae..59641e2561 100644
--- a/editor/plugins/resource_preloader_editor_plugin.h
+++ b/editor/plugins/resource_preloader_editor_plugin.h
@@ -33,6 +33,7 @@
#include "editor/editor_plugin.h"
#include "scene/gui/dialogs.h"
+#include "scene/gui/panel_container.h"
#include "scene/gui/tree.h"
#include "scene/main/resource_preloader.h"
diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp
index de30c4100d..596b2c0edb 100644
--- a/editor/plugins/root_motion_editor_plugin.cpp
+++ b/editor/plugins/root_motion_editor_plugin.cpp
@@ -30,6 +30,8 @@
#include "root_motion_editor_plugin.h"
#include "editor/editor_node.h"
+#include "scene/animation/animation_player.h"
+#include "scene/animation/animation_tree.h"
#include "scene/main/window.h"
void EditorPropertyRootMotion::_confirmed() {
@@ -45,8 +47,6 @@ void EditorPropertyRootMotion::_confirmed() {
}
void EditorPropertyRootMotion::_node_assign() {
- NodePath current = get_edited_object()->get(get_edited_property());
-
AnimationTree *atree = Object::cast_to<AnimationTree>(get_edited_object());
if (!atree->has_node(atree->get_animation_player())) {
EditorNode::get_singleton()->show_warning(TTR("AnimationTree has no path set to an AnimationPlayer"));
@@ -73,7 +73,10 @@ void EditorPropertyRootMotion::_node_assign() {
for (const StringName &E : animations) {
Ref<Animation> anim = player->get_animation(E);
for (int i = 0; i < anim->get_track_count(); i++) {
- paths.insert(anim->track_get_path(i));
+ String pathname = anim->track_get_path(i).get_concatenated_names();
+ if (!paths.has(pathname)) {
+ paths.insert(pathname);
+ }
}
}
}
@@ -122,66 +125,33 @@ void EditorPropertyRootMotion::_node_assign() {
continue; //no node, can't edit
}
- if (path.get_subname_count()) {
- String concat = path.get_concatenated_subnames();
-
- Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node);
- if (skeleton && skeleton->find_bone(concat) != -1) {
- //path in skeleton
- const String &bone = concat;
- int idx = skeleton->find_bone(bone);
- List<String> bone_path;
- while (idx != -1) {
- bone_path.push_front(skeleton->get_bone_name(idx));
- idx = skeleton->get_bone_parent(idx);
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node);
+ if (skeleton) {
+ HashMap<int, TreeItem *> items;
+ items.insert(-1, ti);
+ Ref<Texture> bone_icon = get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons"));
+ Vector<int> bones_to_process = skeleton->get_parentless_bones();
+ while (bones_to_process.size() > 0) {
+ int current_bone_idx = bones_to_process[0];
+ bones_to_process.erase(current_bone_idx);
+
+ Vector<int> current_bone_child_bones = skeleton->get_bone_children(current_bone_idx);
+ int child_bone_size = current_bone_child_bones.size();
+ for (int i = 0; i < child_bone_size; i++) {
+ bones_to_process.push_back(current_bone_child_bones[i]);
}
- accum += ":";
- for (List<String>::Element *F = bone_path.front(); F; F = F->next()) {
- if (F != bone_path.front()) {
- accum += "/";
- }
-
- accum += F->get();
- if (!parenthood.has(accum)) {
- ti = filters->create_item(ti);
- parenthood[accum] = ti;
- ti->set_text(0, F->get());
- ti->set_selectable(0, true);
- ti->set_editable(0, false);
- ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
- ti->set_metadata(0, accum);
- } else {
- ti = parenthood[accum];
- }
- }
+ const int parent_idx = skeleton->get_bone_parent(current_bone_idx);
+ TreeItem *parent_item = items.find(parent_idx)->value;
- ti->set_selectable(0, true);
- ti->set_text(0, concat);
- ti->set_icon(0, get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
- ti->set_metadata(0, path);
- if (path == current) {
- ti->select(0);
- }
+ TreeItem *joint_item = filters->create_item(parent_item);
+ items.insert(current_bone_idx, joint_item);
- } else {
- //just a property
- ti = filters->create_item(ti);
- ti->set_text(0, concat);
- ti->set_selectable(0, true);
- ti->set_metadata(0, path);
- if (path == current) {
- ti->select(0);
- }
- }
- } else {
- if (ti) {
- //just a node, likely call or animation track
- ti->set_selectable(0, true);
- ti->set_metadata(0, path);
- if (path == current) {
- ti->select(0);
- }
+ joint_item->set_text(0, skeleton->get_bone_name(current_bone_idx));
+ joint_item->set_icon(0, bone_icon);
+ joint_item->set_selectable(0, true);
+ joint_item->set_metadata(0, accum + ":" + skeleton->get_bone_name(current_bone_idx));
+ joint_item->set_collapsed(true);
}
}
}
@@ -197,7 +167,6 @@ void EditorPropertyRootMotion::_node_clear() {
void EditorPropertyRootMotion::update_property() {
NodePath p = get_edited_object()->get(get_edited_property());
-
assign->set_tooltip_text(p);
if (p == NodePath()) {
assign->set_icon(Ref<Texture2D>());
@@ -206,26 +175,8 @@ void EditorPropertyRootMotion::update_property() {
return;
}
- Node *base_node = nullptr;
- if (base_hint != NodePath()) {
- if (get_tree()->get_root()->has_node(base_hint)) {
- base_node = get_tree()->get_root()->get_node(base_hint);
- }
- } else {
- base_node = Object::cast_to<Node>(get_edited_object());
- }
-
- if (!base_node || !base_node->has_node(p)) {
- assign->set_icon(Ref<Texture2D>());
- assign->set_text(p);
- return;
- }
-
- Node *target_node = base_node->get_node(p);
- ERR_FAIL_COND(!target_node);
-
- assign->set_text(target_node->get_name());
- assign->set_icon(EditorNode::get_singleton()->get_object_icon(target_node, "Node"));
+ assign->set_icon(Ref<Texture2D>());
+ assign->set_text(p);
}
void EditorPropertyRootMotion::setup(const NodePath &p_base_hint) {
@@ -280,9 +231,6 @@ bool EditorInspectorRootMotionPlugin::can_handle(Object *p_object) {
bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
if (p_path == "root_motion_track" && p_object->is_class("AnimationTree") && p_type == Variant::NODE_PATH) {
EditorPropertyRootMotion *editor = memnew(EditorPropertyRootMotion);
- if (p_hint == PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && !p_hint_text.is_empty()) {
- editor->setup(p_hint_text);
- }
add_property_editor(p_path, editor);
return true;
}
diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h
index 5b8c1d77b3..7134b48c36 100644
--- a/editor/plugins/root_motion_editor_plugin.h
+++ b/editor/plugins/root_motion_editor_plugin.h
@@ -32,9 +32,8 @@
#define ROOT_MOTION_EDITOR_PLUGIN_H
#include "editor/editor_inspector.h"
-#include "editor/editor_spin_slider.h"
-#include "editor/property_selector.h"
-#include "scene/animation/animation_tree.h"
+
+class Tree;
class EditorPropertyRootMotion : public EditorProperty {
GDCLASS(EditorPropertyRootMotion, EditorProperty);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index a45ce4cc22..3f84ded0a2 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -48,6 +48,7 @@
#include "scene/resources/text_file.h"
class EditorFileDialog;
+class TextureRect;
class EditorSyntaxHighlighter : public SyntaxHighlighter {
GDCLASS(EditorSyntaxHighlighter, SyntaxHighlighter)
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 0d12d07aa7..4e66dc3d7e 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1860,7 +1860,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (valid) {
color_args = line.substr(begin, end - begin);
String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
- Vector<float> color = stripped.split_floats(",");
+ PackedFloat64Array color = stripped.split_floats(",");
if (color.size() > 2) {
float alpha = color.size() > 3 ? color[3] : 1.0f;
color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 7638778af7..1ae419053e 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -35,6 +35,7 @@
class HSplitContainer;
class ItemList;
+class MenuButton;
class ShaderCreateDialog;
class TabContainer;
class TextShaderEditor;
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index 4874944d33..dd644cb369 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -286,6 +286,7 @@ ShaderFileEditor::ShaderFileEditor() {
error_text = memnew(RichTextLabel);
error_text->set_v_size_flags(SIZE_EXPAND_FILL);
+ error_text->set_selection_enabled(true);
main_vb->add_child(error_text);
}
diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h
index 295725b751..6794f72955 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.h
+++ b/editor/plugins/skeleton_2d_editor_plugin.h
@@ -35,6 +35,9 @@
#include "scene/2d/skeleton_2d.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class MenuButton;
+
class Skeleton2DEditor : public Control {
GDCLASS(Skeleton2DEditor, Control);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 7922a768ec..fd6c9b761e 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -714,12 +714,12 @@ void Skeleton3DEditor::create_editors() {
// Skeleton options.
PopupMenu *p = skeleton_options->get_popup();
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_all_poses", TTR("Reset all bone Poses")), SKELETON_OPTION_RESET_ALL_POSES);
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_selected_poses", TTR("Reset selected Poses")), SKELETON_OPTION_RESET_SELECTED_POSES);
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply all poses to rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
- p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply selected poses to rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
- p->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
- p->add_item(TTR("Export skeleton profile"), SKELETON_OPTION_EXPORT_SKELETON_PROFILE);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_all_poses", TTR("Reset All Bone Poses")), SKELETON_OPTION_RESET_ALL_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/reset_selected_poses", TTR("Reset Selected Poses")), SKELETON_OPTION_RESET_SELECTED_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply All Poses to Rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply Selected Poses to Rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
+ p->add_item(TTR("Create Physical Skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
+ p->add_item(TTR("Export Skeleton Profile"), SKELETON_OPTION_EXPORT_SKELETON_PROFILE);
p->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_skeleton_option));
set_bone_options_enabled(false);
@@ -1288,7 +1288,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi
ERR_FAIL_COND(!skeleton);
// Prepare for global to local.
- Transform3D original_to_local = Transform3D();
+ Transform3D original_to_local;
int parent_idx = skeleton->get_bone_parent(p_id);
if (parent_idx >= 0) {
original_to_local = original_to_local * skeleton->get_bone_global_pose(parent_idx);
@@ -1296,7 +1296,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi
Basis to_local = original_to_local.get_basis().inverse();
// Prepare transform.
- Transform3D t = Transform3D();
+ Transform3D t;
// Basis.
t.basis = to_local * p_transform.get_basis();
diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h
index b87f108bd2..ae1083ed41 100644
--- a/editor/plugins/sprite_2d_editor_plugin.h
+++ b/editor/plugins/sprite_2d_editor_plugin.h
@@ -35,6 +35,10 @@
#include "scene/2d/sprite_2d.h"
#include "scene/gui/spin_box.h"
+class AcceptDialog;
+class ConfirmationDialog;
+class MenuButton;
+
class Sprite2DEditor : public Control {
GDCLASS(Sprite2DEditor, Control);
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index d3ab5b6f77..cf8cc71db7 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -1525,7 +1525,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
_zoom_reset();
// Ensure the anim search box is wide enough by default.
- // Not by setting its minimum size so it can still be shrinked if desired.
+ // Not by setting its minimum size so it can still be shrunk if desired.
set_split_offset(56 * EDSCALE);
}
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index fffcce6d9a..16a6a48df9 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -80,9 +80,9 @@ void StyleBoxPreview::_notification(int p_what) {
// See https://github.com/godotengine/godot/issues/50743.
break;
}
- grid_preview->set_normal_texture(get_theme_icon(SNAME("StyleBoxGridInvisible"), SNAME("EditorIcons")));
- grid_preview->set_pressed_texture(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
- grid_preview->set_hover_texture(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
+ grid_preview->set_texture_normal(get_theme_icon(SNAME("StyleBoxGridInvisible"), SNAME("EditorIcons")));
+ grid_preview->set_texture_pressed(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
+ grid_preview->set_texture_hover(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons")));
checkerboard->set_texture(get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")));
} break;
}
diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h
index 7795c83c8a..6790f6f2d5 100644
--- a/editor/plugins/texture_3d_editor_plugin.h
+++ b/editor/plugins/texture_3d_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef TEXTURE_3D_EDITOR_PLUGIN_H
#define TEXTURE_3D_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/gui/spin_box.h"
#include "scene/resources/shader.h"
diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h
index 9beada556c..d7312bfcb4 100644
--- a/editor/plugins/texture_editor_plugin.h
+++ b/editor/plugins/texture_editor_plugin.h
@@ -31,9 +31,13 @@
#ifndef TEXTURE_EDITOR_PLUGIN_H
#define TEXTURE_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
+#include "scene/gui/margin_container.h"
#include "scene/resources/texture.h"
+class TextureRect;
+
class TexturePreview : public MarginContainer {
GDCLASS(TexturePreview, MarginContainer);
diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h
index f4dbc104c8..16a2f65386 100644
--- a/editor/plugins/texture_layered_editor_plugin.h
+++ b/editor/plugins/texture_layered_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef TEXTURE_LAYERED_EDITOR_PLUGIN_H
#define TEXTURE_LAYERED_EDITOR_PLUGIN_H
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/gui/spin_box.h"
#include "scene/resources/shader.h"
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 7eda4f469f..48cbb6b70e 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -32,6 +32,7 @@
#define TEXTURE_REGION_EDITOR_PLUGIN_H
#include "canvas_item_editor_plugin.h"
+#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
#include "scene/2d/sprite_2d.h"
#include "scene/3d/sprite_3d.h"
@@ -41,6 +42,7 @@
class ViewPanner;
class EditorUndoRedoManager;
+class OptionButton;
class TextureRegionEditor : public AcceptDialog {
GDCLASS(TextureRegionEditor, AcceptDialog);
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 9f89a047cb..b54aa5de6c 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -45,6 +45,8 @@
#include "scene/resources/theme.h"
class EditorFileDialog;
+class PanelContainer;
+class TabContainer;
class ThemeItemImportTree : public VBoxContainer {
GDCLASS(ThemeItemImportTree, VBoxContainer);
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index a7d90856ac..42eceb82ab 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -1138,6 +1138,7 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
void TileDataDefaultEditor::setup_property_editor(Variant::Type p_type, String p_property, String p_label, Variant p_default_value) {
ERR_FAIL_COND_MSG(!property.is_empty(), "Cannot setup TileDataDefaultEditor twice");
property = p_property;
+ property_type = p_type;
// Update everything.
if (property_editor) {
@@ -1182,6 +1183,10 @@ void TileDataDefaultEditor::_notification(int p_what) {
}
}
+Variant::Type TileDataDefaultEditor::get_property_type() {
+ return property_type;
+}
+
TileDataDefaultEditor::TileDataDefaultEditor() {
undo_redo = EditorNode::get_undo_redo();
@@ -2476,9 +2481,6 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi
if (terrain_set == -1 || !tile_data || tile_data->get_terrain_set() != terrain_set) {
// Paint terrain sets.
- if (mb->get_button_index() == MouseButton::RIGHT) {
- terrain_set = -1;
- }
drag_type = DRAG_TYPE_PAINT_TERRAIN_SET;
drag_modified.clear();
drag_painted_value = int(dummy_object->get("terrain_set"));
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index c1560138b2..0a947fce8b 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -220,6 +220,7 @@ protected:
StringName type;
String property;
+ Variant::Type property_type;
void _notification(int p_what);
virtual Variant _get_painted_value();
@@ -237,6 +238,7 @@ public:
virtual void draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected = false) override;
void setup_property_editor(Variant::Type p_type, String p_property, String p_label = "", Variant p_default_value = Variant());
+ Variant::Type get_property_type();
TileDataDefaultEditor();
~TileDataDefaultEditor();
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 57416ff55f..93f9df4d6e 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -2267,6 +2267,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
patterns_help_label = memnew(Label);
patterns_help_label->set_text(TTR("Drag and drop or paste a TileMap selection here to store a pattern."));
+ patterns_help_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
patterns_help_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER);
patterns_item_list->add_child(patterns_help_label);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index ab54a093f2..8e69abd7ff 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -737,18 +737,29 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
// --- Custom Data ---
ADD_TILE_DATA_EDITOR_GROUP("Custom Data");
for (int i = 0; i < tile_set->get_custom_data_layers_count(); i++) {
- if (tile_set->get_custom_data_layer_name(i).is_empty()) {
- ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), vformat("custom_data_%d", i));
+ String editor_name = vformat("custom_data_%d", i);
+ String prop_name = tile_set->get_custom_data_layer_name(i);
+ Variant::Type prop_type = tile_set->get_custom_data_layer_type(i);
+
+ if (prop_name.is_empty()) {
+ ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), editor_name);
} else {
- ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_layer_name(i), vformat("custom_data_%d", i));
+ ADD_TILE_DATA_EDITOR(group, prop_name, editor_name);
+ }
+
+ // If the type of the edited property has been changed, delete the
+ // editor and create a new one.
+ if (tile_data_editors.has(editor_name) && ((TileDataDefaultEditor *)tile_data_editors[editor_name])->get_property_type() != prop_type) {
+ tile_data_editors[vformat("custom_data_%d", i)]->queue_free();
+ tile_data_editors.erase(vformat("custom_data_%d", i));
}
- if (!tile_data_editors.has(vformat("custom_data_%d", i))) {
+ if (!tile_data_editors.has(editor_name)) {
TileDataDefaultEditor *tile_data_custom_data_editor = memnew(TileDataDefaultEditor());
tile_data_custom_data_editor->hide();
- tile_data_custom_data_editor->setup_property_editor(tile_set->get_custom_data_layer_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_layer_name(i));
+ tile_data_custom_data_editor->setup_property_editor(prop_type, editor_name, prop_name);
tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::queue_redraw));
tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::queue_redraw));
- tile_data_editors[vformat("custom_data_%d", i)] = tile_data_custom_data_editor;
+ tile_data_editors[editor_name] = tile_data_custom_data_editor;
}
}
for (int i = tile_set->get_custom_data_layers_count(); tile_data_editors.has(vformat("custom_data_%d", i)); i++) {
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 5e25d343b0..eaae9555dc 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -701,7 +701,7 @@ TileSetEditor::TileSetEditor() {
source_sort_button = memnew(MenuButton);
source_sort_button->set_flat(true);
- source_sort_button->set_tooltip_text(TTR("Sort sources"));
+ source_sort_button->set_tooltip_text(TTR("Sort Sources"));
PopupMenu *p = source_sort_button->get_popup();
p->connect("id_pressed", callable_mp(this, &TileSetEditor::_set_source_sort));
@@ -801,6 +801,7 @@ TileSetEditor::TileSetEditor() {
patterns_help_label = memnew(Label);
patterns_help_label->set_text(TTR("Add new patterns in the TileMap editing mode."));
+ patterns_help_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
patterns_help_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER);
patterns_item_list->add_child(patterns_help_label);
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 5b54062632..4239e2c981 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -92,7 +92,7 @@ void TilesEditorPlugin::_thread() {
TypedArray<Vector2i> used_cells = tile_map->get_used_cells(0);
- Rect2 encompassing_rect = Rect2();
+ Rect2 encompassing_rect;
encompassing_rect.set_position(tile_map->map_to_local(used_cells[0]));
for (int i = 0; i < used_cells.size(); i++) {
Vector2i cell = used_cells[i];
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index bdada9ec90..fe0d8179bc 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -71,7 +71,7 @@ private:
// For synchronization.
int atlas_sources_lists_current = 0;
float atlas_view_zoom = 1.0;
- Vector2 atlas_view_scroll = Vector2();
+ Vector2 atlas_view_scroll;
void _tile_map_changed();
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index c8f6a2431d..adc93c0752 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -816,8 +816,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (vsnode->is_output_port_expandable(i)) {
TextureButton *expand = memnew(TextureButton);
expand->set_toggle_mode(true);
- expand->set_normal_texture(editor->get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
- expand->set_pressed_texture(editor->get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")));
+ expand->set_texture_normal(editor->get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
+ expand->set_texture_pressed(editor->get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")));
expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
expand->set_pressed(vsnode->_is_output_port_expanded(i));
expand->connect("pressed", callable_mp(editor, &VisualShaderEditor::_expand_output_port).bind(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
@@ -826,8 +826,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (vsnode->has_output_port_preview(i) && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
- preview->set_normal_texture(editor->get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")));
- preview->set_pressed_texture(editor->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
+ preview->set_texture_normal(editor->get_theme_icon(SNAME("GuiVisibilityHidden"), SNAME("EditorIcons")));
+ preview->set_texture_pressed(editor->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
register_output_port(p_id, j, preview);
@@ -3623,12 +3623,6 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNod
node_filter->select_all();
}
-void VisualShaderEditor::_show_varying_menu() {
- varying_options->set_item_disabled(int(VaryingMenuOptions::REMOVE), visual_shader->get_varyings_count() == 0);
- varying_options->set_position(graph->get_screen_position() + varying_button->get_position() + Size2(0, varying_button->get_size().height));
- varying_options->popup();
-}
-
void VisualShaderEditor::_varying_menu_id_pressed(int p_idx) {
switch (VaryingMenuOptions(p_idx)) {
case VaryingMenuOptions::ADD: {
@@ -4334,7 +4328,7 @@ void VisualShaderEditor::_update_varying_tree() {
}
}
- varying_options->set_item_disabled(int(VaryingMenuOptions::REMOVE), count == 0);
+ varying_button->get_popup()->set_item_disabled(int(VaryingMenuOptions::REMOVE), count == 0);
}
void VisualShaderEditor::_varying_create() {
@@ -4809,17 +4803,15 @@ VisualShaderEditor::VisualShaderEditor() {
graph->get_zoom_hbox()->move_child(add_node, 0);
add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog).bind(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX));
- varying_button = memnew(Button);
- varying_button->set_flat(true);
+ varying_button = memnew(MenuButton);
varying_button->set_text(TTR("Manage Varyings"));
+ varying_button->set_switch_on_hover(true);
graph->get_zoom_hbox()->add_child(varying_button);
- varying_button->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_varying_menu));
- varying_options = memnew(PopupMenu);
- add_child(varying_options);
- varying_options->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
- varying_options->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
- varying_options->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
+ PopupMenu *varying_menu = varying_button->get_popup();
+ varying_menu->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
+ varying_menu->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
+ varying_menu->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
preview_shader = memnew(Button);
preview_shader->set_flat(true);
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index f7e033d753..e673051eb3 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -32,20 +32,13 @@
#define VISUAL_SHADER_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
+#include "editor/editor_properties.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "scene/resources/visual_shader.h"
-class Button;
-class CodeEdit;
-class CodeHighlighter;
class CurveEditor;
class GraphEdit;
class GraphNode;
-class PopupMenu;
-class PopupPanel;
-class RichTextLabel;
-class TextEdit;
-class Tree;
class VisualShaderEditor;
class EditorUndoRedoManager;
@@ -172,8 +165,7 @@ class VisualShaderEditor : public VBoxContainer {
Ref<VisualShader> visual_shader;
GraphEdit *graph = nullptr;
Button *add_node = nullptr;
- Button *varying_button = nullptr;
- PopupMenu *varying_options = nullptr;
+ MenuButton *varying_button = nullptr;
Button *preview_shader = nullptr;
OptionButton *edit_type = nullptr;
@@ -290,7 +282,6 @@ class VisualShaderEditor : public VBoxContainer {
void _tools_menu_option(int p_idx);
void _show_members_dialog(bool at_mouse_pos, VisualShaderNode::PortType p_input_port_type = VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PortType p_output_port_type = VisualShaderNode::PORT_TYPE_MAX);
- void _show_varying_menu();
void _varying_menu_id_pressed(int p_idx);
void _show_add_varying_dialog();
void _show_remove_varying_dialog();
diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h
index 43d6f71e26..feff3b4f35 100644
--- a/editor/plugins/voxel_gi_editor_plugin.h
+++ b/editor/plugins/voxel_gi_editor_plugin.h
@@ -37,6 +37,7 @@
class EditorFileDialog;
struct EditorProgress;
+class HBoxContainer;
class VoxelGIEditorPlugin : public EditorPlugin {
GDCLASS(VoxelGIEditorPlugin, EditorPlugin);
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 78f3b4de0e..3b764a9466 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -366,6 +366,7 @@ static const char *gdscript_function_renames[][2] = {
{ "get_scancode", "get_keycode" }, // InputEventKey
{ "get_scancode_string", "get_keycode_string" }, // OS
{ "get_scancode_with_modifiers", "get_keycode_with_modifiers" }, // InputEventKey
+ { "get_selected_path", "get_current_directory" }, // EditorInterface
{ "get_shift", "is_shift_pressed" }, // InputEventWithModifiers
{ "get_size_override", "get_size_2d_override" }, // SubViewport
{ "get_slide_count", "get_slide_collision_count" }, // CharacterBody2D, CharacterBody3D
@@ -464,6 +465,7 @@ static const char *gdscript_function_renames[][2] = {
{ "post_import", "_post_import" }, // EditorScenePostImport
{ "print_stray_nodes", "print_orphan_nodes" }, // Node
{ "property_list_changed_notify", "notify_property_list_changed" }, // Object
+ { "raise", "move_to_front" }, // CanvasItem
{ "recognize", "_recognize" }, // ResourceFormatLoader
{ "regen_normalmaps", "regen_normal_maps" }, // ArrayMesh
{ "remove", "remove_at" }, // Array, broke Directory
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index b2a2566ad4..02d59921bf 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -1376,7 +1376,7 @@ void ProjectList::create_project_item_control(int p_index) {
favorite_box->set_name("FavoriteBox");
TextureButton *favorite = memnew(TextureButton);
favorite->set_name("FavoriteButton");
- favorite->set_normal_texture(favorite_icon);
+ favorite->set_texture_normal(favorite_icon);
// This makes the project's "hover" style display correctly when hovering the favorite icon.
favorite->set_mouse_filter(MOUSE_FILTER_PASS);
favorite->connect("pressed", callable_mp(this, &ProjectList::_favorite_pressed).bind(hb));
diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp
new file mode 100644
index 0000000000..d3097a694e
--- /dev/null
+++ b/editor/register_editor_types.cpp
@@ -0,0 +1,221 @@
+/*************************************************************************/
+/* register_editor_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "register_editor_types.h"
+
+#include "core/extension/native_extension_manager.h"
+
+#include "editor/animation_track_editor.h"
+#include "editor/debugger/debug_adapter/debug_adapter_server.h"
+#include "editor/editor_command_palette.h"
+#include "editor/editor_feature_profile.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_file_system.h"
+#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
+#include "editor/editor_resource_picker.h"
+#include "editor/editor_resource_preview.h"
+#include "editor/editor_run_script.h"
+#include "editor/editor_translation_parser.h"
+#include "editor/editor_undo_redo_manager.h"
+#include "editor/filesystem_dock.h"
+#include "editor/import/editor_import_plugin.h"
+#include "editor/import/resource_importer_scene.h"
+#include "editor/plugins/animation_tree_editor_plugin.h"
+#include "editor/plugins/audio_stream_randomizer_editor_plugin.h"
+#include "editor/plugins/bit_map_editor_plugin.h"
+#include "editor/plugins/bone_map_editor_plugin.h"
+#include "editor/plugins/camera_3d_editor_plugin.h"
+#include "editor/plugins/cast_2d_editor_plugin.h"
+#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
+#include "editor/plugins/collision_shape_2d_editor_plugin.h"
+#include "editor/plugins/control_editor_plugin.h"
+#include "editor/plugins/cpu_particles_2d_editor_plugin.h"
+#include "editor/plugins/cpu_particles_3d_editor_plugin.h"
+#include "editor/plugins/curve_editor_plugin.h"
+#include "editor/plugins/editor_debugger_plugin.h"
+#include "editor/plugins/font_config_plugin.h"
+#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
+#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
+#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
+#include "editor/plugins/gradient_editor_plugin.h"
+#include "editor/plugins/gradient_texture_2d_editor_plugin.h"
+#include "editor/plugins/input_event_editor_plugin.h"
+#include "editor/plugins/light_occluder_2d_editor_plugin.h"
+#include "editor/plugins/lightmap_gi_editor_plugin.h"
+#include "editor/plugins/line_2d_editor_plugin.h"
+#include "editor/plugins/material_editor_plugin.h"
+#include "editor/plugins/mesh_editor_plugin.h"
+#include "editor/plugins/mesh_instance_3d_editor_plugin.h"
+#include "editor/plugins/mesh_library_editor_plugin.h"
+#include "editor/plugins/multimesh_editor_plugin.h"
+#include "editor/plugins/navigation_link_2d_editor_plugin.h"
+#include "editor/plugins/navigation_polygon_editor_plugin.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
+#include "editor/plugins/occluder_instance_3d_editor_plugin.h"
+#include "editor/plugins/path_2d_editor_plugin.h"
+#include "editor/plugins/path_3d_editor_plugin.h"
+#include "editor/plugins/physical_bone_3d_editor_plugin.h"
+#include "editor/plugins/polygon_2d_editor_plugin.h"
+#include "editor/plugins/polygon_3d_editor_plugin.h"
+#include "editor/plugins/resource_preloader_editor_plugin.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "editor/plugins/shader_editor_plugin.h"
+#include "editor/plugins/shader_file_editor_plugin.h"
+#include "editor/plugins/skeleton_2d_editor_plugin.h"
+#include "editor/plugins/skeleton_3d_editor_plugin.h"
+#include "editor/plugins/skeleton_ik_3d_editor_plugin.h"
+#include "editor/plugins/sprite_2d_editor_plugin.h"
+#include "editor/plugins/sprite_frames_editor_plugin.h"
+#include "editor/plugins/style_box_editor_plugin.h"
+#include "editor/plugins/sub_viewport_preview_editor_plugin.h"
+#include "editor/plugins/texture_3d_editor_plugin.h"
+#include "editor/plugins/texture_editor_plugin.h"
+#include "editor/plugins/texture_layered_editor_plugin.h"
+#include "editor/plugins/texture_region_editor_plugin.h"
+#include "editor/plugins/theme_editor_plugin.h"
+#include "editor/plugins/tiles/tiles_editor_plugin.h"
+#include "editor/plugins/version_control_editor_plugin.h"
+#include "editor/plugins/visual_shader_editor_plugin.h"
+#include "editor/plugins/voxel_gi_editor_plugin.h"
+
+void register_editor_types() {
+ ResourceLoader::set_timestamp_on_load(true);
+ ResourceSaver::set_timestamp_on_save(true);
+
+ GDREGISTER_CLASS(EditorPaths);
+ GDREGISTER_CLASS(EditorPlugin);
+ GDREGISTER_CLASS(EditorTranslationParserPlugin);
+ GDREGISTER_CLASS(EditorImportPlugin);
+ GDREGISTER_CLASS(EditorScript);
+ GDREGISTER_CLASS(EditorSelection);
+ GDREGISTER_CLASS(EditorFileDialog);
+ GDREGISTER_ABSTRACT_CLASS(EditorSettings);
+ GDREGISTER_CLASS(EditorNode3DGizmo);
+ GDREGISTER_CLASS(EditorNode3DGizmoPlugin);
+ GDREGISTER_ABSTRACT_CLASS(EditorResourcePreview);
+ GDREGISTER_CLASS(EditorResourcePreviewGenerator);
+ GDREGISTER_ABSTRACT_CLASS(EditorFileSystem);
+ GDREGISTER_CLASS(EditorFileSystemDirectory);
+ GDREGISTER_CLASS(EditorVCSInterface);
+ GDREGISTER_ABSTRACT_CLASS(ScriptEditor);
+ GDREGISTER_ABSTRACT_CLASS(ScriptEditorBase);
+ GDREGISTER_CLASS(EditorSyntaxHighlighter);
+ GDREGISTER_ABSTRACT_CLASS(EditorInterface);
+ GDREGISTER_CLASS(EditorExportPlugin);
+ GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform);
+ GDREGISTER_CLASS(EditorResourceConversionPlugin);
+ GDREGISTER_CLASS(EditorSceneFormatImporter);
+ GDREGISTER_CLASS(EditorScenePostImportPlugin);
+ GDREGISTER_CLASS(EditorInspector);
+ GDREGISTER_CLASS(EditorInspectorPlugin);
+ GDREGISTER_CLASS(EditorProperty);
+ GDREGISTER_CLASS(AnimationTrackEditPlugin);
+ GDREGISTER_CLASS(ScriptCreateDialog);
+ GDREGISTER_CLASS(EditorFeatureProfile);
+ GDREGISTER_CLASS(EditorSpinSlider);
+ GDREGISTER_CLASS(EditorResourcePicker);
+ GDREGISTER_CLASS(EditorScriptPicker);
+ GDREGISTER_ABSTRACT_CLASS(EditorUndoRedoManager);
+
+ GDREGISTER_ABSTRACT_CLASS(FileSystemDock);
+ GDREGISTER_VIRTUAL_CLASS(EditorFileSystemImportFormatSupportQuery);
+
+ GDREGISTER_CLASS(EditorScenePostImport);
+ GDREGISTER_CLASS(EditorCommandPalette);
+ GDREGISTER_CLASS(EditorDebuggerPlugin);
+ GDREGISTER_ABSTRACT_CLASS(EditorDebuggerSession);
+
+ // This list is alphabetized, and plugins that depend on Node2D are in their own section below.
+ EditorPlugins::add_by_type<AnimationTreeEditorPlugin>();
+ EditorPlugins::add_by_type<AudioStreamRandomizerEditorPlugin>();
+ EditorPlugins::add_by_type<BitMapEditorPlugin>();
+ EditorPlugins::add_by_type<BoneMapEditorPlugin>();
+ EditorPlugins::add_by_type<Camera3DEditorPlugin>();
+ EditorPlugins::add_by_type<ControlEditorPlugin>();
+ EditorPlugins::add_by_type<CPUParticles3DEditorPlugin>();
+ EditorPlugins::add_by_type<CurveEditorPlugin>();
+ EditorPlugins::add_by_type<DebugAdapterServer>();
+ EditorPlugins::add_by_type<FontEditorPlugin>();
+ EditorPlugins::add_by_type<GPUParticles3DEditorPlugin>();
+ EditorPlugins::add_by_type<GPUParticlesCollisionSDF3DEditorPlugin>();
+ EditorPlugins::add_by_type<GradientEditorPlugin>();
+ EditorPlugins::add_by_type<GradientTexture2DEditorPlugin>();
+ EditorPlugins::add_by_type<InputEventEditorPlugin>();
+ EditorPlugins::add_by_type<LightmapGIEditorPlugin>();
+ EditorPlugins::add_by_type<MaterialEditorPlugin>();
+ EditorPlugins::add_by_type<MeshEditorPlugin>();
+ EditorPlugins::add_by_type<MeshInstance3DEditorPlugin>();
+ EditorPlugins::add_by_type<MeshLibraryEditorPlugin>();
+ EditorPlugins::add_by_type<MultiMeshEditorPlugin>();
+ EditorPlugins::add_by_type<OccluderInstance3DEditorPlugin>();
+ EditorPlugins::add_by_type<Path3DEditorPlugin>();
+ EditorPlugins::add_by_type<PhysicalBone3DEditorPlugin>();
+ EditorPlugins::add_by_type<Polygon3DEditorPlugin>();
+ EditorPlugins::add_by_type<ResourcePreloaderEditorPlugin>();
+ EditorPlugins::add_by_type<ShaderEditorPlugin>();
+ EditorPlugins::add_by_type<ShaderFileEditorPlugin>();
+ EditorPlugins::add_by_type<Skeleton3DEditorPlugin>();
+ EditorPlugins::add_by_type<SkeletonIK3DEditorPlugin>();
+ EditorPlugins::add_by_type<SpriteFramesEditorPlugin>();
+ EditorPlugins::add_by_type<StyleBoxEditorPlugin>();
+ EditorPlugins::add_by_type<SubViewportPreviewEditorPlugin>();
+ EditorPlugins::add_by_type<Texture3DEditorPlugin>();
+ EditorPlugins::add_by_type<TextureEditorPlugin>();
+ EditorPlugins::add_by_type<TextureLayeredEditorPlugin>();
+ EditorPlugins::add_by_type<TextureRegionEditorPlugin>();
+ EditorPlugins::add_by_type<ThemeEditorPlugin>();
+ EditorPlugins::add_by_type<VoxelGIEditorPlugin>();
+
+ // 2D
+ EditorPlugins::add_by_type<CollisionPolygon2DEditorPlugin>();
+ EditorPlugins::add_by_type<CollisionShape2DEditorPlugin>();
+ EditorPlugins::add_by_type<CPUParticles2DEditorPlugin>();
+ EditorPlugins::add_by_type<GPUParticles2DEditorPlugin>();
+ EditorPlugins::add_by_type<LightOccluder2DEditorPlugin>();
+ EditorPlugins::add_by_type<Line2DEditorPlugin>();
+ EditorPlugins::add_by_type<NavigationLink2DEditorPlugin>();
+ EditorPlugins::add_by_type<NavigationPolygonEditorPlugin>();
+ EditorPlugins::add_by_type<Path2DEditorPlugin>();
+ EditorPlugins::add_by_type<Polygon2DEditorPlugin>();
+ EditorPlugins::add_by_type<Cast2DEditorPlugin>();
+ EditorPlugins::add_by_type<Skeleton2DEditorPlugin>();
+ EditorPlugins::add_by_type<Sprite2DEditorPlugin>();
+ EditorPlugins::add_by_type<TilesEditorPlugin>();
+}
+
+void unregister_editor_types() {
+ EditorNode::cleanup();
+ if (EditorPaths::get_singleton()) {
+ EditorPaths::free();
+ }
+
+ EditorResourcePicker::clear_caches();
+}
diff --git a/editor/register_editor_types.h b/editor/register_editor_types.h
new file mode 100644
index 0000000000..f53e7e3649
--- /dev/null
+++ b/editor/register_editor_types.h
@@ -0,0 +1,37 @@
+/*************************************************************************/
+/* register_editor_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef REGISTER_EDITOR_TYPES_H
+#define REGISTER_EDITOR_TYPES_H
+
+void register_editor_types();
+void unregister_editor_types();
+
+#endif // REGISTER_EDITOR_TYPES_H
diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp
index 5b54a5a229..9f3ce26a59 100644
--- a/editor/scene_create_dialog.cpp
+++ b/editor/scene_create_dialog.cpp
@@ -175,7 +175,7 @@ Node *SceneCreateDialog::create_scene_root() {
root = gui_ctl;
} break;
case ROOT_OTHER:
- root = Object::cast_to<Node>(select_node_dialog->instance_selected());
+ root = Object::cast_to<Node>(select_node_dialog->instantiate_selected());
break;
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 64ac38aaa5..7c323a8524 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -106,7 +106,7 @@ void SceneTreeDock::shortcut_input(const Ref<InputEvent> &p_event) {
#endif // MODULE_REGEX_ENABLED
} else if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
_tool_selected(TOOL_NEW);
- } else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) {
+ } else if (ED_IS_SHORTCUT("scene_tree/instantiate_scene", p_event)) {
_tool_selected(TOOL_INSTANTIATE);
} else if (ED_IS_SHORTCUT("scene_tree/expand_collapse_all", p_event)) {
_tool_selected(TOOL_EXPAND_COLLAPSE);
@@ -198,7 +198,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instantiated_scene) {
current_option = -1;
- accept->set_text(vformat(TTR("Error instancing scene from %s"), p_files[i]));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), p_files[i]));
accept->popup_centered();
error = true;
break;
@@ -206,7 +206,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
if (!edited_scene->get_scene_file_path().is_empty()) {
if (_cyclical_dependency_exists(edited_scene->get_scene_file_path(), instantiated_scene)) {
- accept->set_text(vformat(TTR("Cannot instance the scene '%s' because the current scene exists within one of its nodes."), p_files[i]));
+ accept->set_text(vformat(TTR("Cannot instantiate the scene '%s' because the current scene exists within one of its nodes."), p_files[i]));
accept->popup_centered();
error = true;
break;
@@ -225,7 +225,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
return;
}
- editor_data->get_undo_redo()->create_action(TTR("Instance Scene(s)"));
+ editor_data->get_undo_redo()->create_action(TTR("Instantiate Scene(s)"));
for (int i = 0; i < instances.size(); i++) {
Node *instantiated_scene = instances[i];
@@ -242,7 +242,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
String new_name = parent->validate_child_name(instantiated_scene);
EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
- editor_data->get_undo_redo()->add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), p_files[i], new_name);
+ editor_data->get_undo_redo()->add_do_method(ed, "live_debug_instantiate_node", edited_scene->get_path_to(parent), p_files[i], new_name);
editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(new_name)));
}
@@ -263,7 +263,7 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instantiated_scene) {
- accept->set_text(vformat(TTR("Error instancing scene from %s"), p_file));
+ accept->set_text(vformat(TTR("Error instantiating scene from %s"), p_file));
accept->popup_centered();
return;
}
@@ -1814,7 +1814,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
// Sort by tree order, so re-adding is easy.
p_nodes.sort_custom<Node::Comparator>();
- editor_data->get_undo_redo()->create_action(TTR("Reparent Node"));
+ editor_data->get_undo_redo()->create_action(TTR("Reparent Node"), UndoRedo::MERGE_DISABLE, p_nodes[0]);
HashMap<Node *, NodePath> path_renames;
Vector<StringName> former_names;
@@ -1835,14 +1835,17 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
owners.push_back(E);
}
- if (new_parent == node->get_parent() && node->get_index() < p_position_in_parent + ni) {
+ bool same_parent = new_parent == node->get_parent();
+ if (same_parent && node->get_index() < p_position_in_parent + ni) {
inc--; // If the child will generate a gap when moved, adjust.
}
- editor_data->get_undo_redo()->add_do_method(node->get_parent(), "remove_child", node);
- editor_data->get_undo_redo()->add_do_method(new_parent, "add_child", node, true);
+ if (!same_parent) {
+ editor_data->get_undo_redo()->add_do_method(node->get_parent(), "remove_child", node);
+ editor_data->get_undo_redo()->add_do_method(new_parent, "add_child", node, true);
+ }
- if (p_position_in_parent >= 0) {
+ if (p_position_in_parent >= 0 || same_parent) {
editor_data->get_undo_redo()->add_do_method(new_parent, "move_child", node, p_position_in_parent + inc);
}
@@ -2177,7 +2180,7 @@ void SceneTreeDock::_selection_changed() {
}
void SceneTreeDock::_do_create(Node *p_parent) {
- Variant c = create_dialog->instance_selected();
+ Variant c = create_dialog->instantiate_selected();
Node *child = Object::cast_to<Node>(c);
ERR_FAIL_COND(!child);
@@ -2261,7 +2264,7 @@ void SceneTreeDock::_create() {
for (Node *n : selection) {
ERR_FAIL_COND(!n);
- Variant c = create_dialog->instance_selected();
+ Variant c = create_dialog->instantiate_selected();
ERR_FAIL_COND(!c);
Node *newnode = Object::cast_to<Node>(c);
@@ -2686,7 +2689,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->clear();
if (profile_allow_editing) {
menu->add_icon_shortcut(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instantiate_scene"), TOOL_INSTANTIATE);
}
menu->reset_size();
@@ -2719,7 +2722,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
}
menu->add_icon_shortcut(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANTIATE);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/instantiate_scene"), TOOL_INSTANTIATE);
}
menu->add_icon_shortcut(get_theme_icon(SNAME("Collapse"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE);
menu->add_separator();
@@ -3445,7 +3448,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
ED_SHORTCUT_OVERRIDE("scene_tree/batch_rename", "macos", KeyModifierMask::SHIFT | Key::ENTER);
ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KeyModifierMask::CMD_OR_CTRL | Key::A);
- ED_SHORTCUT("scene_tree/instance_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::A);
+ ED_SHORTCUT("scene_tree/instantiate_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::A);
ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse Branch"));
ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KeyModifierMask::CMD_OR_CTRL | Key::X);
ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KeyModifierMask::CMD_OR_CTRL | Key::C);
@@ -3477,7 +3480,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
button_instance->set_flat(true);
button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_INSTANTIATE, false));
button_instance->set_tooltip_text(TTR("Instantiate a scene file as a Node. Creates an inherited scene if no root node exists."));
- button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instance_scene"));
+ button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instantiate_scene"));
filter_hbc->add_child(button_instance);
vbc->add_child(filter_hbc);
@@ -3514,6 +3517,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
button_tree_menu = memnew(MenuButton);
button_tree_menu->set_flat(true);
+ button_tree_menu->set_tooltip_text(TTR("Extra scene options."));
button_tree_menu->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_update_tree_menu));
filter_hbc->add_child(button_tree_menu);
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 04bb4d93e7..6ec9d31ca8 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -46,6 +46,8 @@
#include "scene/gui/tree.h"
#include "scene_tree_editor.h"
+class TextureRect;
+
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
class RenameDialog;
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 08c0f0f708..4a3b0e979f 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -853,7 +853,7 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL
script_template.inherit = p_inherits;
String space_indent = " ";
// Get meta delimiter
- String meta_delimiter = String();
+ String meta_delimiter;
List<String> comment_delimiters;
p_language->get_comment_delimiters(&comment_delimiters);
for (const String &script_delimiter : comment_delimiters) {
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index 596b3eefba..9b82e80072 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -111,7 +111,7 @@ protected:
undo_redo->add_do_method(this, "_var_changed");
undo_redo->add_undo_method(this, "_var_changed");
block_update = true;
- undo_redo->commit_action();
+ undo_redo->commit_action(false);
block_update = false;
return true;
diff --git a/gles3_builders.py b/gles3_builders.py
index 46ab1bbc03..0d0037dea1 100644
--- a/gles3_builders.py
+++ b/gles3_builders.py
@@ -20,6 +20,7 @@ class GLES3HeaderStruct:
self.texunit_names = []
self.ubos = []
self.ubo_names = []
+ self.feedbacks = []
self.vertex_included_files = []
self.fragment_included_files = []
@@ -168,6 +169,20 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct,
if not x in header_data.uniforms:
header_data.uniforms += [x]
+ if (line.strip().find("out ") == 0 or line.strip().find("flat ") == 0) and line.find("tfb:") != -1:
+ uline = line.replace("flat ", "")
+ uline = uline.replace("out ", "")
+ uline = uline.replace("highp ", "")
+ uline = uline.replace(";", "")
+ uline = uline[uline.find(" ") :].strip()
+
+ if uline.find("//") != -1:
+ name, bind = uline.split("//")
+ if bind.find("tfb:") != -1:
+ name = name.strip()
+ bind = bind.replace("tfb:", "").strip()
+ header_data.feedbacks += [(name, bind)]
+
line = line.replace("\r", "")
line = line.replace("\n", "")
@@ -240,11 +255,11 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
defspec |= 1 << i
fd.write(
- "\t_FORCE_INLINE_ void version_bind_shader(RID p_version,ShaderVariant p_variant"
+ "\t_FORCE_INLINE_ bool version_bind_shader(RID p_version,ShaderVariant p_variant"
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _version_bind_shader(p_version,p_variant,p_specialization); }\n\n"
+ + ") { return _version_bind_shader(p_version,p_variant,p_specialization); }\n\n"
)
if header_data.uniforms:
@@ -278,7 +293,7 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _FU glUniform1i(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
+ + ") { _FU glUniform1ui(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
)
fd.write(
"\t_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int8_t p_value,RID p_version,ShaderVariant p_variant"
@@ -292,7 +307,7 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _FU glUniform1i(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
+ + ") { _FU glUniform1ui(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
)
fd.write(
"\t_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int16_t p_value,RID p_version,ShaderVariant p_variant"
@@ -306,7 +321,7 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ defvariant
+ ",uint64_t p_specialization="
+ str(defspec)
- + ") { _FU glUniform1i(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
+ + ") { _FU glUniform1ui(version_get_uniform(p_uniform,p_version,p_variant,p_specialization),p_value); }\n\n"
)
fd.write(
"\t_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int32_t p_value,RID p_version,ShaderVariant p_variant"
@@ -497,6 +512,8 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
else:
fd.write("\t\tstatic UBOPair *_ubo_pairs=nullptr;\n")
+ specializations_found = []
+
if header_data.specialization_names:
fd.write("\t\tstatic Specialization _spec_pairs[]={\n")
for i in range(len(header_data.specialization_names)):
@@ -507,10 +524,30 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
defval = "false"
fd.write('\t\t\t{"' + header_data.specialization_names[i] + '",' + defval + "},\n")
+ specializations_found.append(header_data.specialization_names[i])
fd.write("\t\t};\n\n")
else:
fd.write("\t\tstatic Specialization *_spec_pairs=nullptr;\n")
+ feedback_count = 0
+
+ if header_data.feedbacks:
+
+ fd.write("\t\tstatic const Feedback _feedbacks[]={\n")
+ for x in header_data.feedbacks:
+ name = x[0]
+ spec = x[1]
+ if spec in specializations_found:
+ fd.write('\t\t\t{"' + name + '",' + str(1 << specializations_found.index(spec)) + "},\n")
+ else:
+ fd.write('\t\t\t{"' + name + '",0},\n')
+
+ feedback_count += 1
+
+ fd.write("\t\t};\n\n")
+ else:
+ fd.write("\t\tstatic const Feedback* _feedbacks=nullptr;\n")
+
fd.write("\t\tstatic const char _vertex_code[]={\n")
for x in header_data.vertex_lines:
for c in x:
@@ -535,6 +572,8 @@ def build_gles3_header(filename: str, include: str, class_suffix: str, header_da
+ ",_uniform_strings,"
+ str(len(header_data.ubos))
+ ",_ubo_pairs,"
+ + str(feedback_count)
+ + ",_feedbacks,"
+ str(len(header_data.texunits))
+ ",_texunit_pairs,"
+ str(len(header_data.specialization_names))
diff --git a/main/main.cpp b/main/main.cpp
index 0fce8e3d94..55f7177258 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -85,6 +85,7 @@
#endif
#ifdef TOOLS_ENABLED
+#include "editor/debugger/editor_debugger_node.h"
#include "editor/doc_data_class_path.gen.h"
#include "editor/doc_tools.h"
#include "editor/editor_node.h"
@@ -94,6 +95,7 @@
#include "editor/progress_dialog.h"
#include "editor/project_converter_3_to_4.h"
#include "editor/project_manager.h"
+#include "editor/register_editor_types.h"
#ifndef NO_EDITOR_SPLASH
#include "main/splash_editor.gen.h"
#endif
@@ -486,7 +488,7 @@ Error Main::test_setup() {
#ifdef TOOLS_ENABLED
ClassDB::set_current_api(ClassDB::API_EDITOR);
- EditorNode::register_editor_types();
+ register_editor_types();
initialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
@@ -539,7 +541,7 @@ void Main::test_cleanup() {
#ifdef TOOLS_ENABLED
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
- EditorNode::unregister_editor_types();
+ unregister_editor_types();
#endif
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SCENE);
@@ -1788,6 +1790,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_ticks_per_second",
PropertyInfo(Variant::INT, "physics/common/physics_ticks_per_second",
PROPERTY_HINT_RANGE, "1,1000,1"));
+
+ Engine::get_singleton()->set_max_physics_steps_per_frame(GLOBAL_DEF("physics/common/max_physics_steps_per_frame", 8));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/common/max_physics_steps_per_frame",
+ PropertyInfo(Variant::INT, "physics/common/max_physics_steps_per_frame",
+ PROPERTY_HINT_RANGE, "1,100,1"));
+
Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF("physics/common/physics_jitter_fix", 0.5));
Engine::get_singleton()->set_max_fps(GLOBAL_DEF("application/run/max_fps", 0));
ProjectSettings::get_singleton()->set_custom_property_info("application/run/max_fps",
@@ -1925,6 +1933,9 @@ error:
}
Error Main::setup2(Thread::ID p_main_tid_override) {
+ // Print engine name and version
+ print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
+
engine->startup_benchmark_begin_measure("servers");
tsman = memnew(TextServerManager);
@@ -1942,9 +1953,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
- // Print engine name and version
- print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
-
if (p_main_tid_override) {
Thread::main_thread_id = p_main_tid_override;
}
@@ -2312,7 +2320,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
#ifdef TOOLS_ENABLED
ClassDB::set_current_api(ClassDB::API_EDITOR);
- EditorNode::register_editor_types();
+ register_editor_types();
initialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
@@ -3104,7 +3112,7 @@ bool Main::iteration() {
last_ticks = ticks;
- static const int max_physics_steps = 8;
+ const int max_physics_steps = Engine::get_singleton()->get_max_physics_steps_per_frame();
if (fixed_fps == -1 && advance.physics_steps > max_physics_steps) {
process_step -= (advance.physics_steps - max_physics_steps) * physics_step;
advance.physics_steps = max_physics_steps;
@@ -3312,7 +3320,7 @@ void Main::cleanup(bool p_force) {
#ifdef TOOLS_ENABLED
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_EDITOR);
- EditorNode::unregister_editor_types();
+ unregister_editor_types();
#endif
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index b58f002f3c..e717b501f4 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -164,7 +164,7 @@
};
buildConfigurationList = D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "$binary" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh
index 1200b96ea0..a2f33692f9 100755
--- a/misc/scripts/file_format.sh
+++ b/misc/scripts/file_format.sh
@@ -31,7 +31,9 @@ while IFS= read -rd '' f; do
continue
elif [[ "$f" == *"po" ]]; then
continue
- elif [[ "$f" == "thirdparty"* ]]; then
+ elif [[ "$f" == "thirdparty/"* ]]; then
+ continue
+ elif [[ "$f" == *"/thirdparty/"* ]]; then
continue
elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then
continue
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 420401cb79..0ebdbf090d 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -322,7 +322,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
String word = str.substr(j, to - j);
- Color col = Color();
+ Color col;
if (global_functions.has(word)) {
// "assert" and "preload" are reserved, so highlight even if not followed by a bracket.
if (word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::ASSERT) || word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::PRELOAD)) {
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index b4da9c1224..60230257e0 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -629,10 +629,6 @@ void GDScript::_update_doc() {
}
}
- for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
- E.value->_update_doc();
- }
-
_add_doc(doc);
}
#endif
@@ -674,36 +670,14 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
base_cache = Ref<GDScript>();
}
- if (c->extends_used) {
- String ext_path = "";
- if (String(c->extends_path) != "" && String(c->extends_path) != get_path()) {
- ext_path = c->extends_path;
- if (ext_path.is_relative_path()) {
- String base_path = get_path();
- if (base_path.is_empty() || base_path.is_relative_path()) {
- ERR_PRINT(("Could not resolve relative path for parent class: " + ext_path).utf8().get_data());
- } else {
- ext_path = base_path.get_base_dir().path_join(ext_path);
- }
- }
- } else if (c->extends.size() != 0) {
- const StringName &base_class = c->extends[0];
-
- if (ScriptServer::is_global_class(base_class)) {
- ext_path = ScriptServer::get_global_class_path(base_class);
- }
- }
-
- if (!ext_path.is_empty()) {
- if (ext_path != get_path()) {
- Ref<GDScript> bf = ResourceLoader::load(ext_path);
-
- if (bf.is_valid()) {
- base_cache = bf;
- bf->inheriters_cache.insert(get_instance_id());
- }
- } else {
- ERR_PRINT(("Path extending itself in " + ext_path).utf8().get_data());
+ GDScriptParser::DataType base_type = parser.get_tree()->base_type;
+ if (base_type.kind == GDScriptParser::DataType::CLASS) {
+ Ref<GDScript> bf = GDScriptCache::get_full_script(base_type.script_path, err, path);
+ if (err == OK) {
+ bf = Ref<GDScript>(bf->find_class(base_type.class_type->fqcn));
+ if (bf.is_valid()) {
+ base_cache = bf;
+ bf->inheriters_cache.insert(get_instance_id());
}
}
}
@@ -825,13 +799,6 @@ void GDScript::update_exports() {
#endif
}
-void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) {
- p_sc->path = p_path;
- for (KeyValue<StringName, Ref<GDScript>> &E : p_sc->subclasses) {
- _set_subclass_path(E.value, p_path);
- }
-}
-
String GDScript::_get_debug_path() const {
if (is_built_in() && !get_name().is_empty()) {
return get_name() + " (" + get_path() + ")";
@@ -841,6 +808,11 @@ String GDScript::_get_debug_path() const {
}
Error GDScript::reload(bool p_keep_state) {
+ if (reloading) {
+ return OK;
+ }
+ reloading = true;
+
bool has_instances;
{
MutexLock lock(GDScriptLanguage::singleton->mutex);
@@ -860,9 +832,10 @@ Error GDScript::reload(bool p_keep_state) {
basedir = basedir.get_base_dir();
}
-// Loading a template, don't parse.
+ // Loading a template, don't parse.
#ifdef TOOLS_ENABLED
if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) {
+ reloading = false;
return OK;
}
#endif
@@ -872,11 +845,10 @@ Error GDScript::reload(bool p_keep_state) {
if (source_path.is_empty()) {
source_path = get_path();
}
- if (!source_path.is_empty()) {
- MutexLock lock(GDScriptCache::singleton->lock);
- if (!GDScriptCache::singleton->shallow_gdscript_cache.has(source_path)) {
- GDScriptCache::singleton->shallow_gdscript_cache[source_path] = this;
- }
+ Ref<GDScript> cached_script = GDScriptCache::get_cached_script(source_path);
+ if (!source_path.is_empty() && cached_script.is_null()) {
+ MutexLock lock(GDScriptCache::singleton->mutex);
+ GDScriptCache::singleton->shallow_gdscript_cache[source_path] = Ref<GDScript>(this);
}
}
@@ -889,6 +861,7 @@ Error GDScript::reload(bool p_keep_state) {
}
// TODO: Show all error messages.
_err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
+ reloading = false;
return ERR_PARSE_ERROR;
}
@@ -905,6 +878,7 @@ Error GDScript::reload(bool p_keep_state) {
_err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
e = e->next();
}
+ reloading = false;
return ERR_PARSE_ERROR;
}
@@ -913,18 +887,16 @@ Error GDScript::reload(bool p_keep_state) {
GDScriptCompiler compiler;
err = compiler.compile(&parser, this, p_keep_state);
-#ifdef TOOLS_ENABLED
- _update_doc();
-#endif
-
if (err) {
if (can_run) {
if (EngineDebugger::is_active()) {
GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error());
}
_err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT);
+ reloading = false;
return ERR_COMPILATION_FAILED;
} else {
+ reloading = false;
return err;
}
}
@@ -937,14 +909,7 @@ Error GDScript::reload(bool p_keep_state) {
}
#endif
- valid = true;
-
- for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
- _set_subclass_path(E.value, path);
- }
-
- _init_rpc_methods_properties();
-
+ reloading = false;
return OK;
}
@@ -1051,11 +1016,22 @@ Error GDScript::load_byte_code(const String &p_path) {
}
void GDScript::set_path(const String &p_path, bool p_take_over) {
- Script::set_path(p_path, p_take_over);
+ String old_path = path;
+ if (is_root_script()) {
+ Script::set_path(p_path, p_take_over);
+ }
this->path = p_path;
+ GDScriptCache::move_script(old_path, p_path);
+ for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) {
+ kv.value->set_path(p_path, p_take_over);
+ }
}
Error GDScript::load_source_code(const String &p_path) {
+ if (p_path.is_empty() || ResourceLoader::get_resource_type(p_path.get_slice("::", 0)) == "PackedScene") {
+ return OK;
+ }
+
Vector<uint8_t> sourcef;
Error err;
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
@@ -1127,6 +1103,124 @@ bool GDScript::inherits_script(const Ref<Script> &p_script) const {
return false;
}
+GDScript *GDScript::find_class(const String &p_qualified_name) {
+ String first = p_qualified_name.get_slice("::", 0);
+
+ GDScript *result = nullptr;
+ if (first.is_empty() || first == name) {
+ result = this;
+ } else if (first == get_root_script()->path) {
+ result = get_root_script();
+ } else if (HashMap<StringName, Ref<GDScript>>::Iterator E = subclasses.find(first)) {
+ result = E->value.ptr();
+ } else if (_owner != nullptr) {
+ // Check parent scope.
+ return _owner->find_class(p_qualified_name);
+ }
+
+ int name_count = p_qualified_name.get_slice_count("::");
+ for (int i = 1; result != nullptr && i < name_count; i++) {
+ String current_name = p_qualified_name.get_slice("::", i);
+ if (HashMap<StringName, Ref<GDScript>>::Iterator E = result->subclasses.find(current_name)) {
+ result = E->value.ptr();
+ } else {
+ // Couldn't find inner class.
+ return nullptr;
+ }
+ }
+
+ return result;
+}
+
+bool GDScript::is_subclass(const GDScript *p_script) {
+ String fqn = p_script->fully_qualified_name;
+ if (!fqn.is_empty() && fqn != fully_qualified_name && fqn.begins_with(fully_qualified_name)) {
+ String fqn_rest = fqn.substr(fully_qualified_name.length());
+ return find_class(fqn_rest) == p_script;
+ }
+ return false;
+}
+
+GDScript *GDScript::get_root_script() {
+ GDScript *result = this;
+ while (result->_owner) {
+ result = result->_owner;
+ }
+ return result;
+}
+
+RBSet<GDScript *> GDScript::get_dependencies() {
+ RBSet<GDScript *> dependencies;
+
+ _get_dependencies(dependencies, this);
+ dependencies.erase(this);
+
+ return dependencies;
+}
+
+RBSet<GDScript *> GDScript::get_inverted_dependencies() {
+ RBSet<GDScript *> inverted_dependencies;
+
+ List<GDScript *> scripts;
+ {
+ MutexLock lock(GDScriptLanguage::singleton->mutex);
+
+ SelfList<GDScript> *elem = GDScriptLanguage::singleton->script_list.first();
+ while (elem) {
+ scripts.push_back(elem->self());
+ elem = elem->next();
+ }
+ }
+
+ for (GDScript *scr : scripts) {
+ if (scr == nullptr || scr == this || scr->destructing) {
+ continue;
+ }
+
+ RBSet<GDScript *> scr_dependencies = scr->get_dependencies();
+ if (scr_dependencies.has(this)) {
+ inverted_dependencies.insert(scr);
+ }
+ }
+
+ return inverted_dependencies;
+}
+
+RBSet<GDScript *> GDScript::get_must_clear_dependencies() {
+ RBSet<GDScript *> dependencies = get_dependencies();
+ RBSet<GDScript *> must_clear_dependencies;
+ HashMap<GDScript *, RBSet<GDScript *>> inverted_dependencies;
+
+ for (GDScript *E : dependencies) {
+ inverted_dependencies.insert(E, E->get_inverted_dependencies());
+ }
+
+ RBSet<GDScript *> cant_clear;
+ for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) {
+ for (GDScript *F : E.value) {
+ if (!dependencies.has(F)) {
+ cant_clear.insert(E.key);
+ for (GDScript *G : E.key->get_dependencies()) {
+ cant_clear.insert(G);
+ }
+ break;
+ }
+ }
+ }
+
+ for (KeyValue<GDScript *, RBSet<GDScript *>> &E : inverted_dependencies) {
+ if (cant_clear.has(E.key) || ScriptServer::is_global_class(E.key->get_fully_qualified_name())) {
+ continue;
+ }
+ must_clear_dependencies.insert(E.key);
+ }
+
+ cant_clear.clear();
+ dependencies.clear();
+ inverted_dependencies.clear();
+ return must_clear_dependencies;
+}
+
bool GDScript::has_script_signal(const StringName &p_signal) const {
if (_signals.has(p_signal)) {
return true;
@@ -1188,6 +1282,69 @@ String GDScript::_get_gdscript_reference_class_name(const GDScript *p_gdscript)
return class_name;
}
+GDScript *GDScript::_get_gdscript_from_variant(const Variant &p_variant) {
+ Variant::Type type = p_variant.get_type();
+ if (type != Variant::Type::OBJECT)
+ return nullptr;
+
+ Object *obj = p_variant;
+ if (obj == nullptr) {
+ return nullptr;
+ }
+
+ return Object::cast_to<GDScript>(obj);
+}
+
+void GDScript::_get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except) {
+ if (skip_dependencies || p_dependencies.has(this)) {
+ return;
+ }
+ p_dependencies.insert(this);
+
+ for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
+ if (E.value == nullptr) {
+ continue;
+ }
+ for (const Variant &V : E.value->constants) {
+ GDScript *scr = _get_gdscript_from_variant(V);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+ }
+
+ if (implicit_initializer) {
+ for (const Variant &V : implicit_initializer->constants) {
+ GDScript *scr = _get_gdscript_from_variant(V);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+ }
+
+ if (implicit_ready) {
+ for (const Variant &V : implicit_ready->constants) {
+ GDScript *scr = _get_gdscript_from_variant(V);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+ }
+
+ for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
+ if (E.value != p_except) {
+ E.value->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+
+ for (const KeyValue<StringName, Variant> &E : constants) {
+ GDScript *scr = _get_gdscript_from_variant(E.value);
+ if (scr != nullptr && scr != p_except) {
+ scr->_get_dependencies(p_dependencies, p_except);
+ }
+ }
+}
+
GDScript::GDScript() :
script_list(this) {
#ifdef DEBUG_ENABLED
@@ -1238,56 +1395,67 @@ void GDScript::_init_rpc_methods_properties() {
rpc_config = base->rpc_config.duplicate();
}
- GDScript *cscript = this;
- HashMap<StringName, Ref<GDScript>>::Iterator sub_E = subclasses.begin();
- while (cscript) {
- // RPC Methods
- for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) {
- Variant config = E.value->get_rpc_config();
- if (config.get_type() != Variant::NIL) {
- rpc_config[E.value->get_name()] = config;
- }
- }
-
- if (cscript != this) {
- ++sub_E;
- }
-
- if (sub_E) {
- cscript = sub_E->value.ptr();
- } else {
- cscript = nullptr;
+ // RPC Methods
+ for (KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
+ Variant config = E.value->get_rpc_config();
+ if (config.get_type() != Variant::NIL) {
+ rpc_config[E.value->get_name()] = config;
}
}
}
-GDScript::~GDScript() {
- {
- MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
+void GDScript::clear() {
+ if (clearing) {
+ return;
+ }
+ clearing = true;
- while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
- // Order matters since clearing the stack may already cause
- // the GDSCriptFunctionState to be destroyed and thus removed from the list.
- pending_func_states.remove(E);
- E->self()->_clear_stack();
+ RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies();
+ HashMap<GDScript *, ObjectID> must_clear_dependencies_objectids;
+
+ // Log the objectids before clearing, as a cascade of clear could
+ // remove instances that are still in the clear loop
+ for (GDScript *E : must_clear_dependencies) {
+ must_clear_dependencies_objectids.insert(E, E->get_instance_id());
+ }
+
+ for (GDScript *E : must_clear_dependencies) {
+ Object *obj = ObjectDB::get_instance(must_clear_dependencies_objectids[E]);
+ if (obj == nullptr) {
+ continue;
}
+
+ E->skip_dependencies = true;
+ E->clear();
+ E->skip_dependencies = false;
+ GDScriptCache::remove_script(E->get_path());
}
+ RBSet<StringName> member_function_names;
for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
- memdelete(E.value);
+ member_function_names.insert(E.key);
+ }
+ for (const StringName &E : member_function_names) {
+ if (member_functions.has(E)) {
+ memdelete(member_functions[E]);
+ }
+ }
+ member_function_names.clear();
+ member_functions.clear();
+
+ for (KeyValue<StringName, GDScript::MemberInfo> &E : member_indices) {
+ E.value.data_type.script_type_ref = Ref<Script>();
}
if (implicit_initializer) {
memdelete(implicit_initializer);
}
+ implicit_initializer = nullptr;
if (implicit_ready) {
memdelete(implicit_ready);
}
-
- if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown.
- GDScriptCache::remove_script(get_path());
- }
+ implicit_ready = nullptr;
_save_orphaned_subclasses();
@@ -1297,6 +1465,27 @@ GDScript::~GDScript() {
_clear_doc();
}
#endif
+ clearing = false;
+}
+
+GDScript::~GDScript() {
+ if (destructing) {
+ return;
+ }
+ destructing = true;
+
+ clear();
+
+ {
+ MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
+
+ while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
+ // Order matters since clearing the stack may already cause
+ // the GDScriptFunctionState to be destroyed and thus removed from the list.
+ pending_func_states.remove(E);
+ E->self()->_clear_stack();
+ }
+ }
#ifdef DEBUG_ENABLED
{
@@ -1305,6 +1494,10 @@ GDScript::~GDScript() {
GDScriptLanguage::get_singleton()->script_list.remove(&script_list);
}
#endif
+
+ if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown.
+ GDScriptCache::remove_script(get_path());
+ }
}
//////////////////////////////
@@ -2344,26 +2537,27 @@ GDScriptLanguage::~GDScriptLanguage() {
// Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit).
SelfList<GDScript> *s = script_list.first();
while (s) {
- GDScript *scr = s->self();
// This ensures the current script is not released before we can check what's the next one
// in the list (we can't get the next upfront because we don't know if the reference breaking
// will cause it -or any other after it, for that matter- to be released so the next one
// is not the same as before).
- scr->reference();
-
- for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) {
- GDScriptFunction *func = E.value;
- for (int i = 0; i < func->argument_types.size(); i++) {
- func->argument_types.write[i].script_type_ref = Ref<Script>();
+ Ref<GDScript> scr = s->self();
+ if (scr.is_valid()) {
+ for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) {
+ GDScriptFunction *func = E.value;
+ for (int i = 0; i < func->argument_types.size(); i++) {
+ func->argument_types.write[i].script_type_ref = Ref<Script>();
+ }
+ func->return_type.script_type_ref = Ref<Script>();
+ }
+ for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) {
+ E.value.data_type.script_type_ref = Ref<Script>();
}
- func->return_type.script_type_ref = Ref<Script>();
- }
- for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) {
- E.value.data_type.script_type_ref = Ref<Script>();
- }
+ // Clear backup for scripts that could slip out of the cyclic reference check
+ scr->clear();
+ }
s = s->next();
- scr->unreference();
}
singleton = nullptr;
@@ -2387,6 +2581,27 @@ Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_na
return Ref<GDScript>(Object::cast_to<GDScript>(obj));
}
+Ref<GDScript> GDScriptLanguage::get_script_by_fully_qualified_name(const String &p_name) {
+ {
+ MutexLock lock(mutex);
+
+ SelfList<GDScript> *elem = script_list.first();
+ while (elem) {
+ GDScript *scr = elem->self();
+ scr = scr->find_class(p_name);
+ if (scr != nullptr) {
+ return scr;
+ }
+ elem = elem->next();
+ }
+ }
+
+ Ref<GDScript> scr;
+ scr.instantiate();
+ scr->fully_qualified_name = p_name;
+ return scr;
+}
+
/*************** RESOURCE ***************/
Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 72ad890fbc..2df89d812c 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -61,6 +61,8 @@ class GDScript : public Script {
GDCLASS(GDScript, Script);
bool tool = false;
bool valid = false;
+ bool reloading = false;
+ bool skip_dependencies = false;
struct MemberInfo {
int index = 0;
@@ -124,6 +126,8 @@ class GDScript : public Script {
int subclass_count = 0;
RBSet<Object *> instances;
+ bool destructing = false;
+ bool clearing = false;
//exported members
String source;
String path;
@@ -137,7 +141,6 @@ class GDScript : public Script {
void _super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error);
GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
- void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path);
String _get_debug_path() const;
#ifdef TOOLS_ENABLED
@@ -164,6 +167,9 @@ class GDScript : public Script {
// This method will map the class name from "RefCounted" to "MyClass.InnerClass".
static String _get_gdscript_reference_class_name(const GDScript *p_gdscript);
+ GDScript *_get_gdscript_from_variant(const Variant &p_variant);
+ void _get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except);
+
protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
bool _set(const StringName &p_name, const Variant &p_value);
@@ -174,10 +180,17 @@ protected:
static void _bind_methods();
public:
+ void clear();
+
virtual bool is_valid() const override { return valid; }
bool inherits_script(const Ref<Script> &p_script) const override;
+ GDScript *find_class(const String &p_qualified_name);
+ bool is_subclass(const GDScript *p_script);
+ GDScript *get_root_script();
+ bool is_root_script() const { return _owner == nullptr; }
+ String get_fully_qualified_name() const { return fully_qualified_name; }
const HashMap<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; }
const HashMap<StringName, Variant> &get_constants() const { return constants; }
const HashSet<StringName> &get_members() const { return members; }
@@ -189,6 +202,10 @@ public:
const Ref<GDScriptNativeClass> &get_native() const { return native; }
const String &get_script_class_name() const { return name; }
+ RBSet<GDScript *> get_dependencies();
+ RBSet<GDScript *> get_inverted_dependencies();
+ RBSet<GDScript *> get_must_clear_dependencies();
+
virtual bool has_script_signal(const StringName &p_signal) const override;
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const override;
@@ -223,7 +240,6 @@ public:
virtual Error reload(bool p_keep_state = false) override;
virtual void set_path(const String &p_path, bool p_take_over = false) override;
- void set_script_path(const String &p_path) { path = p_path; } //because subclasses need a path too...
Error load_source_code(const String &p_path);
Error load_byte_code(const String &p_path);
@@ -267,6 +283,7 @@ class GDScriptInstance : public ScriptInstance {
friend class GDScriptLambdaCallable;
friend class GDScriptLambdaSelfCallable;
friend class GDScriptCompiler;
+ friend class GDScriptCache;
friend struct GDScriptUtilityFunctionsDefinitions;
ObjectID owner_id;
@@ -515,6 +532,8 @@ public:
void add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass);
Ref<GDScript> get_orphan_subclass(const String &p_qualified_name);
+ Ref<GDScript> get_script_by_fully_qualified_name(const String &p_name);
+
GDScriptLanguage();
~GDScriptLanguage();
};
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 704dda8045..3a536b42c1 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -32,6 +32,7 @@
#include "core/config/engine.h"
#include "core/config/project_settings.h"
+#include "core/core_string_names.h"
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/object/class_db.h"
@@ -39,6 +40,7 @@
#include "core/templates/hash_map.h"
#include "gdscript.h"
#include "gdscript_utility_functions.h"
+#include "scene/resources/packed_scene.h"
static MethodInfo info_from_utility_func(const StringName &p_function) {
ERR_FAIL_COND_V(!Variant::has_utility_function(p_function), MethodInfo());
@@ -132,7 +134,7 @@ static GDScriptParser::DataType make_builtin_meta_type(Variant::Type p_type) {
return type;
}
-bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class) {
+bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_member) {
if (p_class->members_indices.has(p_member_name)) {
int index = p_class->members_indices[p_member_name];
const GDScriptParser::ClassNode::Member *member = &p_class->members[index];
@@ -145,6 +147,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName
member->type == GDScriptParser::ClassNode::Member::SIGNAL) {
return true;
}
+ if (p_member->type != GDScriptParser::Node::FUNCTION && member->type == GDScriptParser::ClassNode::Member::FUNCTION) {
+ return true;
+ }
}
return false;
@@ -160,6 +165,9 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_native_type(const StringName
if (ClassDB::has_integer_constant(p_native_type_string, p_member_name)) {
return true;
}
+ if (p_member_name == CoreStringNames::get_singleton()->_script) {
+ return true;
+ }
return false;
}
@@ -187,14 +195,15 @@ Error GDScriptAnalyzer::check_class_member_name_conflict(const GDScriptParser::C
const GDScriptParser::DataType *current_data_type = &p_class_node->base_type;
while (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::CLASS) {
GDScriptParser::ClassNode *current_class_node = current_data_type->class_type;
- if (has_member_name_conflict_in_script_class(p_member_name, current_class_node)) {
- push_error(vformat(R"(The member "%s" already exists in a parent class.)", p_member_name),
+ if (has_member_name_conflict_in_script_class(p_member_name, current_class_node, p_member_node)) {
+ push_error(vformat(R"(The member "%s" already exists in parent class %s.)", p_member_name, current_class_node->identifier->name),
p_member_node);
return ERR_PARSE_ERROR;
}
current_data_type = &current_class_node->base_type;
}
+ // No need for native class recursion because Node exposes all Object's properties.
if (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::NATIVE) {
if (current_data_type->native_type != StringName()) {
return check_native_member_name_conflict(
@@ -213,16 +222,6 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
return OK;
}
- if (p_class == parser->head) {
- if (p_class->identifier) {
- p_class->fqcn = p_class->identifier->name;
- } else {
- p_class->fqcn = parser->script_path;
- }
- } else {
- p_class->fqcn = p_class->outer->fqcn + "::" + String(p_class->identifier->name);
- }
-
if (p_class->identifier) {
StringName class_name = p_class->identifier->name;
if (class_exists(class_name)) {
@@ -2922,7 +2921,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
base_class = base_class->base_type.class_type;
}
- // Check native members.
+ // Check native members. No need for native class recursion because Node exposes all Object's properties.
const StringName &native = base.native_type;
if (class_exists(native)) {
@@ -3113,7 +3112,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
GDScriptParser::DataType result;
result.kind = GDScriptParser::DataType::NATIVE;
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
- if (autoload.path.to_lower().ends_with(GDScriptLanguage::get_singleton()->get_extension())) {
+ if (ResourceLoader::get_resource_type(autoload.path) == "GDScript") {
Ref<GDScriptParserRef> singl_parser = get_parser_for(autoload.path);
if (singl_parser.is_valid()) {
Error err = singl_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
@@ -3246,9 +3245,28 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
}
} else {
// TODO: Don't load if validating: use completion cache.
- p_preload->resource = ResourceLoader::load(p_preload->resolved_path);
- if (p_preload->resource.is_null()) {
- push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
+
+ // Must load GDScript and PackedScenes separately to permit cyclic references
+ // as ResourceLoader::load() detect and reject those.
+ if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "GDScript") {
+ Error err = OK;
+ Ref<GDScript> res = GDScriptCache::get_shallow_script(p_preload->resolved_path, err, parser->script_path);
+ p_preload->resource = res;
+ if (err != OK) {
+ push_error(vformat(R"(Could not preload resource script "%s".)", p_preload->resolved_path), p_preload->path);
+ }
+ } else if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "PackedScene") {
+ Error err = OK;
+ Ref<PackedScene> res = GDScriptCache::get_packed_scene(p_preload->resolved_path, err, parser->script_path);
+ p_preload->resource = res;
+ if (err != OK) {
+ push_error(vformat(R"(Could not preload resource scene "%s".)", p_preload->resolved_path), p_preload->path);
+ }
+ } else {
+ p_preload->resource = ResourceLoader::load(p_preload->resolved_path);
+ if (p_preload->resource.is_null()) {
+ push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
+ }
}
}
}
@@ -3290,6 +3308,17 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
// Just try to get it.
bool valid = false;
Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid);
+
+ // If it's a GDScript instance, try to get the full script. Maybe it's not still completely loaded.
+ Ref<GDScript> gdscr = Ref<GDScript>(p_subscript->base->reduced_value);
+ if (!valid && gdscr.is_valid()) {
+ Error err = OK;
+ GDScriptCache::get_full_script(gdscr->get_path(), err);
+ if (err == OK) {
+ value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid);
+ }
+ }
+
if (!valid) {
push_error(vformat(R"(Cannot get member "%s" from "%s".)", p_subscript->attribute->name, p_subscript->base->reduced_value), p_subscript->index);
result_type.kind = GDScriptParser::DataType::VARIANT;
@@ -3672,50 +3701,43 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
scr = obj->get_script();
}
if (scr.is_valid()) {
- if (scr->is_valid()) {
- result.script_type = scr;
- result.script_path = scr->get_path();
- Ref<GDScript> gds = scr;
- if (gds.is_valid()) {
- result.kind = GDScriptParser::DataType::CLASS;
- // This might be an inner class, so we want to get the parser for the root.
- // But still get the inner class from that tree.
- GDScript *current = gds.ptr();
- List<StringName> class_chain;
- while (current->_owner) {
- // Push to front so it's in reverse.
- class_chain.push_front(current->name);
- current = current->_owner;
- }
-
- Ref<GDScriptParserRef> ref = get_parser_for(current->get_path());
- if (ref.is_null()) {
- push_error("Could not find script in path.", p_source);
- GDScriptParser::DataType error_type;
- error_type.kind = GDScriptParser::DataType::VARIANT;
- return error_type;
- }
- ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
+ result.script_type = scr;
+ result.script_path = scr->get_path();
+ Ref<GDScript> gds = scr;
+ if (gds.is_valid()) {
+ result.kind = GDScriptParser::DataType::CLASS;
+ // This might be an inner class, so we want to get the parser for the root.
+ // But still get the inner class from that tree.
+ GDScript *current = gds.ptr();
+ List<StringName> class_chain;
+ while (current->_owner) {
+ // Push to front so it's in reverse.
+ class_chain.push_front(current->name);
+ current = current->_owner;
+ }
- GDScriptParser::ClassNode *found = ref->get_parser()->head;
+ Ref<GDScriptParserRef> ref = get_parser_for(current->get_path());
+ if (ref.is_null()) {
+ push_error("Could not find script in path.", p_source);
+ GDScriptParser::DataType error_type;
+ error_type.kind = GDScriptParser::DataType::VARIANT;
+ return error_type;
+ }
+ ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
- // It should be okay to assume this exists, since we have a complete script already.
- for (const StringName &E : class_chain) {
- found = found->get_member(E).m_class;
- }
+ GDScriptParser::ClassNode *found = ref->get_parser()->head;
- result.class_type = found;
- result.script_path = ref->get_parser()->script_path;
- } else {
- result.kind = GDScriptParser::DataType::SCRIPT;
+ // It should be okay to assume this exists, since we have a complete script already.
+ for (const StringName &E : class_chain) {
+ found = found->get_member(E).m_class;
}
- result.native_type = scr->get_instance_base_type();
+
+ result.class_type = found;
+ result.script_path = ref->get_parser()->script_path;
} else {
- push_error(vformat(R"(Constant value uses script from "%s" which is loaded but not compiled.)", scr->get_path()), p_source);
- result.kind = GDScriptParser::DataType::VARIANT;
- result.type_source = GDScriptParser::DataType::UNDETECTED;
- result.is_meta_type = false;
+ result.kind = GDScriptParser::DataType::SCRIPT;
}
+ result.native_type = scr->get_instance_base_type();
} else {
result.kind = GDScriptParser::DataType::NATIVE;
if (result.native_type == GDScriptNativeClass::get_class_static()) {
diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h
index 217a856ce0..23a3ad39a5 100644
--- a/modules/gdscript/gdscript_analyzer.h
+++ b/modules/gdscript/gdscript_analyzer.h
@@ -45,7 +45,7 @@ class GDScriptAnalyzer {
List<GDScriptParser::LambdaNode *> lambda_stack;
// Tests for detecting invalid overloading of script members
- static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node);
+ static _FORCE_INLINE_ bool has_member_name_conflict_in_script_class(const StringName &p_name, const GDScriptParser::ClassNode *p_current_class_node, const GDScriptParser::Node *p_member);
static _FORCE_INLINE_ bool has_member_name_conflict_in_native_type(const StringName &p_name, const StringName &p_native_type_string);
Error check_native_member_name_conflict(const StringName &p_member_name, const GDScriptParser::Node *p_member_node, const StringName &p_native_type_string);
Error check_class_member_name_conflict(const GDScriptParser::ClassNode *p_class_node, const StringName &p_member_name, const GDScriptParser::Node *p_member_node);
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 271296c2f9..add36591f3 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -34,7 +34,9 @@
#include "core/templates/vector.h"
#include "gdscript.h"
#include "gdscript_analyzer.h"
+#include "gdscript_compiler.h"
#include "gdscript_parser.h"
+#include "scene/resources/packed_scene.h"
bool GDScriptParserRef::is_valid() const {
return parser != nullptr;
@@ -95,27 +97,88 @@ Error GDScriptParserRef::raise_status(Status p_new_status) {
return result;
}
-GDScriptParserRef::~GDScriptParserRef() {
+void GDScriptParserRef::clear() {
+ if (cleared) {
+ return;
+ }
+ cleared = true;
+
if (parser != nullptr) {
memdelete(parser);
}
+
if (analyzer != nullptr) {
memdelete(analyzer);
}
- MutexLock lock(GDScriptCache::singleton->lock);
+}
+
+GDScriptParserRef::~GDScriptParserRef() {
+ clear();
+
+ MutexLock lock(GDScriptCache::singleton->mutex);
GDScriptCache::singleton->parser_map.erase(path);
}
GDScriptCache *GDScriptCache::singleton = nullptr;
+void GDScriptCache::move_script(const String &p_from, const String &p_to) {
+ if (singleton == nullptr || p_from == p_to) {
+ return;
+ }
+
+ MutexLock lock(singleton->mutex);
+
+ for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) {
+ if (E.value.has(p_from)) {
+ E.value.insert(p_to);
+ E.value.erase(p_from);
+ }
+ }
+
+ if (singleton->parser_map.has(p_from) && !p_from.is_empty()) {
+ singleton->parser_map[p_to] = singleton->parser_map[p_from];
+ }
+ singleton->parser_map.erase(p_from);
+
+ if (singleton->shallow_gdscript_cache.has(p_from) && !p_from.is_empty()) {
+ singleton->shallow_gdscript_cache[p_to] = singleton->shallow_gdscript_cache[p_from];
+ }
+ singleton->shallow_gdscript_cache.erase(p_from);
+
+ if (singleton->full_gdscript_cache.has(p_from) && !p_from.is_empty()) {
+ singleton->full_gdscript_cache[p_to] = singleton->full_gdscript_cache[p_from];
+ }
+ singleton->full_gdscript_cache.erase(p_from);
+}
+
void GDScriptCache::remove_script(const String &p_path) {
- MutexLock lock(singleton->lock);
+ if (singleton == nullptr) {
+ return;
+ }
+
+ MutexLock lock(singleton->mutex);
+
+ for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) {
+ if (!E.value.has(p_path)) {
+ continue;
+ }
+ E.value.erase(p_path);
+ }
+
+ GDScriptCache::clear_unreferenced_packed_scenes();
+
+ if (singleton->parser_map.has(p_path)) {
+ singleton->parser_map[p_path]->clear();
+ singleton->parser_map.erase(p_path);
+ }
+
+ singleton->dependencies.erase(p_path);
singleton->shallow_gdscript_cache.erase(p_path);
singleton->full_gdscript_cache.erase(p_path);
}
Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptParserRef::Status p_status, Error &r_error, const String &p_owner) {
- MutexLock lock(singleton->lock);
+ MutexLock lock(singleton->mutex);
Ref<GDScriptParserRef> ref;
if (!p_owner.is_empty()) {
singleton->dependencies[p_owner].insert(p_path);
@@ -161,8 +224,8 @@ String GDScriptCache::get_source_code(const String &p_path) {
return source;
}
-Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const String &p_owner) {
- MutexLock lock(singleton->lock);
+Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, Error &r_error, const String &p_owner) {
+ MutexLock lock(singleton->mutex);
if (!p_owner.is_empty()) {
singleton->dependencies[p_owner].insert(p_path);
}
@@ -176,15 +239,19 @@ Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const Stri
Ref<GDScript> script;
script.instantiate();
script->set_path(p_path, true);
- script->set_script_path(p_path);
script->load_source_code(p_path);
- singleton->shallow_gdscript_cache[p_path] = script.ptr();
+ Ref<GDScriptParserRef> parser_ref = get_parser(p_path, GDScriptParserRef::PARSED, r_error);
+ if (r_error == OK) {
+ GDScriptCompiler::make_scripts(script.ptr(), parser_ref->get_parser()->get_tree(), true);
+ }
+
+ singleton->shallow_gdscript_cache[p_path] = script;
return script;
}
Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner, bool p_update_from_disk) {
- MutexLock lock(singleton->lock);
+ MutexLock lock(singleton->mutex);
if (!p_owner.is_empty()) {
singleton->dependencies[p_owner].insert(p_path);
@@ -200,31 +267,53 @@ Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_erro
}
if (script.is_null()) {
- script = get_shallow_script(p_path);
- ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>());
+ script = get_shallow_script(p_path, r_error);
+ if (r_error) {
+ return script;
+ }
}
- r_error = script->load_source_code(p_path);
+ if (p_update_from_disk) {
+ r_error = script->load_source_code(p_path);
+ }
if (r_error) {
return script;
}
- r_error = script->reload();
+ singleton->full_gdscript_cache[p_path] = script;
+ singleton->shallow_gdscript_cache.erase(p_path);
+
+ r_error = script->reload(true);
if (r_error) {
+ singleton->shallow_gdscript_cache[p_path] = script;
+ singleton->full_gdscript_cache.erase(p_path);
return script;
}
- singleton->full_gdscript_cache[p_path] = script.ptr();
- singleton->shallow_gdscript_cache.erase(p_path);
-
return script;
}
+Ref<GDScript> GDScriptCache::get_cached_script(const String &p_path) {
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->full_gdscript_cache.has(p_path)) {
+ return singleton->full_gdscript_cache[p_path];
+ }
+
+ if (singleton->shallow_gdscript_cache.has(p_path)) {
+ return singleton->shallow_gdscript_cache[p_path];
+ }
+
+ return Ref<GDScript>();
+}
+
Error GDScriptCache::finish_compiling(const String &p_owner) {
+ MutexLock lock(singleton->mutex);
+
// Mark this as compiled.
- Ref<GDScript> script = get_shallow_script(p_owner);
- singleton->full_gdscript_cache[p_owner] = script.ptr();
+ Ref<GDScript> script = get_cached_script(p_owner);
+ singleton->full_gdscript_cache[p_owner] = script;
singleton->shallow_gdscript_cache.erase(p_owner);
HashSet<String> depends = singleton->dependencies[p_owner];
@@ -245,13 +334,73 @@ Error GDScriptCache::finish_compiling(const String &p_owner) {
return err;
}
+Ref<PackedScene> GDScriptCache::get_packed_scene(const String &p_path, Error &r_error, const String &p_owner) {
+ MutexLock lock(singleton->mutex);
+
+ if (singleton->packed_scene_cache.has(p_path)) {
+ singleton->packed_scene_dependencies[p_path].insert(p_owner);
+ return singleton->packed_scene_cache[p_path];
+ }
+
+ Ref<PackedScene> scene;
+ scene.instantiate();
+
+ r_error = OK;
+ if (p_path.is_empty()) {
+ r_error = ERR_FILE_BAD_PATH;
+ return scene;
+ }
+
+ scene->set_path(p_path);
+ singleton->packed_scene_cache[p_path] = scene;
+ singleton->packed_scene_dependencies[p_path].insert(p_owner);
+
+ scene->recreate_state();
+ scene->reload_from_file();
+ return scene;
+}
+
+void GDScriptCache::clear_unreferenced_packed_scenes() {
+ if (singleton == nullptr) {
+ return;
+ }
+
+ MutexLock lock(singleton->mutex);
+
+ for (KeyValue<String, HashSet<String>> &E : singleton->packed_scene_dependencies) {
+ if (E.value.size() > 0 || !ResourceLoader::is_imported(E.key)) {
+ continue;
+ }
+
+ singleton->packed_scene_dependencies.erase(E.key);
+ singleton->packed_scene_cache.erase(E.key);
+ }
+}
+
GDScriptCache::GDScriptCache() {
singleton = this;
}
GDScriptCache::~GDScriptCache() {
+ destructing = true;
+
+ RBSet<Ref<GDScriptParserRef>> parser_map_refs;
+ for (KeyValue<String, GDScriptParserRef *> &E : parser_map) {
+ parser_map_refs.insert(E.value);
+ }
+
+ for (Ref<GDScriptParserRef> &E : parser_map_refs) {
+ if (E.is_valid())
+ E->clear();
+ }
+
+ parser_map_refs.clear();
parser_map.clear();
shallow_gdscript_cache.clear();
full_gdscript_cache.clear();
+
+ packed_scene_cache.clear();
+ packed_scene_dependencies.clear();
+
singleton = nullptr;
}
diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h
index 3d111ea229..2195932aa3 100644
--- a/modules/gdscript/gdscript_cache.h
+++ b/modules/gdscript/gdscript_cache.h
@@ -36,6 +36,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/hash_set.h"
#include "gdscript.h"
+#include "scene/resources/packed_scene.h"
class GDScriptAnalyzer;
class GDScriptParser;
@@ -56,6 +57,7 @@ private:
Status status = EMPTY;
Error result = OK;
String path;
+ bool cleared = false;
friend class GDScriptCache;
@@ -64,6 +66,7 @@ public:
Status get_status() const;
GDScriptParser *get_parser() const;
Error raise_status(Status p_new_status);
+ void clear();
GDScriptParserRef() {}
~GDScriptParserRef();
@@ -72,25 +75,42 @@ public:
class GDScriptCache {
// String key is full path.
HashMap<String, GDScriptParserRef *> parser_map;
- HashMap<String, GDScript *> shallow_gdscript_cache;
- HashMap<String, GDScript *> full_gdscript_cache;
+ HashMap<String, Ref<GDScript>> shallow_gdscript_cache;
+ HashMap<String, Ref<GDScript>> full_gdscript_cache;
HashMap<String, HashSet<String>> dependencies;
+ HashMap<String, Ref<PackedScene>> packed_scene_cache;
+ HashMap<String, HashSet<String>> packed_scene_dependencies;
friend class GDScript;
friend class GDScriptParserRef;
+ friend class GDScriptInstance;
static GDScriptCache *singleton;
- Mutex lock;
- static void remove_script(const String &p_path);
+ bool destructing = false;
+
+ Mutex mutex;
public:
+ static void move_script(const String &p_from, const String &p_to);
+ static void remove_script(const String &p_path);
static Ref<GDScriptParserRef> get_parser(const String &p_path, GDScriptParserRef::Status status, Error &r_error, const String &p_owner = String());
static String get_source_code(const String &p_path);
- static Ref<GDScript> get_shallow_script(const String &p_path, const String &p_owner = String());
+ static Ref<GDScript> get_shallow_script(const String &p_path, Error &r_error, const String &p_owner = String());
static Ref<GDScript> get_full_script(const String &p_path, Error &r_error, const String &p_owner = String(), bool p_update_from_disk = false);
+ static Ref<GDScript> get_cached_script(const String &p_path);
static Error finish_compiling(const String &p_owner);
+ static Ref<PackedScene> get_packed_scene(const String &p_path, Error &r_error, const String &p_owner = "");
+ static void clear_unreferenced_packed_scenes();
+
+ static bool is_destructing() {
+ if (singleton == nullptr) {
+ return true;
+ }
+ return singleton->destructing;
+ };
+
GDScriptCache();
~GDScriptCache();
};
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index fd13edc4cf..f0ceb42f89 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -80,7 +80,7 @@ void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::N
}
}
-GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner) const {
+GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner) {
if (!p_datatype.is_set() || !p_datatype.is_hard_type()) {
return GDScriptDataType();
}
@@ -103,75 +103,46 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
} break;
case GDScriptParser::DataType::SCRIPT: {
result.kind = GDScriptDataType::SCRIPT;
- result.script_type_ref = Ref<Script>(p_datatype.script_type);
+ result.builtin_type = p_datatype.builtin_type;
+ result.script_type_ref = p_datatype.script_type;
result.script_type = result.script_type_ref.ptr();
- result.native_type = result.script_type->get_instance_base_type();
+ result.native_type = p_datatype.native_type;
} break;
case GDScriptParser::DataType::CLASS: {
- // Locate class by constructing the path to it and following that path.
- GDScriptParser::ClassNode *class_type = p_datatype.class_type;
- if (class_type) {
- result.kind = GDScriptDataType::GDSCRIPT;
- result.builtin_type = p_datatype.builtin_type;
-
- String class_name = class_type->fqcn.split("::")[0];
- const bool is_inner_by_path = (!main_script->path.is_empty()) && (class_name == main_script->path);
- const bool is_inner_by_name = (!main_script->name.is_empty()) && (class_name == main_script->name);
- if (is_inner_by_path || is_inner_by_name) {
- // Local class.
- List<StringName> names;
- while (class_type->outer) {
- names.push_back(class_type->identifier->name);
- class_type = class_type->outer;
- }
+ result.kind = GDScriptDataType::GDSCRIPT;
+ result.builtin_type = p_datatype.builtin_type;
+ result.native_type = p_datatype.native_type;
- Ref<GDScript> script = Ref<GDScript>(main_script);
- while (names.back()) {
- if (!script->subclasses.has(names.back()->get())) {
- ERR_PRINT("Parser bug: Cannot locate datatype class.");
- result.has_type = false;
- return GDScriptDataType();
- }
- script = script->subclasses[names.back()->get()];
- names.pop_back();
- }
- result.script_type = script.ptr();
- result.native_type = script->get_instance_base_type();
- } else {
- // Inner class.
- PackedStringArray classes = class_type->fqcn.split("::");
- if (!classes.is_empty()) {
- for (GDScript *script : parsed_classes) {
- // Checking of inheritance structure of inner class to find a correct script link.
- if (script->name == classes[classes.size() - 1]) {
- PackedStringArray classes2 = script->fully_qualified_name.split("::");
- bool valid = true;
- if (classes.size() != classes2.size()) {
- valid = false;
- } else {
- for (int i = 0; i < classes.size(); i++) {
- if (classes[i] != classes2[i]) {
- valid = false;
- break;
- }
- }
- }
- if (!valid) {
- continue;
- }
- result.script_type_ref = Ref<GDScript>(script);
- break;
- }
- }
- }
- if (result.script_type_ref.is_null()) {
- result.script_type_ref = GDScriptCache::get_shallow_script(p_datatype.script_path, main_script->path);
- }
+ String root_name = p_datatype.class_type->fqcn.get_slice("::", 0);
+ bool is_local_class = !root_name.is_empty() && root_name == main_script->fully_qualified_name;
- result.script_type = result.script_type_ref.ptr();
- result.native_type = p_datatype.native_type;
+ Ref<GDScript> script;
+ if (is_local_class) {
+ script = Ref<GDScript>(main_script);
+ } else {
+ Error err = OK;
+ script = GDScriptCache::get_shallow_script(p_datatype.script_path, err, p_owner->path);
+ if (err) {
+ _set_error(vformat(R"(Could not find script "%s": %s)", p_datatype.script_path, error_names[err]), nullptr);
}
}
+
+ if (script.is_valid()) {
+ script = Ref<GDScript>(script->find_class(p_datatype.class_type->fqcn));
+ }
+
+ if (script.is_null()) {
+ _set_error(vformat(R"(Could not find class "%s" in "%s".)", p_datatype.class_type->fqcn, p_datatype.script_path), nullptr);
+ return GDScriptDataType();
+ } else {
+ // Only hold a strong reference if the owner of the element qualified with this type is not local, to avoid cyclic references (leaks).
+ // TODO: Might lead to use after free if script_type is a subclass and is used after its parent is freed.
+ if (!is_local_class) {
+ result.script_type_ref = script;
+ }
+ result.script_type = script.ptr();
+ result.native_type = p_datatype.native_type;
+ }
} break;
case GDScriptParser::DataType::ENUM:
result.has_type = true;
@@ -189,13 +160,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
}
if (p_datatype.has_container_element_type()) {
- result.set_container_element_type(_gdtype_from_datatype(p_datatype.get_container_element_type()));
- }
-
- // Only hold strong reference to the script if it's not the owner of the
- // element qualified with this type, to avoid cyclic references (leaks).
- if (result.script_type && result.script_type == p_owner) {
- result.script_type_ref = Ref<Script>();
+ result.set_container_element_type(_gdtype_from_datatype(p_datatype.get_container_element_type(), p_owner));
}
return result;
@@ -367,7 +332,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// This is so one autoload doesn't try to load another before it's compiled.
HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
if (autoloads.has(identifier) && autoloads[identifier].is_singleton) {
- GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype()));
+ GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype(), codegen.script));
int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
gen->write_store_global(global, idx);
return global;
@@ -390,11 +355,22 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
if (class_node->identifier && class_node->identifier->name == identifier) {
res = Ref<GDScript>(main_script);
} else {
- res = ResourceLoader::load(ScriptServer::get_global_class_path(identifier));
- if (res.is_null()) {
- _set_error("Can't load global class " + String(identifier) + ", cyclic reference?", p_expression);
- r_error = ERR_COMPILATION_FAILED;
- return GDScriptCodeGenerator::Address();
+ String global_class_path = ScriptServer::get_global_class_path(identifier);
+ if (ResourceLoader::get_resource_type(global_class_path) == "GDScript") {
+ Error err = OK;
+ res = GDScriptCache::get_full_script(global_class_path, err);
+ if (err != OK) {
+ _set_error("Can't load global class " + String(identifier), p_expression);
+ r_error = ERR_COMPILATION_FAILED;
+ return GDScriptCodeGenerator::Address();
+ }
+ } else {
+ res = ResourceLoader::load(global_class_path);
+ if (res.is_null()) {
+ _set_error("Can't load global class " + String(identifier) + ", cyclic reference?", p_expression);
+ r_error = ERR_COMPILATION_FAILED;
+ return GDScriptCodeGenerator::Address();
+ }
}
}
@@ -434,7 +410,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
Vector<GDScriptCodeGenerator::Address> values;
// Create the result temporary first since it's the last to be killed.
- GDScriptDataType array_type = _gdtype_from_datatype(an->get_datatype());
+ GDScriptDataType array_type = _gdtype_from_datatype(an->get_datatype(), codegen.script);
GDScriptCodeGenerator::Address result = codegen.add_temporary(array_type);
for (int i = 0; i < an->elements.size(); i++) {
@@ -511,7 +487,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::CAST: {
const GDScriptParser::CastNode *cn = static_cast<const GDScriptParser::CastNode *>(p_expression);
GDScriptParser::DataType og_cast_type = cn->cast_type->get_datatype();
- GDScriptDataType cast_type = _gdtype_from_datatype(og_cast_type);
+ GDScriptDataType cast_type = _gdtype_from_datatype(og_cast_type, codegen.script);
if (og_cast_type.kind == GDScriptParser::DataType::ENUM) {
// Enum types are usually treated as dictionaries, but in this case we want to cast to an integer.
@@ -534,7 +510,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
} break;
case GDScriptParser::Node::CALL: {
const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(p_expression);
- GDScriptDataType type = _gdtype_from_datatype(call->get_datatype());
+ GDScriptDataType type = _gdtype_from_datatype(call->get_datatype(), codegen.script);
GDScriptCodeGenerator::Address result = codegen.add_temporary(type);
GDScriptCodeGenerator::Address nil = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::NIL);
@@ -670,7 +646,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
Vector<GDScriptCodeGenerator::Address> args;
args.push_back(codegen.add_constant(NodePath(get_node->full_path)));
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype(), codegen.script));
MethodBind *get_node_method = ClassDB::get_method("Node", "get_node");
gen->write_call_ptrcall(result, GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), get_node_method, args);
@@ -686,7 +662,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::AWAIT: {
const GDScriptParser::AwaitNode *await = static_cast<const GDScriptParser::AwaitNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(p_expression->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(p_expression->get_datatype(), codegen.script));
within_await = true;
GDScriptCodeGenerator::Address argument = _parse_expression(codegen, r_error, await->to_await);
within_await = false;
@@ -705,7 +681,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// Indexing operator.
case GDScriptParser::Node::SUBSCRIPT: {
const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
if (r_error) {
@@ -735,7 +711,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// Remove result temp as we don't need it.
gen->pop_temporary();
// Faster than indexing self (as if no self. had been used).
- return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->get_datatype()));
+ return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->get_datatype(), codegen.script));
}
}
@@ -773,7 +749,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::UNARY_OPERATOR: {
const GDScriptParser::UnaryOpNode *unary = static_cast<const GDScriptParser::UnaryOpNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(unary->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(unary->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address operand = _parse_expression(codegen, r_error, unary->operand);
if (r_error) {
@@ -791,7 +767,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::BINARY_OPERATOR: {
const GDScriptParser::BinaryOpNode *binary = static_cast<const GDScriptParser::BinaryOpNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(binary->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(binary->get_datatype(), codegen.script));
switch (binary->operation) {
case GDScriptParser::BinaryOpNode::OP_LOGIC_AND: {
@@ -867,7 +843,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::TERNARY_OPERATOR: {
// x IF a ELSE y operator with early out on failure.
const GDScriptParser::TernaryOpNode *ternary = static_cast<const GDScriptParser::TernaryOpNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(ternary->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(ternary->get_datatype(), codegen.script));
gen->write_start_ternary(result);
@@ -985,7 +961,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
break;
}
const GDScriptParser::SubscriptNode *subscript_elem = E->get();
- GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript_elem->get_datatype()));
+ GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript_elem->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address key;
StringName name;
@@ -1024,8 +1000,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// Perform operator if any.
if (assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) {
- GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype()));
- GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype()));
+ GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
+ GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype(), codegen.script));
if (subscript->is_attribute) {
gen->write_get_named(value, name, prev_base);
} else {
@@ -1130,8 +1106,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
StringName name = static_cast<GDScriptParser::IdentifierNode *>(assignment->assignee)->name;
if (has_operation) {
- GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype()));
- GDScriptCodeGenerator::Address member = codegen.add_temporary(_gdtype_from_datatype(assignment->assignee->get_datatype()));
+ GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
+ GDScriptCodeGenerator::Address member = codegen.add_temporary(_gdtype_from_datatype(assignment->assignee->get_datatype(), codegen.script));
gen->write_get_member(member, name);
gen->write_binary_operator(op_result, assignment->variant_op, member, assigned_value);
gen->pop_temporary(); // Pop member temp.
@@ -1184,7 +1160,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
bool has_operation = assignment->operation != GDScriptParser::AssignmentNode::OP_NONE;
if (has_operation) {
// Perform operation.
- GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype()));
+ GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address og_value = _parse_expression(codegen, r_error, assignment->assignee);
gen->write_binary_operator(op_result, assignment->variant_op, og_value, assigned_value);
to_assign = op_result;
@@ -1196,7 +1172,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
to_assign = assigned_value;
}
- GDScriptDataType assign_type = _gdtype_from_datatype(assignment->assignee->get_datatype());
+ GDScriptDataType assign_type = _gdtype_from_datatype(assignment->assignee->get_datatype(), codegen.script);
if (has_setter && !is_in_setter) {
// Call setter.
@@ -1226,7 +1202,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
} break;
case GDScriptParser::Node::LAMBDA: {
const GDScriptParser::LambdaNode *lambda = static_cast<const GDScriptParser::LambdaNode *>(p_expression);
- GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(lambda->get_datatype()));
+ GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(lambda->get_datatype(), codegen.script));
Vector<GDScriptCodeGenerator::Address> captures;
captures.resize(lambda->captures.size());
@@ -1645,7 +1621,7 @@ void GDScriptCompiler::_add_locals_in_block(CodeGen &codegen, const GDScriptPars
// Parameters are added directly from function and loop variables are declared explicitly.
continue;
}
- codegen.add_local(p_block->locals[i].name, _gdtype_from_datatype(p_block->locals[i].get_datatype()));
+ codegen.add_local(p_block->locals[i].name, _gdtype_from_datatype(p_block->locals[i].get_datatype(), codegen.script));
}
}
@@ -1675,7 +1651,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
codegen.start_block();
// Evaluate the match expression.
- GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype()));
+ GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, err, match->test);
if (err) {
return err;
@@ -1784,9 +1760,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
const GDScriptParser::ForNode *for_n = static_cast<const GDScriptParser::ForNode *>(s);
codegen.start_block();
- GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->get_datatype()));
+ GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->get_datatype(), codegen.script));
- gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype()));
+ gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address list = _parse_expression(codegen, err, for_n->list);
if (err) {
@@ -1897,13 +1873,13 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
const GDScriptParser::VariableNode *lv = static_cast<const GDScriptParser::VariableNode *>(s);
// Should be already in stack when the block began.
GDScriptCodeGenerator::Address local = codegen.locals[lv->identifier->name];
- GDScriptParser::DataType local_type = lv->get_datatype();
+ GDScriptDataType local_type = _gdtype_from_datatype(lv->get_datatype(), codegen.script);
if (lv->initializer != nullptr) {
// For typed arrays we need to make sure this is already initialized correctly so typed assignment work.
- if (local_type.is_hard_type() && local_type.builtin_type == Variant::ARRAY) {
+ if (local_type.has_type && local_type.builtin_type == Variant::ARRAY) {
if (local_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(local, _gdtype_from_datatype(local_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
+ codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
} else {
codegen.generator->write_construct_array(local, Vector<GDScriptCodeGenerator::Address>());
}
@@ -1920,11 +1896,11 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
- } else if (lv->get_datatype().is_hard_type()) {
+ } else if (local_type.has_type) {
// Initialize with default for type.
if (local_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(local, _gdtype_from_datatype(local_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
- } else if (local_type.kind == GDScriptParser::DataType::BUILTIN) {
+ codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
+ } else if (local_type.kind == GDScriptDataType::BUILTIN) {
codegen.generator->write_construct(local, local_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
}
// The `else` branch is for objects, in such case we leave it as `null`.
@@ -2033,17 +2009,17 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
continue;
}
- GDScriptParser::DataType field_type = field->get_datatype();
+ GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script);
- GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, _gdtype_from_datatype(field->get_datatype()));
+ GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, field_type);
if (field->initializer) {
// Emit proper line change.
codegen.generator->write_newline(field->initializer->start_line);
// For typed arrays we need to make sure this is already initialized correctly so typed assignment work.
- if (field_type.is_hard_type() && field_type.builtin_type == Variant::ARRAY) {
+ if (field_type.has_type && field_type.builtin_type == Variant::ARRAY) {
if (field_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(dst_address, _gdtype_from_datatype(field_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
+ codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
} else {
codegen.generator->write_construct_array(dst_address, Vector<GDScriptCodeGenerator::Address>());
}
@@ -2062,13 +2038,13 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
- } else if (field->get_datatype().is_hard_type()) {
+ } else if (field_type.has_type) {
codegen.generator->write_newline(field->start_line);
// Initialize with default for type.
if (field_type.has_container_element_type()) {
- codegen.generator->write_construct_typed_array(dst_address, _gdtype_from_datatype(field_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>());
- } else if (field_type.kind == GDScriptParser::DataType::BUILTIN) {
+ codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
+ } else if (field_type.kind == GDScriptDataType::BUILTIN) {
codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
}
// The `else` branch is for objects, in such case we leave it as `null`.
@@ -2195,23 +2171,20 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP
return err;
}
-Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
- parsing_classes.insert(p_script);
+Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+ if (parsed_classes.has(p_script)) {
+ return OK;
+ }
- if (p_class->outer && p_class->outer->outer) {
- // Owner is not root
- if (!parsed_classes.has(p_script->_owner)) {
- if (parsing_classes.has(p_script->_owner)) {
- _set_error("Cyclic class reference for '" + String(p_class->identifier->name) + "'.", p_class);
- return ERR_PARSE_ERROR;
- }
- Error err = _parse_class_level(p_script->_owner, p_class->outer, p_keep_state);
- if (err) {
- return err;
- }
- }
+ if (parsing_classes.has(p_script)) {
+ String class_name = p_class->identifier ? String(p_class->identifier->name) : p_class->fqcn;
+ _set_error(vformat(R"(Cyclic class reference for "%s".)", class_name), p_class);
+ return ERR_PARSE_ERROR;
}
+ parsing_classes.insert(p_script);
+
+ p_script->clearing = true;
#ifdef TOOLS_ENABLED
p_script->doc_functions.clear();
p_script->doc_variables.clear();
@@ -2234,10 +2207,24 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
p_script->base = Ref<GDScript>();
p_script->_base = nullptr;
p_script->members.clear();
+
+ // This makes possible to clear script constants and member_functions without heap-use-after-free errors.
+ HashMap<StringName, Variant> constants;
+ for (const KeyValue<StringName, Variant> &E : p_script->constants) {
+ constants.insert(E.key, E.value);
+ }
p_script->constants.clear();
+ constants.clear();
+ HashMap<StringName, GDScriptFunction *> member_functions;
for (const KeyValue<StringName, GDScriptFunction *> &E : p_script->member_functions) {
+ member_functions.insert(E.key, E.value);
+ }
+ p_script->member_functions.clear();
+ for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
memdelete(E.value);
}
+ member_functions.clear();
+
if (p_script->implicit_initializer) {
memdelete(p_script->implicit_initializer);
}
@@ -2252,8 +2239,9 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
p_script->implicit_initializer = nullptr;
p_script->implicit_ready = nullptr;
+ p_script->clearing = false;
+
p_script->tool = parser->is_tool();
- p_script->name = p_class->identifier ? p_class->identifier->name : "";
if (!p_script->name.is_empty()) {
if (ClassDB::class_exists(p_script->name) && ClassDB::is_class_exposed(p_script->name)) {
@@ -2262,53 +2250,50 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
}
}
- Ref<GDScriptNativeClass> native;
+ GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type, p_script);
- GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type);
// Inheritance
switch (base_type.kind) {
case GDScriptDataType::NATIVE: {
int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[base_type.native_type];
- native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
- ERR_FAIL_COND_V(native.is_null(), ERR_BUG);
- p_script->native = native;
+ p_script->native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
+ ERR_FAIL_COND_V(p_script->native.is_null(), ERR_BUG);
} break;
case GDScriptDataType::GDSCRIPT: {
Ref<GDScript> base = Ref<GDScript>(base_type.script_type);
- p_script->base = base;
- p_script->_base = base.ptr();
+ if (base.is_null()) {
+ return ERR_COMPILATION_FAILED;
+ }
- if (p_class->base_type.kind == GDScriptParser::DataType::CLASS && p_class->base_type.class_type != nullptr) {
- if (p_class->base_type.script_path == main_script->path) {
- if (!parsed_classes.has(p_script->_base)) {
- if (parsing_classes.has(p_script->_base)) {
- String class_name = p_class->identifier ? p_class->identifier->name : "<main>";
- _set_error("Cyclic class reference for '" + class_name + "'.", p_class);
- return ERR_PARSE_ERROR;
- }
- Error err = _parse_class_level(p_script->_base, p_class->base_type.class_type, p_keep_state);
- if (err) {
- return err;
- }
- }
- } else {
- Error err = OK;
- base = GDScriptCache::get_full_script(p_class->base_type.script_path, err, main_script->path);
- if (err) {
- return err;
- }
- if (base.is_null() || !base->is_valid()) {
- return ERR_COMPILATION_FAILED;
- }
+ if (base.ptr() == main_script || main_script->is_subclass(base.ptr())) {
+ Error err = _populate_class_members(base.ptr(), p_class->base_type.class_type, p_keep_state);
+ if (err) {
+ return err;
}
+ } else if (!base->is_valid()) {
+ Error err = OK;
+ Ref<GDScript> base_root = GDScriptCache::get_full_script(base->path, err, p_script->path);
+ if (err) {
+ _set_error(vformat(R"(Could not compile base class "%s" from "%s": %s)", base->fully_qualified_name, base->path, error_names[err]), nullptr);
+ return err;
+ }
+ if (base_root.is_valid()) {
+ base = Ref<GDScript>(base_root->find_class(base->fully_qualified_name));
+ }
+ if (base.is_null()) {
+ _set_error(vformat(R"(Could not find class "%s" in "%s".)", base->fully_qualified_name, base->path), nullptr);
+ return ERR_COMPILATION_FAILED;
+ }
+ ERR_FAIL_COND_V(!base->is_valid(), ERR_BUG);
}
+ p_script->base = base;
+ p_script->_base = base.ptr();
p_script->member_indices = base->member_indices;
- native = base->native;
- p_script->native = native;
+ p_script->native = base->native;
} break;
default: {
- _set_error("Parser bug: invalid inheritance.", p_class);
+ _set_error("Parser bug: invalid inheritance.", nullptr);
return ERR_BUG;
} break;
}
@@ -2478,8 +2463,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
parsed_classes.insert(p_script);
parsing_classes.erase(p_script);
- //parse sub-classes
-
+ // Populate sub-classes.
for (int i = 0; i < p_class->members.size(); i++) {
const GDScriptParser::ClassNode::Member &member = p_class->members[i];
if (member.type != member.CLASS) {
@@ -2491,27 +2475,24 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
GDScript *subclass_ptr = subclass.ptr();
// Subclass might still be parsing, just skip it
- if (!parsed_classes.has(subclass_ptr) && !parsing_classes.has(subclass_ptr)) {
- Error err = _parse_class_level(subclass_ptr, inner_class, p_keep_state);
+ if (!parsing_classes.has(subclass_ptr)) {
+ Error err = _populate_class_members(subclass_ptr, inner_class, p_keep_state);
if (err) {
return err;
}
}
#ifdef TOOLS_ENABLED
-
p_script->member_lines[name] = inner_class->start_line;
#endif
-
p_script->constants.insert(name, subclass); //once parsed, goes to the list of constants
}
return OK;
}
-Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
- //parse methods
-
+Error GDScriptCompiler::_compile_class(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+ // Compile member functions, getters, and setters.
for (int i = 0; i < p_class->members.size(); i++) {
const GDScriptParser::ClassNode::Member &member = p_class->members[i];
if (member.type == member.FUNCTION) {
@@ -2615,17 +2596,26 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
StringName name = inner_class->identifier->name;
GDScript *subclass = p_script->subclasses[name].ptr();
- Error err = _parse_class_blocks(subclass, inner_class, p_keep_state);
+ Error err = _compile_class(subclass, inner_class, p_keep_state);
if (err) {
return err;
}
}
+#ifdef TOOLS_ENABLED
+ p_script->_update_doc();
+#endif
+
+ p_script->_init_rpc_methods_properties();
+
p_script->valid = true;
return OK;
}
-void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+void GDScriptCompiler::make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+ p_script->fully_qualified_name = p_class->fqcn;
+ p_script->name = p_class->identifier ? p_class->identifier->name : "";
+
HashMap<StringName, Ref<GDScript>> old_subclasses;
if (p_keep_state) {
@@ -2642,24 +2632,22 @@ void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::C
StringName name = inner_class->identifier->name;
Ref<GDScript> subclass;
- String fully_qualified_name = p_script->fully_qualified_name + "::" + name;
if (old_subclasses.has(name)) {
subclass = old_subclasses[name];
} else {
- Ref<GDScript> orphan_subclass = GDScriptLanguage::get_singleton()->get_orphan_subclass(fully_qualified_name);
- if (orphan_subclass.is_valid()) {
- subclass = orphan_subclass;
- } else {
- subclass.instantiate();
- }
+ subclass = GDScriptLanguage::get_singleton()->get_orphan_subclass(inner_class->fqcn);
+ }
+
+ if (subclass.is_null()) {
+ subclass.instantiate();
}
subclass->_owner = p_script;
- subclass->fully_qualified_name = fully_qualified_name;
+ subclass->path = p_script->path;
p_script->subclasses.insert(name, subclass);
- _make_scripts(subclass.ptr(), inner_class, false);
+ make_scripts(subclass.ptr(), inner_class, p_keep_state);
}
}
@@ -2673,26 +2661,22 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri
source = p_script->get_path();
- // The best fully qualified name for a base level script is its file path
- p_script->fully_qualified_name = p_script->path;
-
// Create scripts for subclasses beforehand so they can be referenced
- _make_scripts(p_script, root, p_keep_state);
+ make_scripts(p_script, root, p_keep_state);
- p_script->_owner = nullptr;
- Error err = _parse_class_level(p_script, root, p_keep_state);
+ main_script->_owner = nullptr;
+ Error err = _populate_class_members(main_script, parser->get_tree(), p_keep_state);
if (err) {
return err;
}
- err = _parse_class_blocks(p_script, root, p_keep_state);
-
+ err = _compile_class(main_script, root, p_keep_state);
if (err) {
return err;
}
- return GDScriptCache::finish_compiling(p_script->get_path());
+ return GDScriptCache::finish_compiling(main_script->get_path());
}
String GDScriptCompiler::get_error() const {
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index e4264ea55b..45ca4fe342 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -121,7 +121,7 @@ class GDScriptCompiler {
Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::BinaryOpNode *on, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::ExpressionNode *p_left_operand, const GDScriptParser::ExpressionNode *p_right_operand, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
- GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner = nullptr) const;
+ GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner);
GDScriptCodeGenerator::Address _parse_assign_right_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::AssignmentNode *p_assignmentint, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
GDScriptCodeGenerator::Address _parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root = false, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address());
@@ -130,9 +130,8 @@ class GDScriptCompiler {
Error _parse_block(CodeGen &codegen, const GDScriptParser::SuiteNode *p_block, bool p_add_locals = true);
GDScriptFunction *_parse_function(Error &r_error, GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false, bool p_for_lambda = false);
Error _parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter);
- Error _parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- Error _parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- void _make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _populate_class_members(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _compile_class(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line = 0;
int err_column = 0;
StringName source;
@@ -140,6 +139,7 @@ class GDScriptCompiler {
bool within_await = false;
public:
+ static void make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false);
String get_error() const;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index f33d1409bc..48a6e3fb51 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2511,6 +2511,57 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
}
+static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::SubscriptNode *p_subscript, GDScriptParser::DataType &r_base_type, Variant *r_base = nullptr) {
+ if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
+ const GDScriptParser::GetNodeNode *get_node = nullptr;
+ const GDScriptParser::IdentifierNode *identifier_node = static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base);
+
+ switch (identifier_node->source) {
+ case GDScriptParser::IdentifierNode::Source::MEMBER_VARIABLE: {
+ if (p_context.current_class != nullptr) {
+ const StringName &member_name = identifier_node->name;
+ const GDScriptParser::ClassNode *current_class = p_context.current_class;
+
+ if (current_class->has_member(member_name)) {
+ const GDScriptParser::ClassNode::Member &member = current_class->get_member(member_name);
+
+ if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) {
+ const GDScriptParser::VariableNode *variable = static_cast<GDScriptParser::VariableNode *>(member.variable);
+
+ if (variable->initializer && variable->initializer->type == GDScriptParser::Node::GET_NODE) {
+ get_node = static_cast<GDScriptParser::GetNodeNode *>(variable->initializer);
+ }
+ }
+ }
+ }
+ } break;
+ case GDScriptParser::IdentifierNode::Source::LOCAL_VARIABLE: {
+ if (identifier_node->next != nullptr && identifier_node->next->type == GDScriptParser::ClassNode::Node::GET_NODE) {
+ get_node = static_cast<GDScriptParser::GetNodeNode *>(identifier_node->next);
+ }
+ } break;
+ default:
+ break;
+ }
+
+ if (get_node != nullptr) {
+ const Object *node = p_context.base->call("get_node_or_null", NodePath(get_node->full_path));
+ if (node != nullptr) {
+ if (r_base != nullptr) {
+ *r_base = node;
+ }
+ r_base_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
+ r_base_type.kind = GDScriptParser::DataType::NATIVE;
+ r_base_type.native_type = node->get_class_name();
+ r_base_type.builtin_type = Variant::OBJECT;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
if (p_call->type == GDScriptParser::Node::PRELOAD) {
if (p_argidx == 0 && bool(EDITOR_GET("text_editor/completion/complete_file_paths"))) {
@@ -2561,13 +2612,17 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
}
- if (subscript->is_attribute) {
- GDScriptCompletionIdentifier ci;
- if (_guess_expression_type(p_context, subscript->base, ci)) {
- base_type = ci.type;
- base = ci.value;
- } else {
- return;
+ if (p_context.base != nullptr && subscript->is_attribute) {
+ bool found_type = _get_subscript_type(p_context, subscript, base_type, &base);
+
+ if (!found_type) {
+ GDScriptCompletionIdentifier ci;
+ if (_guess_expression_type(p_context, subscript->base, ci)) {
+ base_type = ci.type;
+ base = ci.value;
+ } else {
+ return;
+ }
}
_static = base_type.is_meta_type;
@@ -2765,7 +2820,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
const GDScriptParser::SubscriptNode *attr = static_cast<const GDScriptParser::SubscriptNode *>(completion_context.node);
if (attr->base) {
GDScriptCompletionIdentifier base;
- if (!_guess_expression_type(completion_context, attr->base, base)) {
+ bool found_type = _get_subscript_type(completion_context, attr, base.type);
+ if (!found_type && !_guess_expression_type(completion_context, attr->base, base)) {
break;
}
@@ -3051,8 +3107,9 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
r_result.type = ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION;
r_result.location = base_type.class_type->get_member(p_symbol).get_line();
r_result.class_path = base_type.script_path;
- r_result.script = GDScriptCache::get_shallow_script(r_result.class_path);
- return OK;
+ Error err = OK;
+ r_result.script = GDScriptCache::get_shallow_script(r_result.class_path, err);
+ return err;
}
base_type = base_type.class_type->base_type;
}
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 98b3e40f1b..24a614b1ad 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -149,10 +149,17 @@ GDScriptFunction::GDScriptFunction() {
}
GDScriptFunction::~GDScriptFunction() {
+ get_script()->member_functions.erase(name);
+
for (int i = 0; i < lambdas.size(); i++) {
memdelete(lambdas[i]);
}
+ for (int i = 0; i < argument_types.size(); i++) {
+ argument_types.write[i].script_type_ref = Ref<Script>();
+ }
+ return_type.script_type_ref = Ref<Script>();
+
#ifdef DEBUG_ENABLED
MutexLock lock(GDScriptLanguage::get_singleton()->mutex);
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index e44038d6da..6e5f7a8520 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -430,6 +430,7 @@ public:
};
private:
+ friend class GDScript;
friend class GDScriptCompiler;
friend class GDScriptByteCodeGenerator;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 6842a1ff49..d24cba4c59 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -147,6 +147,8 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, varray(), true);
// Networking.
register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::rpc_annotation, varray("", "", "", 0), true);
+
+ is_ignoring_warnings = !(bool)GLOBAL_GET("debug/gdscript/warnings/enable");
}
GDScriptParser::~GDScriptParser() {
@@ -230,7 +232,7 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_
warning.leftmost_column = p_source->leftmost_column;
warning.rightmost_column = p_source->rightmost_column;
- if (warn_level == GDScriptWarning::WarnLevel::ERROR) {
+ if (warn_level == GDScriptWarning::WarnLevel::ERROR || bool(GLOBAL_GET("debug/gdscript/warnings/treat_warnings_as_errors"))) {
push_error(warning.get_message(), p_source);
return;
}
@@ -534,6 +536,7 @@ void GDScriptParser::end_statement(const String &p_context) {
void GDScriptParser::parse_program() {
head = alloc_node<ClassNode>();
+ head->fqcn = script_path;
current_class = head;
// If we happen to parse an annotation before extends or class_name keywords, track it.
@@ -646,6 +649,15 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for the class name after "class".)")) {
n_class->identifier = parse_identifier();
+ if (n_class->outer) {
+ String fqcn = n_class->outer->fqcn;
+ if (fqcn.is_empty()) {
+ fqcn = script_path;
+ }
+ n_class->fqcn = fqcn + "::" + n_class->identifier->name;
+ } else {
+ n_class->fqcn = n_class->identifier->name;
+ }
}
if (match(GDScriptTokenizer::Token::EXTENDS)) {
@@ -684,6 +696,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
void GDScriptParser::parse_class_name() {
if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for the global class name after "class_name".)")) {
current_class->identifier = parse_identifier();
+ current_class->fqcn = String(current_class->identifier->name);
}
if (match(GDScriptTokenizer::Token::EXTENDS)) {
@@ -1530,7 +1543,7 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
VariableNode *variable = static_cast<VariableNode *>(statement);
const SuiteNode::Local &local = current_suite->get_local(variable->identifier->name);
if (local.type != SuiteNode::Local::UNDEFINED) {
- push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", local.get_name(), variable->identifier->name));
+ push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", local.get_name(), variable->identifier->name), variable->identifier);
}
current_suite->add_local(variable, current_function);
break;
@@ -1545,7 +1558,7 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
} else {
name = "variable";
}
- push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", name, constant->identifier->name));
+ push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", name, constant->identifier->name), constant->identifier);
}
current_suite->add_local(constant, current_function);
break;
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index 15131afde7..7f42643c8f 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -251,7 +251,10 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) {
return false;
}
} else {
- if (next.get_extension().to_lower() == "gd") {
+ if (next.ends_with(".notest.gd")) {
+ next = dir->get_next();
+ continue;
+ } else if (next.get_extension().to_lower() == "gd") {
#ifndef DEBUG_ENABLED
// On release builds, skip tests marked as debug only.
Error open_err = OK;
@@ -461,7 +464,6 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
Ref<GDScript> script;
script.instantiate();
script->set_path(source_file);
- script->set_script_path(source_file);
err = script->load_source_code(source_file);
if (err != OK) {
enable_stdout();
@@ -598,6 +600,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
}
enable_stdout();
+
+ GDScriptCache::remove_script(script->get_path());
+
return result;
}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd
new file mode 100644
index 0000000000..5c8b9fa4ae
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.gd
@@ -0,0 +1,6 @@
+extends Node
+
+var script: int
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out
new file mode 100644
index 0000000000..8454aaa404
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/overload_script_variable.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Member "script" redefined (original in native class 'Node')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd
new file mode 100644
index 0000000000..28561ff94b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.gd
@@ -0,0 +1,9 @@
+func test():
+ pass
+
+class A:
+ func overload_me():
+ pass
+
+class B extends A:
+ var overload_me
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out
new file mode 100644
index 0000000000..32357f9f6a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/variable_overloads_superclass_function.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The member "overload_me" already exists in parent class A.
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd
new file mode 100644
index 0000000000..3f9bfe189c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.gd
@@ -0,0 +1,4 @@
+extends "inner_base.gd".InnerA.InnerAB
+
+func test():
+ super.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out
new file mode 100644
index 0000000000..62f1383392
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_inner_base.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+InnerA.InnerAB.test
+InnerB.test
diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd
index ea744e3027..c3fc176679 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.notest.gd
@@ -1,7 +1,4 @@
const A := 42
-func test():
- pass
-
func something():
return "OK"
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_base.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_base.gd
new file mode 100644
index 0000000000..a825b59255
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_base.gd
@@ -0,0 +1,18 @@
+extends InnerA
+
+func test():
+ super.test()
+
+class InnerA extends InnerAB:
+ func test():
+ print("InnerA.test")
+ super.test()
+
+ class InnerAB extends InnerB:
+ func test():
+ print("InnerA.InnerAB.test")
+ super.test()
+
+class InnerB:
+ func test():
+ print("InnerB.test")
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_base.out b/modules/gdscript/tests/scripts/analyzer/features/inner_base.out
new file mode 100644
index 0000000000..ddd5ffcfd3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_base.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+InnerA.test
+InnerA.InnerAB.test
+InnerB.test
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd
index 276875dd5a..9d0324ead8 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_constant_types_are_inferred.gd
@@ -1,4 +1,4 @@
-const Constants = preload("gdscript_to_preload.gd")
+const Constants = preload("gdscript_to_preload.notest.gd")
func test():
var a := Constants.A
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd
new file mode 100644
index 0000000000..b730453a8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.gd
@@ -0,0 +1,4 @@
+const A = preload("preload_cyclic_reference_a.notest.gd")
+
+func test():
+ A.test_cyclic_reference()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out
index d73c5eb7cd..14bb971221 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/gdscript_to_preload.out
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference.out
@@ -1 +1,2 @@
GDTEST_OK
+godot
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd
new file mode 100644
index 0000000000..7a6035ded1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_a.notest.gd
@@ -0,0 +1,12 @@
+const B = preload("preload_cyclic_reference_b.notest.gd")
+
+const WAITING_FOR = "godot"
+
+static func test_cyclic_reference():
+ B.test_cyclic_reference()
+
+static func test_cyclic_reference_2():
+ B.test_cyclic_reference_2()
+
+static func test_cyclic_reference_3():
+ B.test_cyclic_reference_3()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd
new file mode 100644
index 0000000000..3ea5b01156
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_cyclic_reference_b.notest.gd
@@ -0,0 +1,10 @@
+const A = preload("preload_cyclic_reference_a.notest.gd")
+
+static func test_cyclic_reference():
+ A.test_cyclic_reference_2()
+
+static func test_cyclic_reference_2():
+ A.test_cyclic_reference_3()
+
+static func test_cyclic_reference_3():
+ print(A.WAITING_FOR)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
index 5f73064cc0..beabf3d2e5 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/use_preload_script_as_type.gd
@@ -1,4 +1,4 @@
-const preloaded : GDScript = preload("gdscript_to_preload.gd")
+const preloaded : GDScript = preload("gdscript_to_preload.notest.gd")
func test():
var preloaded_instance: preloaded = preloaded.new()
diff --git a/modules/gltf/doc_classes/GLTFDocument.xml b/modules/gltf/doc_classes/GLTFDocument.xml
index 3cd0f5c0f9..1967df5218 100644
--- a/modules/gltf/doc_classes/GLTFDocument.xml
+++ b/modules/gltf/doc_classes/GLTFDocument.xml
@@ -16,6 +16,8 @@
<param index="3" name="flags" type="int" default="0" />
<param index="4" name="bake_fps" type="int" default="30" />
<description>
+ Takes a [PackedByteArray] defining a gLTF and returns a [GLTFState] object through the [param state] parameter.
+ [b]Note:[/b] The [param base_path] tells [method append_from_buffer] where to find dependencies and can be empty.
</description>
</method>
<method name="append_from_file">
@@ -26,6 +28,8 @@
<param index="3" name="bake_fps" type="int" default="30" />
<param index="4" name="base_path" type="String" default="&quot;&quot;" />
<description>
+ Takes a path to a gLTF file and returns a [GLTFState] object through the [param state] parameter.
+ [b]Note:[/b] The [param base_path] tells [method append_from_file] where to find dependencies and can be empty.
</description>
</method>
<method name="append_from_scene">
@@ -35,12 +39,14 @@
<param index="2" name="flags" type="int" default="0" />
<param index="3" name="bake_fps" type="int" default="30" />
<description>
+ Takes a Godot Engine scene node and returns a [GLTFState] object through the [param state] parameter.
</description>
</method>
<method name="generate_buffer">
<return type="PackedByteArray" />
<param index="0" name="state" type="GLTFState" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and returns a gLTF [PackedByteArray].
</description>
</method>
<method name="generate_scene">
@@ -48,6 +54,16 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="bake_fps" type="int" default="30" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and returns a Godot Engine scene node.
+ </description>
+ </method>
+ <method name="register_gltf_document_extension" qualifiers="static">
+ <return type="void" />
+ <param index="0" name="extension" type="GLTFDocumentExtension" />
+ <param index="1" name="first_priority" type="bool" default="false" />
+ <description>
+ Registers this GLTFDocumentExtension instance with GLTFDocument. If [param first_priority] is true, this extension will be ran first. Otherwise, it will be ran last.
+ [b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode].
</description>
</method>
<method name="write_to_filesystem">
@@ -55,11 +71,9 @@
<param index="0" name="state" type="GLTFState" />
<param index="1" name="path" type="String" />
<description>
+ Takes a [GLTFState] object through the [param state] parameter and writes a glTF file to the filesystem.
+ [b]Note:[/b] The extension of the glTF file determines if it is a .glb binary file or a .gltf file.
</description>
</method>
</methods>
- <members>
- <member name="extensions" type="GLTFDocumentExtension[]" setter="set_extensions" getter="get_extensions" default="[]">
- </member>
- </members>
</class>
diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
index 936794976d..adc32df8dc 100644
--- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml
+++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
@@ -5,6 +5,8 @@
</brief_description>
<description>
Extends the functionality of the [GLTFDocument] class by allowing you to run arbitrary code at various stages of GLTF import or export.
+ To use, make a new class extending GLTFDocumentExtension, override any methods you need, make an instance of your class, and register it using [method GLTFDocument.register_gltf_document_extension].
+ [b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode].
</description>
<tutorials>
</tutorials>
@@ -61,7 +63,9 @@
<method name="_import_preflight" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
+ <param index="1" name="extensions" type="PackedStringArray" />
<description>
+ This callback is run first. It is used to determine if this GLTFDocumentExtension class should be used for importing a given GLTF file. If [constant OK], the import will use this GLTFDocumentExtension class.
</description>
</method>
</methods>
diff --git a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h
index 5af46bc752..66fd27b449 100644
--- a/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h
+++ b/modules/gltf/editor/editor_scene_exporter_gltf_plugin.h
@@ -36,6 +36,8 @@
#include "editor/editor_plugin.h"
#include "editor_scene_importer_gltf.h"
+class EditorFileDialog;
+
class SceneExporterGLTFPlugin : public EditorPlugin {
GDCLASS(SceneExporterGLTFPlugin, EditorPlugin);
diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h
index b17a1e4eaa..edca038532 100644
--- a/modules/gltf/editor/editor_scene_importer_gltf.h
+++ b/modules/gltf/editor/editor_scene_importer_gltf.h
@@ -33,9 +33,6 @@
#ifdef TOOLS_ENABLED
-#include "../gltf_document_extension.h"
-#include "../gltf_state.h"
-
#include "editor/import/resource_importer_scene.h"
class Animation;
diff --git a/modules/gltf/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp
index 713779712c..56519f70d3 100644
--- a/modules/gltf/gltf_document_extension.cpp
+++ b/modules/gltf/extensions/gltf_document_extension.cpp
@@ -32,7 +32,7 @@
void GLTFDocumentExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_supported_extensions);
- GDVIRTUAL_BIND(_import_preflight, "state");
+ GDVIRTUAL_BIND(_import_preflight, "state", "extensions");
GDVIRTUAL_BIND(_import_post_parse, "state");
GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node");
GDVIRTUAL_BIND(_import_post, "state", "root");
@@ -55,10 +55,10 @@ Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) {
return Error(err);
}
-Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state) {
+Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
int err = OK;
- GDVIRTUAL_CALL(_import_preflight, p_state, err);
+ GDVIRTUAL_CALL(_import_preflight, p_state, p_extensions, err);
return Error(err);
}
diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h
index d4bb3993dc..43e29ea0ab 100644
--- a/modules/gltf/gltf_document_extension.h
+++ b/modules/gltf/extensions/gltf_document_extension.h
@@ -31,8 +31,7 @@
#ifndef GLTF_DOCUMENT_EXTENSION_H
#define GLTF_DOCUMENT_EXTENSION_H
-#include "gltf_state.h"
-#include "structures/gltf_node.h"
+#include "../gltf_state.h"
class GLTFDocumentExtension : public Resource {
GDCLASS(GLTFDocumentExtension, Resource);
@@ -42,7 +41,7 @@ protected:
public:
virtual Vector<String> get_supported_extensions();
- virtual Error import_preflight(Ref<GLTFState> p_state);
+ virtual Error import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions);
virtual Error import_post_parse(Ref<GLTFState> p_state);
virtual Error export_post(Ref<GLTFState> p_state);
virtual Error import_post(Ref<GLTFState> p_state, Node *p_node);
@@ -50,7 +49,7 @@ public:
virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
virtual Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
GDVIRTUAL0R(Vector<String>, _get_supported_extensions);
- GDVIRTUAL1R(int, _import_preflight, Ref<GLTFState>);
+ GDVIRTUAL2R(int, _import_preflight, Ref<GLTFState>, Vector<String>);
GDVIRTUAL1R(int, _import_post_parse, Ref<GLTFState>);
GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *);
diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp
index 1620900a04..49496afb62 100644
--- a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp
+++ b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.cpp
@@ -30,7 +30,7 @@
#include "gltf_document_extension_convert_importer_mesh.h"
-#include "gltf_state.h"
+#include "../gltf_state.h"
#include "core/error/error_macros.h"
#include "scene/3d/mesh_instance_3d.h"
diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h
index 00e664e73f..00e664e73f 100644
--- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h
+++ b/modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 99803ed05d..49797bb8fa 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -31,8 +31,6 @@
#include "gltf_document.h"
#include "extensions/gltf_spec_gloss.h"
-#include "gltf_document_extension.h"
-#include "gltf_document_extension_convert_importer_mesh.h"
#include "gltf_state.h"
#include "core/crypto/crypto_core.h"
@@ -215,8 +213,7 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
return Error::FAILED;
}
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->export_post(state);
ERR_FAIL_COND_V(err != OK, err);
@@ -454,8 +451,7 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) {
node["children"] = children;
}
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
ERR_CONTINUE(!state->scene_nodes.find(i));
Error err = ext->export_node(state, gltf_node, node, state->scene_nodes[i]);
@@ -6586,11 +6582,13 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess>
state->major_version = version.get_slice(".", 0).to_int();
state->minor_version = version.get_slice(".", 1).to_int();
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ document_extensions.clear();
+ for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
ERR_CONTINUE(ext.is_null());
- err = ext->import_preflight(state);
- ERR_FAIL_COND_V(err != OK, err);
+ err = ext->import_preflight(state, state->json["extensionsUsed"]);
+ if (err == OK) {
+ document_extensions.push_back(ext);
+ }
}
err = _parse_gltf_state(state, p_path, p_bake_fps);
@@ -6728,14 +6726,8 @@ void GLTFDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"),
&GLTFDocument::write_to_filesystem);
- ClassDB::bind_method(D_METHOD("set_extensions", "extensions"),
- &GLTFDocument::set_extensions);
- ClassDB::bind_method(D_METHOD("get_extensions"),
- &GLTFDocument::get_extensions);
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "extensions", PROPERTY_HINT_ARRAY_TYPE,
- vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GLTFDocumentExtension"),
- PROPERTY_USAGE_DEFAULT),
- "set_extensions", "get_extensions");
+ ClassDB::bind_static_method("GLTFDocument", D_METHOD("register_gltf_document_extension", "extension", "first_priority"),
+ &GLTFDocument::register_gltf_document_extension, DEFVAL(false));
}
void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) {
@@ -6752,22 +6744,20 @@ void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) {
}
}
-void GLTFDocument::set_extensions(TypedArray<GLTFDocumentExtension> p_extensions) {
- document_extensions = p_extensions;
-}
+Vector<Ref<GLTFDocumentExtension>> GLTFDocument::all_document_extensions;
-TypedArray<GLTFDocumentExtension> GLTFDocument::get_extensions() const {
- return document_extensions;
+void GLTFDocument::register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority) {
+ if (all_document_extensions.find(p_extension) == -1) {
+ if (p_first_priority) {
+ all_document_extensions.insert(0, p_extension);
+ } else {
+ all_document_extensions.push_back(p_extension);
+ }
+ }
}
-GLTFDocument::GLTFDocument() {
- bool is_editor = ::Engine::get_singleton()->is_editor_hint();
- if (is_editor) {
- return;
- }
- Ref<GLTFDocumentExtensionConvertImporterMesh> extension_editor;
- extension_editor.instantiate();
- document_extensions.push_back(extension_editor);
+void GLTFDocument::unregister_all_gltf_document_extensions() {
+ all_document_extensions.clear();
}
PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error *r_err) {
@@ -6852,8 +6842,7 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
}
for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
ERR_CONTINUE(!E.value);
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
ERR_CONTINUE(!state->json.has("nodes"));
Array nodes = state->json["nodes"];
@@ -6865,8 +6854,7 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
ERR_CONTINUE(err != OK);
}
}
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_post(state, root);
ERR_CONTINUE(err != OK);
@@ -6880,11 +6868,13 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32
state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ document_extensions.clear();
+ for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
ERR_CONTINUE(ext.is_null());
Error err = ext->export_preflight(p_node);
- ERR_FAIL_COND_V(err != OK, FAILED);
+ if (err == OK) {
+ document_extensions.push_back(ext);
+ }
}
_convert_scene_node(state, p_node, -1, -1);
if (!state->buffers.size()) {
@@ -6906,8 +6896,7 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa
state->base_path = p_base_path.get_base_dir();
err = _parse(state, state->base_path, file_access, p_bake_fps);
ERR_FAIL_COND_V(err != OK, err);
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_post_parse(state);
ERR_FAIL_COND_V(err != OK, err);
@@ -7030,8 +7019,7 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint
r_state->base_path = base_path;
err = _parse(r_state, base_path, f, p_bake_fps);
ERR_FAIL_COND_V(err != OK, err);
- for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_post_parse(r_state);
ERR_FAIL_COND_V(err != OK, err);
@@ -7053,8 +7041,7 @@ Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) {
supported_extensions.insert("KHR_lights_punctual");
supported_extensions.insert("KHR_materials_pbrSpecularGlossiness");
supported_extensions.insert("KHR_texture_transform");
- for (int ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
- Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
Vector<String> ext_supported_extensions = ext->get_supported_extensions();
for (int i = 0; i < ext_supported_extensions.size(); ++i) {
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 62b6e29fe0..15099efe33 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -31,7 +31,7 @@
#ifndef GLTF_DOCUMENT_H
#define GLTF_DOCUMENT_H
-#include "gltf_defines.h"
+#include "extensions/gltf_document_extension.h"
#include "structures/gltf_animation.h"
#include "scene/3d/bone_attachment_3d.h"
@@ -44,13 +44,13 @@
class GLTFDocument : public Resource {
GDCLASS(GLTFDocument, Resource);
- TypedArray<GLTFDocumentExtension> document_extensions;
+ static Vector<Ref<GLTFDocumentExtension>> all_document_extensions;
+ Vector<Ref<GLTFDocumentExtension>> document_extensions;
private:
const float BAKE_FPS = 30.0f;
public:
- GLTFDocument();
const int32_t JOINT_GROUP_SIZE = 4;
enum {
@@ -76,8 +76,8 @@ protected:
static void _bind_methods();
public:
- void set_extensions(TypedArray<GLTFDocumentExtension> p_extensions);
- TypedArray<GLTFDocumentExtension> get_extensions() const;
+ static void register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority = false);
+ static void unregister_all_gltf_document_extensions();
private:
void _build_parent_hierachy(Ref<GLTFState> state);
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index b9027f6e3d..a7abf256ce 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -32,11 +32,10 @@
#ifndef _3D_DISABLED
+#include "extensions/gltf_document_extension_convert_importer_mesh.h"
#include "extensions/gltf_light.h"
#include "extensions/gltf_spec_gloss.h"
#include "gltf_document.h"
-#include "gltf_document_extension.h"
-#include "gltf_document_extension_convert_importer_mesh.h"
#include "gltf_state.h"
#include "structures/gltf_accessor.h"
#include "structures/gltf_animation.h"
@@ -109,6 +108,11 @@ static void _editor_init() {
}
#endif // TOOLS_ENABLED
+#define GLTF_REGISTER_DOCUMENT_EXTENSION(m_doc_ext_class) \
+ Ref<m_doc_ext_class> extension_##m_doc_ext_class; \
+ extension_##m_doc_ext_class.instantiate(); \
+ GLTFDocument::register_gltf_document_extension(extension_##m_doc_ext_class);
+
void initialize_gltf_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
// glTF API available at runtime.
@@ -128,6 +132,11 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(GLTFState);
GDREGISTER_CLASS(GLTFTexture);
GDREGISTER_CLASS(GLTFTextureSampler);
+ // Register GLTFDocumentExtension classes with GLTFDocument.
+ bool is_editor = ::Engine::get_singleton()->is_editor_hint();
+ if (!is_editor) {
+ GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionConvertImporterMesh);
+ }
}
#ifdef TOOLS_ENABLED
@@ -161,6 +170,7 @@ void uninitialize_gltf_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
+ GLTFDocument::unregister_all_gltf_document_extensions();
}
#endif // _3D_DISABLED
diff --git a/modules/gltf/structures/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp
index ba19ed8628..a15141225b 100644
--- a/modules/gltf/structures/gltf_buffer_view.cpp
+++ b/modules/gltf/structures/gltf_buffer_view.cpp
@@ -30,8 +30,6 @@
#include "gltf_buffer_view.h"
-#include "../gltf_document_extension.h"
-
void GLTFBufferView::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer);
ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer);
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h
index 6fd38d9445..91f14690ca 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.h
+++ b/modules/gridmap/editor/grid_map_editor_plugin.h
@@ -35,11 +35,14 @@
#include "../grid_map.h"
#include "editor/editor_plugin.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/item_list.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
+class ConfirmationDialog;
class EditorUndoRedoManager;
+class MenuButton;
class Node3DEditorPlugin;
class GridMapEditor : public VBoxContainer {
diff --git a/modules/lightmapper_rd/register_types.cpp b/modules/lightmapper_rd/register_types.cpp
index 0e0330c1a1..ed223e1faa 100644
--- a/modules/lightmapper_rd/register_types.cpp
+++ b/modules/lightmapper_rd/register_types.cpp
@@ -57,6 +57,7 @@ void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level) {
GLOBAL_DEF("rendering/lightmapping/bake_quality/high_quality_probe_ray_count", 512);
GLOBAL_DEF("rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count", 2048);
GLOBAL_DEF("rendering/lightmapping/bake_performance/max_rays_per_probe_pass", 64);
+ GLOBAL_DEF("rendering/lightmapping/primitive_meshes/texel_size", 0.2);
#ifndef _3D_DISABLED
GDREGISTER_CLASS(LightmapperRD);
Lightmapper::create_gpu = create_lightmapper_rd;
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp
index e84d95773d..e658668355 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.cpp
+++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp
@@ -118,7 +118,6 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_socket_connected(), ERR_INVALID_PARAMETER);
base = p_base;
- int ret = 0;
int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE;
Error err = tls_ctx->init_client(MBEDTLS_SSL_TRANSPORT_DATAGRAM, authmode, p_ca_certs);
@@ -130,7 +129,7 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
status = STATUS_HANDSHAKING;
- if ((ret = _do_handshake()) != OK) {
+ if (_do_handshake() != OK) {
status = STATUS_ERROR_HOSTNAME_MISMATCH;
return FAILED;
}
@@ -158,7 +157,7 @@ Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey>
status = STATUS_HANDSHAKING;
- if ((ret = _do_handshake()) != OK) {
+ if (_do_handshake() != OK) {
status = STATUS_ERROR;
return FAILED;
}
@@ -175,7 +174,7 @@ Error PacketPeerMbedDTLS::put_packet(const uint8_t *p_buffer, int p_bytes) {
int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_buffer, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- ret = 0; // non blocking io
+ // Non blocking io.
} else if (ret <= 0) {
TLSContextMbedTLS::print_mbedtls_error(ret);
_cleanup();
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
index 1a25d684a0..88c0e71155 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
@@ -71,29 +71,29 @@ namespace Godot.SourceGenerators
Expression = 19,
PlaceholderText = 20,
ColorNoAlpha = 21,
- ImageCompressLossy = 22,
- ImageCompressLossless = 23,
- ObjectId = 24,
- TypeString = 25,
- NodePathToEditedNode = 26,
- MethodOfVariantType = 27,
- MethodOfBaseType = 28,
- MethodOfInstance = 29,
- MethodOfScript = 30,
- PropertyOfVariantType = 31,
- PropertyOfBaseType = 32,
- PropertyOfInstance = 33,
- PropertyOfScript = 34,
- ObjectTooBig = 35,
- NodePathValidTypes = 36,
- SaveFile = 37,
- GlobalSaveFile = 38,
- IntIsObjectid = 39,
- IntIsPointer = 41,
- ArrayType = 40,
- LocaleId = 42,
- LocalizableString = 43,
- NodeType = 44,
+ ObjectId = 22,
+ TypeString = 23,
+ NodePathToEditedNode = 24,
+ MethodOfVariantType = 25,
+ MethodOfBaseType = 26,
+ MethodOfInstance = 27,
+ MethodOfScript = 28,
+ PropertyOfVariantType = 29,
+ PropertyOfBaseType = 30,
+ PropertyOfInstance = 31,
+ PropertyOfScript = 32,
+ ObjectTooBig = 33,
+ NodePathValidTypes = 34,
+ SaveFile = 35,
+ GlobalSaveFile = 36,
+ IntIsObjectid = 37,
+ IntIsPointer = 38,
+ ArrayType = 39,
+ LocaleId = 40,
+ LocalizableString = 41,
+ NodeType = 42,
+ HideQuaternionEdit = 43,
+ Password = 44,
Max = 45
}
@@ -128,12 +128,14 @@ namespace Godot.SourceGenerators
DeferredSetResource = 33554432,
EditorInstantiateObject = 67108864,
EditorBasicSetting = 134217728,
+ ReadOnly = 268435456,
Array = 536870912,
Default = 6,
DefaultIntl = 38,
NoEditor = 2
}
+ [Flags]
public enum MethodFlags
{
Normal = 1,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
index db395e21cb..abd8079922 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
@@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis;
namespace Godot.SourceGenerators
{
- public struct GodotMethodData
+ public readonly struct GodotMethodData
{
public GodotMethodData(IMethodSymbol method, ImmutableArray<MarshalType> paramTypes,
ImmutableArray<ITypeSymbol> paramTypeSymbols, MarshalType? retType, ITypeSymbol? retSymbol)
@@ -22,7 +22,7 @@ namespace Godot.SourceGenerators
public ITypeSymbol? RetSymbol { get; }
}
- public struct GodotSignalDelegateData
+ public readonly struct GodotSignalDelegateData
{
public GodotSignalDelegateData(string name, INamedTypeSymbol delegateSymbol, GodotMethodData invokeMethodData)
{
@@ -36,7 +36,7 @@ namespace Godot.SourceGenerators
public GodotMethodData InvokeMethodData { get; }
}
- public struct GodotPropertyData
+ public readonly struct GodotPropertyData
{
public GodotPropertyData(IPropertySymbol propertySymbol, MarshalType type)
{
@@ -48,7 +48,7 @@ namespace Godot.SourceGenerators
public MarshalType Type { get; }
}
- public struct GodotFieldData
+ public readonly struct GodotFieldData
{
public GodotFieldData(IFieldSymbol fieldSymbol, MarshalType type)
{
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
index 81c6f2b7d5..bb9be862c4 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MethodInfo.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Godot.SourceGenerators
{
- internal struct MethodInfo
+ internal readonly struct MethodInfo
{
public MethodInfo(string name, PropertyInfo returnVal, MethodFlags flags,
List<PropertyInfo>? arguments,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
index b345f5f84d..2b89633ef6 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/PropertyInfo.cs
@@ -1,6 +1,6 @@
namespace Godot.SourceGenerators
{
- internal struct PropertyInfo
+ internal readonly struct PropertyInfo
{
public PropertyInfo(VariantType type, string name, PropertyHint hint,
string? hintString, PropertyUsageFlags usage, bool exported)
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
index 9d593fbf8a..ab21527344 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs
@@ -13,7 +13,7 @@ namespace GodotTools.IdeMessaging.Utils
return waitAsyncTask.ContinueWith<IDisposable>(t => wrapper, cancellationToken).ConfigureAwait(false);
}
- private struct SemaphoreSlimWaitReleaseWrapper : IDisposable
+ private readonly struct SemaphoreSlimWaitReleaseWrapper : IDisposable
{
private readonly SemaphoreSlim semaphoreSlim;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
index 2184cae6d6..94efcba3f1 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
@@ -22,7 +22,7 @@ namespace GodotTools.Export
public bool FullAot;
private bool _useInterpreter;
- public bool UseInterpreter { get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; }
+ public bool UseInterpreter { readonly get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; }
public string[] ExtraAotOptions;
public string[] ExtraOptimizerOptions;
diff --git a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
index 820d0c0b83..9a8fdcc7c5 100644
--- a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs
@@ -1,6 +1,6 @@
namespace GodotTools
{
- public struct PlaySettings
+ public readonly struct PlaySettings
{
public bool HasDebugger { get; }
public string DebuggerHost { get; }
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
index 686023a077..ae51c07386 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/CallbacksInfo.cs
@@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis;
namespace Godot.SourceGenerators.Internal;
-internal struct CallbacksData
+internal readonly struct CallbacksData
{
public CallbacksData(INamedTypeSymbol nativeTypeSymbol, INamedTypeSymbol funcStructSymbol)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
index d8a6644a66..a2916d4ae8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector3 Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector3 Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector3 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -54,7 +54,7 @@ namespace Godot
/// the most-negative corner is the origin and the size is positive.
/// </summary>
/// <returns>The modified <see cref="AABB"/>.</returns>
- public AABB Abs()
+ public readonly AABB Abs()
{
Vector3 end = End;
Vector3 topLeft = new Vector3(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y), Mathf.Min(_position.z, end.z));
@@ -66,7 +66,7 @@ namespace Godot
/// to <see cref="Position"/> + (<see cref="Size"/> / 2).
/// </summary>
/// <returns>The center.</returns>
- public Vector3 GetCenter()
+ public readonly Vector3 GetCenter()
{
return _position + (_size * 0.5f);
}
@@ -78,7 +78,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="AABB"/> encloses <paramref name="with"/>.
/// </returns>
- public bool Encloses(AABB with)
+ public readonly bool Encloses(AABB with)
{
Vector3 srcMin = _position;
Vector3 srcMax = _position + _size;
@@ -98,7 +98,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to include.</param>
/// <returns>The expanded <see cref="AABB"/>.</returns>
- public AABB Expand(Vector3 point)
+ public readonly AABB Expand(Vector3 point)
{
Vector3 begin = _position;
Vector3 end = _position + _size;
@@ -140,7 +140,7 @@ namespace Godot
/// <paramref name="idx"/> is less than 0 or greater than 7.
/// </exception>
/// <returns>An endpoint of the <see cref="AABB"/>.</returns>
- public Vector3 GetEndpoint(int idx)
+ public readonly Vector3 GetEndpoint(int idx)
{
switch (idx)
{
@@ -172,7 +172,7 @@ namespace Godot
/// Returns the normalized longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A vector representing the normalized longest axis of the <see cref="AABB"/>.</returns>
- public Vector3 GetLongestAxis()
+ public readonly Vector3 GetLongestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
real_t maxSize = _size.x;
@@ -195,7 +195,7 @@ namespace Godot
/// Returns the <see cref="Vector3.Axis"/> index of the longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is longest.</returns>
- public Vector3.Axis GetLongestAxisIndex()
+ public readonly Vector3.Axis GetLongestAxisIndex()
{
var axis = Vector3.Axis.X;
real_t maxSize = _size.x;
@@ -218,7 +218,7 @@ namespace Godot
/// Returns the scalar length of the longest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>The scalar length of the longest axis of the <see cref="AABB"/>.</returns>
- public real_t GetLongestAxisSize()
+ public readonly real_t GetLongestAxisSize()
{
real_t maxSize = _size.x;
@@ -235,7 +235,7 @@ namespace Godot
/// Returns the normalized shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A vector representing the normalized shortest axis of the <see cref="AABB"/>.</returns>
- public Vector3 GetShortestAxis()
+ public readonly Vector3 GetShortestAxis()
{
var axis = new Vector3(1f, 0f, 0f);
real_t maxSize = _size.x;
@@ -258,7 +258,7 @@ namespace Godot
/// Returns the <see cref="Vector3.Axis"/> index of the shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>A <see cref="Vector3.Axis"/> index for which axis is shortest.</returns>
- public Vector3.Axis GetShortestAxisIndex()
+ public readonly Vector3.Axis GetShortestAxisIndex()
{
var axis = Vector3.Axis.X;
real_t maxSize = _size.x;
@@ -281,7 +281,7 @@ namespace Godot
/// Returns the scalar length of the shortest axis of the <see cref="AABB"/>.
/// </summary>
/// <returns>The scalar length of the shortest axis of the <see cref="AABB"/>.</returns>
- public real_t GetShortestAxisSize()
+ public readonly real_t GetShortestAxisSize()
{
real_t maxSize = _size.x;
@@ -300,7 +300,7 @@ namespace Godot
/// </summary>
/// <param name="dir">The direction to find support for.</param>
/// <returns>A vector representing the support.</returns>
- public Vector3 GetSupport(Vector3 dir)
+ public readonly Vector3 GetSupport(Vector3 dir)
{
Vector3 halfExtents = _size * 0.5f;
Vector3 ofs = _position + halfExtents;
@@ -315,7 +315,7 @@ namespace Godot
/// Returns the volume of the <see cref="AABB"/>.
/// </summary>
/// <returns>The volume.</returns>
- public real_t GetVolume()
+ public readonly real_t GetVolume()
{
return _size.x * _size.y * _size.z;
}
@@ -325,7 +325,7 @@ namespace Godot
/// </summary>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="AABB"/>.</returns>
- public AABB Grow(real_t by)
+ public readonly AABB Grow(real_t by)
{
AABB res = this;
@@ -347,7 +347,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector3 point)
+ public readonly bool HasPoint(Vector3 point)
{
if (point.x < _position.x)
return false;
@@ -374,7 +374,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has surface.
/// </returns>
- public bool HasSurface()
+ public readonly bool HasSurface()
{
return _size.x > 0.0f || _size.y > 0.0f || _size.z > 0.0f;
}
@@ -388,7 +388,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> has volume.
/// </returns>
- public bool HasVolume()
+ public readonly bool HasVolume()
{
return _size.x > 0.0f && _size.y > 0.0f && _size.z > 0.0f;
}
@@ -398,7 +398,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other <see cref="AABB"/>.</param>
/// <returns>The clipped <see cref="AABB"/>.</returns>
- public AABB Intersection(AABB with)
+ public readonly AABB Intersection(AABB with)
{
Vector3 srcMin = _position;
Vector3 srcMax = _position + _size;
@@ -447,7 +447,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not they are intersecting.
/// </returns>
- public bool Intersects(AABB with, bool includeBorders = false)
+ public readonly bool Intersects(AABB with, bool includeBorders = false)
{
if (includeBorders)
{
@@ -490,7 +490,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the <see cref="Plane"/>.
/// </returns>
- public bool IntersectsPlane(Plane plane)
+ public readonly bool IntersectsPlane(Plane plane)
{
Vector3[] points =
{
@@ -531,7 +531,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="AABB"/> intersects the line segment.
/// </returns>
- public bool IntersectsSegment(Vector3 from, Vector3 to)
+ public readonly bool IntersectsSegment(Vector3 from, Vector3 to)
{
real_t min = 0f;
real_t max = 1f;
@@ -590,7 +590,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other <see cref="AABB"/>.</param>
/// <returns>The merged <see cref="AABB"/>.</returns>
- public AABB Merge(AABB with)
+ public readonly AABB Merge(AABB with)
{
Vector3 beg1 = _position;
Vector3 beg2 = with._position;
@@ -702,7 +702,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the AABB and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is AABB other && Equals(other);
}
@@ -714,7 +714,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other AABB.</param>
/// <returns>Whether or not the AABBs are exactly equal.</returns>
- public bool Equals(AABB other)
+ public readonly bool Equals(AABB other)
{
return _position == other._position && _size == other._size;
}
@@ -725,7 +725,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other AABB to compare.</param>
/// <returns>Whether or not the AABBs structures are approximately equal.</returns>
- public bool IsEqualApprox(AABB other)
+ public readonly bool IsEqualApprox(AABB other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size);
}
@@ -734,7 +734,7 @@ namespace Godot
/// Serves as the hash function for <see cref="AABB"/>.
/// </summary>
/// <returns>A hash code for this AABB.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -743,7 +743,7 @@ namespace Godot
/// Converts this <see cref="AABB"/> to a string.
/// </summary>
/// <returns>A string representation of this AABB.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -752,7 +752,7 @@ namespace Godot
/// Converts this <see cref="AABB"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this AABB.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index bb1d6e1661..5d390a298d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -29,7 +29,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column0"/> and array index <c>[0]</c>.</value>
public Vector3 x
{
- get => Column0;
+ readonly get => Column0;
set => Column0 = value;
}
@@ -39,7 +39,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column1"/> and array index <c>[1]</c>.</value>
public Vector3 y
{
- get => Column1;
+ readonly get => Column1;
set => Column1 = value;
}
@@ -49,7 +49,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Column2"/> and array index <c>[2]</c>.</value>
public Vector3 z
{
- get => Column2;
+ readonly get => Column2;
set => Column2 = value;
}
@@ -80,7 +80,7 @@ namespace Godot
/// <value>Equivalent to <see cref="x"/> and array index <c>[0]</c>.</value>
public Vector3 Column0
{
- get => new Vector3(Row0.x, Row1.x, Row2.x);
+ readonly get => new Vector3(Row0.x, Row1.x, Row2.x);
set
{
Row0.x = value.x;
@@ -95,7 +95,7 @@ namespace Godot
/// <value>Equivalent to <see cref="y"/> and array index <c>[1]</c>.</value>
public Vector3 Column1
{
- get => new Vector3(Row0.y, Row1.y, Row2.y);
+ readonly get => new Vector3(Row0.y, Row1.y, Row2.y);
set
{
Row0.y = value.x;
@@ -110,7 +110,7 @@ namespace Godot
/// <value>Equivalent to <see cref="z"/> and array index <c>[2]</c>.</value>
public Vector3 Column2
{
- get => new Vector3(Row0.z, Row1.z, Row2.z);
+ readonly get => new Vector3(Row0.z, Row1.z, Row2.z);
set
{
Row0.z = value.x;
@@ -125,7 +125,7 @@ namespace Godot
/// <value>Equivalent to the lengths of each column vector, but negative if the determinant is negative.</value>
public Vector3 Scale
{
- get
+ readonly get
{
real_t detSign = Mathf.Sign(Determinant());
return detSign * new Vector3
@@ -154,7 +154,7 @@ namespace Godot
/// <value>The basis column.</value>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -195,7 +195,7 @@ namespace Godot
/// <value>The matrix element.</value>
public real_t this[int column, int row]
{
- get
+ readonly get
{
return this[column][row];
}
@@ -234,7 +234,7 @@ namespace Godot
/// and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
- public real_t Determinant()
+ public readonly real_t Determinant()
{
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
@@ -255,7 +255,7 @@ namespace Godot
/// </summary>
/// <param name="order">The Euler order to use. By default, use YXZ order (most common).</param>
/// <returns>A <see cref="Vector3"/> representing the basis rotation in Euler angles.</returns>
- public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
+ public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
{
switch (order)
{
@@ -499,7 +499,7 @@ namespace Godot
/// mind that quaternions should generally be preferred to Euler angles.
/// </summary>
/// <returns>A <see cref="Quaternion"/> representing the basis's rotation.</returns>
- internal Quaternion GetQuaternion()
+ internal readonly Quaternion GetQuaternion()
{
real_t trace = Row0[0] + Row1[1] + Row2[2];
@@ -558,7 +558,7 @@ namespace Godot
/// be preferred to Euler angles.
/// </summary>
/// <returns>The basis rotation.</returns>
- public Quaternion GetRotationQuaternion()
+ public readonly Quaternion GetRotationQuaternion()
{
Basis orthonormalizedBasis = Orthonormalized();
real_t det = orthonormalizedBasis.Determinant();
@@ -581,7 +581,7 @@ namespace Godot
/// <paramref name="index"/> is not 0, 1 or 2.
/// </exception>
/// <returns>One of <c>Row0</c>, <c>Row1</c>, or <c>Row2</c>.</returns>
- public Vector3 GetRow(int index)
+ public readonly Vector3 GetRow(int index)
{
switch (index)
{
@@ -633,7 +633,7 @@ namespace Godot
/// For further details, refer to the Godot source code.
/// </summary>
/// <returns>The orthogonal index.</returns>
- public int GetOrthogonalIndex()
+ public readonly int GetOrthogonalIndex()
{
var orth = this;
@@ -679,7 +679,7 @@ namespace Godot
/// Returns the inverse of the matrix.
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Basis Inverse()
+ public readonly Basis Inverse()
{
real_t cofac00 = Row1[1] * Row2[2] - Row1[2] * Row2[1];
real_t cofac10 = Row1[2] * Row2[0] - Row1[0] * Row2[2];
@@ -709,7 +709,7 @@ namespace Godot
);
}
- internal Basis Lerp(Basis to, real_t weight)
+ internal readonly Basis Lerp(Basis to, real_t weight)
{
Basis b = this;
b.Row0 = Row0.Lerp(to.Row0, weight);
@@ -724,7 +724,7 @@ namespace Godot
/// This performs a Gram-Schmidt orthonormalization on the basis of the matrix.
/// </summary>
/// <returns>An orthonormalized basis matrix.</returns>
- public Basis Orthonormalized()
+ public readonly Basis Orthonormalized()
{
Vector3 column0 = this[0];
Vector3 column1 = this[1];
@@ -746,7 +746,7 @@ namespace Godot
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated basis matrix.</returns>
- public Basis Rotated(Vector3 axis, real_t angle)
+ public readonly Basis Rotated(Vector3 axis, real_t angle)
{
return new Basis(axis, angle) * this;
}
@@ -756,7 +756,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled basis matrix.</returns>
- public Basis Scaled(Vector3 scale)
+ public readonly Basis Scaled(Vector3 scale)
{
Basis b = this;
b.Row0 *= scale.x;
@@ -772,7 +772,7 @@ namespace Godot
/// <param name="target">The destination basis for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting basis matrix of the interpolation.</returns>
- public Basis Slerp(Basis target, real_t weight)
+ public readonly Basis Slerp(Basis target, real_t weight)
{
Quaternion from = new Quaternion(this);
Quaternion to = new Quaternion(target);
@@ -790,7 +790,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdotx(Vector3 with)
+ public readonly real_t Tdotx(Vector3 with)
{
return Row0[0] * with[0] + Row1[0] * with[1] + Row2[0] * with[2];
}
@@ -800,7 +800,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdoty(Vector3 with)
+ public readonly real_t Tdoty(Vector3 with)
{
return Row0[1] * with[0] + Row1[1] * with[1] + Row2[1] * with[2];
}
@@ -810,7 +810,7 @@ namespace Godot
/// </summary>
/// <param name="with">A vector to calculate the dot product with.</param>
/// <returns>The resulting dot product.</returns>
- public real_t Tdotz(Vector3 with)
+ public readonly real_t Tdotz(Vector3 with)
{
return Row0[2] * with[0] + Row1[2] * with[1] + Row2[2] * with[2];
}
@@ -819,21 +819,18 @@ namespace Godot
/// Returns the transposed version of the basis matrix.
/// </summary>
/// <returns>The transposed basis matrix.</returns>
- public Basis Transposed()
+ public readonly Basis Transposed()
{
Basis tr = this;
- real_t temp = tr.Row0[1];
- tr.Row0[1] = tr.Row1[0];
- tr.Row1[0] = temp;
+ tr.Row0[1] = Row1[0];
+ tr.Row1[0] = Row0[1];
- temp = tr.Row0[2];
- tr.Row0[2] = tr.Row2[0];
- tr.Row2[0] = temp;
+ tr.Row0[2] = Row2[0];
+ tr.Row2[0] = Row0[2];
- temp = tr.Row1[2];
- tr.Row1[2] = tr.Row2[1];
- tr.Row2[1] = temp;
+ tr.Row1[2] = Row2[1];
+ tr.Row2[1] = Row1[2];
return tr;
}
@@ -1121,7 +1118,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the basis matrix and the object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Basis other && Equals(other);
}
@@ -1133,7 +1130,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other basis.</param>
/// <returns>Whether or not the basis matrices are exactly equal.</returns>
- public bool Equals(Basis other)
+ public readonly bool Equals(Basis other)
{
return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2);
}
@@ -1144,7 +1141,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other basis to compare.</param>
/// <returns>Whether or not the bases are approximately equal.</returns>
- public bool IsEqualApprox(Basis other)
+ public readonly bool IsEqualApprox(Basis other)
{
return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2);
}
@@ -1153,7 +1150,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Basis"/>.
/// </summary>
/// <returns>A hash code for this basis.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode();
}
@@ -1162,7 +1159,7 @@ namespace Godot
/// Converts this <see cref="Basis"/> to a string.
/// </summary>
/// <returns>A string representation of this basis.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {x}, Y: {y}, Z: {z}]";
}
@@ -1171,7 +1168,7 @@ namespace Godot
/// Converts this <see cref="Basis"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this basis.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, Z: {z.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
index 647ae436ff..85d38f9727 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/MethodInfo.cs
@@ -4,7 +4,7 @@ namespace Godot.Bridge;
#nullable enable
-public struct MethodInfo
+public readonly struct MethodInfo
{
public StringName Name { get; init; }
public PropertyInfo ReturnVal { get; init; }
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
index 80d6f7b4a5..0f447b93c8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/PropertyInfo.cs
@@ -2,7 +2,7 @@ namespace Godot.Bridge;
#nullable enable
-public struct PropertyInfo
+public readonly struct PropertyInfo
{
public Variant.Type Type { get; init; }
public StringName Name { get; init; }
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index ee9e59f9fa..f49023555b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -43,7 +43,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int r8
{
- get
+ readonly get
{
return (int)Math.Round(r * 255.0f);
}
@@ -59,7 +59,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int g8
{
- get
+ readonly get
{
return (int)Math.Round(g * 255.0f);
}
@@ -75,7 +75,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int b8
{
- get
+ readonly get
{
return (int)Math.Round(b * 255.0f);
}
@@ -91,7 +91,7 @@ namespace Godot
/// <value>Getting is equivalent to multiplying by 255 and rounding. Setting is equivalent to dividing by 255.</value>
public int a8
{
- get
+ readonly get
{
return (int)Math.Round(a * 255.0f);
}
@@ -107,7 +107,7 @@ namespace Godot
/// <value>Getting is a long process, refer to the source code for details. Setting uses <see cref="FromHSV"/>.</value>
public float h
{
- get
+ readonly get
{
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
@@ -155,7 +155,7 @@ namespace Godot
/// <value>Getting is equivalent to the ratio between the min and max RGB value. Setting uses <see cref="FromHSV"/>.</value>
public float s
{
- get
+ readonly get
{
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
@@ -176,7 +176,7 @@ namespace Godot
/// <value>Getting is equivalent to using <see cref="Math.Max(float, float)"/> on the RGB components. Setting uses <see cref="FromHSV"/>.</value>
public float v
{
- get
+ readonly get
{
return Math.Max(r, Math.Max(g, b));
}
@@ -197,7 +197,7 @@ namespace Godot
/// </value>
public float this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -242,7 +242,7 @@ namespace Godot
/// </summary>
/// <param name="over">The color to blend over.</param>
/// <returns>This color blended over <paramref name="over"/>.</returns>
- public Color Blend(Color over)
+ public readonly Color Blend(Color over)
{
Color res;
@@ -269,7 +269,7 @@ namespace Godot
/// <param name="min">The color with minimum allowed values.</param>
/// <param name="max">The color with maximum allowed values.</param>
/// <returns>The color with all components clamped.</returns>
- public Color Clamp(Color? min = null, Color? max = null)
+ public readonly Color Clamp(Color? min = null, Color? max = null)
{
Color minimum = min ?? new Color(0, 0, 0, 0);
Color maximum = max ?? new Color(1, 1, 1, 1);
@@ -288,7 +288,7 @@ namespace Godot
/// </summary>
/// <param name="amount">The ratio to darken by.</param>
/// <returns>The darkened color.</returns>
- public Color Darkened(float amount)
+ public readonly Color Darkened(float amount)
{
Color res = this;
res.r *= 1.0f - amount;
@@ -301,7 +301,7 @@ namespace Godot
/// Returns the inverted color: <c>(1 - r, 1 - g, 1 - b, a)</c>.
/// </summary>
/// <returns>The inverted color.</returns>
- public Color Inverted()
+ public readonly Color Inverted()
{
return new Color(
1.0f - r,
@@ -317,7 +317,7 @@ namespace Godot
/// </summary>
/// <param name="amount">The ratio to lighten by.</param>
/// <returns>The darkened color.</returns>
- public Color Lightened(float amount)
+ public readonly Color Lightened(float amount)
{
Color res = this;
res.r += (1.0f - res.r) * amount;
@@ -333,7 +333,7 @@ namespace Godot
/// <param name="to">The destination color for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting color of the interpolation.</returns>
- public Color Lerp(Color to, real_t weight)
+ public readonly Color Lerp(Color to, real_t weight)
{
return new Color
(
@@ -351,7 +351,7 @@ namespace Godot
/// <param name="to">The destination color for interpolation.</param>
/// <param name="weight">A color with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting color of the interpolation.</returns>
- public Color Lerp(Color to, Color weight)
+ public readonly Color Lerp(Color to, Color weight)
{
return new Color
(
@@ -368,7 +368,7 @@ namespace Godot
/// ABGR is the reversed version of the default format.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in ABGR32 format.</returns>
- public uint ToAbgr32()
+ public readonly uint ToAbgr32()
{
uint c = (byte)Math.Round(a * 255);
c <<= 8;
@@ -387,7 +387,7 @@ namespace Godot
/// ABGR is the reversed version of the default format.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in ABGR64 format.</returns>
- public ulong ToAbgr64()
+ public readonly ulong ToAbgr64()
{
ulong c = (ushort)Math.Round(a * 65535);
c <<= 16;
@@ -406,7 +406,7 @@ namespace Godot
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in ARGB32 format.</returns>
- public uint ToArgb32()
+ public readonly uint ToArgb32()
{
uint c = (byte)Math.Round(a * 255);
c <<= 8;
@@ -425,7 +425,7 @@ namespace Godot
/// ARGB is more compatible with DirectX, but not used much in Godot.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in ARGB64 format.</returns>
- public ulong ToArgb64()
+ public readonly ulong ToArgb64()
{
ulong c = (ushort)Math.Round(a * 65535);
c <<= 16;
@@ -444,7 +444,7 @@ namespace Godot
/// RGBA is Godot's default and recommended format.
/// </summary>
/// <returns>A <see langword="uint"/> representing this color in RGBA32 format.</returns>
- public uint ToRgba32()
+ public readonly uint ToRgba32()
{
uint c = (byte)Math.Round(r * 255);
c <<= 8;
@@ -463,7 +463,7 @@ namespace Godot
/// RGBA is Godot's default and recommended format.
/// </summary>
/// <returns>A <see langword="ulong"/> representing this color in RGBA64 format.</returns>
- public ulong ToRgba64()
+ public readonly ulong ToRgba64()
{
ulong c = (ushort)Math.Round(r * 65535);
c <<= 16;
@@ -483,7 +483,7 @@ namespace Godot
/// Whether or not to include alpha. If <see langword="false"/>, the color is RGB instead of RGBA.
/// </param>
/// <returns>A string for the HTML hexadecimal representation of this color.</returns>
- public string ToHTML(bool includeAlpha = true)
+ public readonly string ToHTML(bool includeAlpha = true)
{
string txt = string.Empty;
@@ -777,7 +777,7 @@ namespace Godot
/// <param name="hue">Output parameter for the HSV hue.</param>
/// <param name="saturation">Output parameter for the HSV saturation.</param>
/// <param name="value">Output parameter for the HSV value.</param>
- public void ToHSV(out float hue, out float saturation, out float value)
+ public readonly void ToHSV(out float hue, out float saturation, out float value)
{
float max = (float)Mathf.Max(r, Mathf.Max(g, b));
float min = (float)Mathf.Min(r, Mathf.Min(g, b));
@@ -1149,7 +1149,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the color and the other object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Color other && Equals(other);
}
@@ -1161,7 +1161,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other color.</param>
/// <returns>Whether or not the colors are equal.</returns>
- public bool Equals(Color other)
+ public readonly bool Equals(Color other)
{
return r == other.r && g == other.g && b == other.b && a == other.a;
}
@@ -1172,7 +1172,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other color to compare.</param>
/// <returns>Whether or not the colors are approximately equal.</returns>
- public bool IsEqualApprox(Color other)
+ public readonly bool IsEqualApprox(Color other)
{
return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a);
}
@@ -1181,7 +1181,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Color"/>.
/// </summary>
/// <returns>A hash code for this color.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode();
}
@@ -1190,7 +1190,7 @@ namespace Godot
/// Converts this <see cref="Color"/> to a string.
/// </summary>
/// <returns>A string representation of this color.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({r}, {g}, {b}, {a})";
}
@@ -1199,7 +1199,7 @@ namespace Godot
/// Converts this <see cref="Color"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this color.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({r.ToString(format)}, {g.ToString(format)}, {b.ToString(format)}, {a.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index 664b2e0f34..42c6b0a37e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -22,7 +22,7 @@ namespace Godot
/// <value>Equivalent to <see cref="x"/>, <see cref="y"/>, and <see cref="z"/>.</value>
public Vector3 Normal
{
- get { return _normal; }
+ readonly get { return _normal; }
set { _normal = value; }
}
@@ -32,7 +32,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s X value.</value>
public real_t x
{
- get
+ readonly get
{
return _normal.x;
}
@@ -48,7 +48,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s Y value.</value>
public real_t y
{
- get
+ readonly get
{
return _normal.y;
}
@@ -64,7 +64,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/>'s Z value.</value>
public real_t z
{
- get
+ readonly get
{
return _normal.z;
}
@@ -90,7 +90,7 @@ namespace Godot
/// <value>Equivalent to <see cref="Normal"/> multiplied by <see cref="D"/>.</value>
public Vector3 Center
{
- get
+ readonly get
{
return _normal * D;
}
@@ -106,7 +106,7 @@ namespace Godot
/// </summary>
/// <param name="point">The position to use for the calculation.</param>
/// <returns>The shortest distance.</returns>
- public real_t DistanceTo(Vector3 point)
+ public readonly real_t DistanceTo(Vector3 point)
{
return _normal.Dot(point) - D;
}
@@ -118,7 +118,7 @@ namespace Godot
/// <param name="point">The point to check.</param>
/// <param name="tolerance">The tolerance threshold.</param>
/// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns>
- public bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon)
+ public readonly bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon)
{
real_t dist = _normal.Dot(point) - D;
return Mathf.Abs(dist) <= tolerance;
@@ -131,7 +131,7 @@ namespace Godot
/// <param name="b">One of the three planes to use in the calculation.</param>
/// <param name="c">One of the three planes to use in the calculation.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? Intersect3(Plane b, Plane c)
+ public readonly Vector3? Intersect3(Plane b, Plane c)
{
real_t denom = _normal.Cross(b._normal).Dot(c._normal);
@@ -155,7 +155,7 @@ namespace Godot
/// <param name="from">The start of the ray.</param>
/// <param name="dir">The direction of the ray, normalized.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? IntersectRay(Vector3 from, Vector3 dir)
+ public readonly Vector3? IntersectRay(Vector3 from, Vector3 dir)
{
real_t den = _normal.Dot(dir);
@@ -183,7 +183,7 @@ namespace Godot
/// <param name="begin">The start of the line segment.</param>
/// <param name="end">The end of the line segment.</param>
/// <returns>The intersection, or <see langword="null"/> if none is found.</returns>
- public Vector3? IntersectSegment(Vector3 begin, Vector3 end)
+ public readonly Vector3? IntersectSegment(Vector3 begin, Vector3 end)
{
Vector3 segment = begin - end;
real_t den = _normal.Dot(segment);
@@ -209,7 +209,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to check.</param>
/// <returns>A <see langword="bool"/> for whether or not the point is above the plane.</returns>
- public bool IsPointOver(Vector3 point)
+ public readonly bool IsPointOver(Vector3 point)
{
return _normal.Dot(point) > D;
}
@@ -218,7 +218,7 @@ namespace Godot
/// Returns the plane scaled to unit length.
/// </summary>
/// <returns>A normalized version of the plane.</returns>
- public Plane Normalized()
+ public readonly Plane Normalized()
{
real_t len = _normal.Length();
@@ -235,7 +235,7 @@ namespace Godot
/// </summary>
/// <param name="point">The point to project.</param>
/// <returns>The projected point.</returns>
- public Vector3 Project(Vector3 point)
+ public readonly Vector3 Project(Vector3 point)
{
return point - (_normal * DistanceTo(point));
}
@@ -363,7 +363,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the plane and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Plane other && Equals(other);
}
@@ -373,7 +373,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other plane to compare.</param>
/// <returns>Whether or not the planes are exactly equal.</returns>
- public bool Equals(Plane other)
+ public readonly bool Equals(Plane other)
{
return _normal == other._normal && D == other.D;
}
@@ -384,7 +384,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other plane to compare.</param>
/// <returns>Whether or not the planes are approximately equal.</returns>
- public bool IsEqualApprox(Plane other)
+ public readonly bool IsEqualApprox(Plane other)
{
return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(D, other.D);
}
@@ -393,7 +393,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Plane"/>.
/// </summary>
/// <returns>A hash code for this plane.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _normal.GetHashCode() ^ D.GetHashCode();
}
@@ -402,7 +402,7 @@ namespace Godot
/// Converts this <see cref="Plane"/> to a string.
/// </summary>
/// <returns>A string representation of this plane.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_normal}, {D}";
}
@@ -411,7 +411,7 @@ namespace Godot
/// Converts this <see cref="Plane"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this plane.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_normal.ToString(format)}, {D.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
index da895fd121..371729ebec 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
@@ -286,7 +286,7 @@ namespace Godot
return proj * cm;
}
- public real_t Determinant()
+ public readonly real_t Determinant()
{
return x.w * y.z * z.y * w.x - x.z * y.w * z.y * w.x -
x.w * y.y * z.z * w.x + x.y * y.w * z.z * w.x +
@@ -302,13 +302,13 @@ namespace Godot
x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w;
}
- public real_t GetAspect()
+ public readonly real_t GetAspect()
{
Vector2 vpHe = GetViewportHalfExtents();
return vpHe.x / vpHe.y;
}
- public real_t GetFov()
+ public readonly real_t GetFov()
{
Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized();
if (z.x == 0 && z.y == 0)
@@ -327,7 +327,7 @@ namespace Godot
return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0);
}
- public real_t GetLodMultiplier()
+ public readonly real_t GetLodMultiplier()
{
if (IsOrthogonal())
{
@@ -341,14 +341,14 @@ namespace Godot
}
}
- public int GetPixelsPerMeter(int forPixelWidth)
+ public readonly int GetPixelsPerMeter(int forPixelWidth)
{
Vector3 result = this * new Vector3(1, 0, -1);
return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth);
}
- public Plane GetProjectionPlane(Planes plane)
+ public readonly Plane GetProjectionPlane(Planes plane)
{
Plane newPlane = plane switch
{
@@ -364,36 +364,36 @@ namespace Godot
return newPlane.Normalized();
}
- public Vector2 GetFarPlaneHalfExtents()
+ public readonly Vector2 GetFarPlaneHalfExtents()
{
var res = GetProjectionPlane(Planes.Far).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
return new Vector2(res.Value.x, res.Value.y);
}
- public Vector2 GetViewportHalfExtents()
+ public readonly Vector2 GetViewportHalfExtents()
{
var res = GetProjectionPlane(Planes.Near).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
return new Vector2(res.Value.x, res.Value.y);
}
- public real_t GetZFar()
+ public readonly real_t GetZFar()
{
return GetProjectionPlane(Planes.Far).D;
}
- public real_t GetZNear()
+ public readonly real_t GetZNear()
{
return -GetProjectionPlane(Planes.Near).D;
}
- public Projection FlippedY()
+ public readonly Projection FlippedY()
{
Projection proj = this;
proj.y = -proj.y;
return proj;
}
- public Projection PerspectiveZNearAdjusted(real_t newZNear)
+ public readonly Projection PerspectiveZNearAdjusted(real_t newZNear)
{
Projection proj = this;
real_t zFar = GetZFar();
@@ -404,7 +404,7 @@ namespace Godot
return proj;
}
- public Projection JitterOffseted(Vector2 offset)
+ public readonly Projection JitterOffseted(Vector2 offset)
{
Projection proj = this;
proj.w.x += offset.x;
@@ -412,7 +412,7 @@ namespace Godot
return proj;
}
- public Projection Inverse()
+ public readonly Projection Inverse()
{
Projection proj = this;
int i, j, k;
@@ -535,7 +535,7 @@ namespace Godot
return proj;
}
- public bool IsOrthogonal()
+ public readonly bool IsOrthogonal()
{
return w.w == (real_t)1.0;
}
@@ -654,7 +654,7 @@ namespace Godot
/// </exception>
public Vector4 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -702,7 +702,7 @@ namespace Godot
/// </exception>
public real_t this[int column, int row]
{
- get
+ readonly get
{
switch (column)
{
@@ -772,7 +772,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Projection"/>.
/// </summary>
/// <returns>A hash code for this projection.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -781,7 +781,7 @@ namespace Godot
/// Converts this <see cref="Projection"/> to a string.
/// </summary>
/// <returns>A string representation of this projection.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{x.x}, {x.y}, {x.z}, {x.w}\n{y.x}, {y.y}, {y.z}, {y.w}\n{z.x}, {z.y}, {z.z}, {z.w}\n{w.x}, {w.y}, {w.z}, {w.w}\n";
}
@@ -790,7 +790,7 @@ namespace Godot
/// Converts this <see cref="Projection"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this projection.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{x.x.ToString(format)}, {x.y.ToString(format)}, {x.z.ToString(format)}, {x.w.ToString(format)}\n" +
$"{y.x.ToString(format)}, {y.y.ToString(format)}, {y.z.ToString(format)}, {y.w.ToString(format)}\n" +
@@ -804,7 +804,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Projection other && Equals(other);
}
@@ -814,7 +814,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other projection.</param>
/// <returns>Whether or not the projections are exactly equal.</returns>
- public bool Equals(Projection other)
+ public readonly bool Equals(Projection other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
index f01f0be985..c55003586b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -101,7 +101,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <value>Equivalent to <c>Mathf.Sqrt(LengthSquared)</c>.</value>
- public real_t Length
+ public readonly real_t Length
{
get { return Mathf.Sqrt(LengthSquared); }
}
@@ -112,7 +112,7 @@ namespace Godot
/// you need to compare quaternions or need the squared length for some formula.
/// </summary>
/// <value>Equivalent to <c>Dot(this)</c>.</value>
- public real_t LengthSquared
+ public readonly real_t LengthSquared
{
get { return Dot(this); }
}
@@ -128,7 +128,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other quaternion.</param>
/// <returns>The angle between the quaternions.</returns>
- public real_t AngleTo(Quaternion to)
+ public readonly real_t AngleTo(Quaternion to)
{
real_t dot = Dot(to);
return Mathf.Acos(Mathf.Clamp(dot * dot * 2 - 1, -1, 1));
@@ -143,7 +143,7 @@ namespace Godot
/// <param name="postB">A quaternion after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated quaternion.</returns>
- public Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
+ public readonly Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -212,7 +212,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated quaternion.</returns>
- public Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT)
+ public readonly Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT)
{
#if DEBUG
if (!IsNormalized())
@@ -272,12 +272,12 @@ namespace Godot
/// </summary>
/// <param name="b">The other quaternion.</param>
/// <returns>The dot product.</returns>
- public real_t Dot(Quaternion b)
+ public readonly real_t Dot(Quaternion b)
{
return (x * b.x) + (y * b.y) + (z * b.z) + (w * b.w);
}
- public Quaternion Exp()
+ public readonly Quaternion Exp()
{
Vector3 v = new Vector3(x, y, z);
real_t theta = v.Length();
@@ -289,12 +289,12 @@ namespace Godot
return new Quaternion(v, theta);
}
- public real_t GetAngle()
+ public readonly real_t GetAngle()
{
return 2 * Mathf.Acos(w);
}
- public Vector3 GetAxis()
+ public readonly Vector3 GetAxis()
{
if (Mathf.Abs(w) > 1 - Mathf.Epsilon)
{
@@ -312,7 +312,7 @@ namespace Godot
/// the rotation angles in the format (X angle, Y angle, Z angle).
/// </summary>
/// <returns>The Euler angle representation of this quaternion.</returns>
- public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
+ public readonly Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz)
{
#if DEBUG
if (!IsNormalized())
@@ -328,7 +328,7 @@ namespace Godot
/// Returns the inverse of the quaternion.
/// </summary>
/// <returns>The inverse quaternion.</returns>
- public Quaternion Inverse()
+ public readonly Quaternion Inverse()
{
#if DEBUG
if (!IsNormalized())
@@ -343,12 +343,12 @@ namespace Godot
/// Returns whether the quaternion is normalized or not.
/// </summary>
/// <returns>A <see langword="bool"/> for whether the quaternion is normalized or not.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
}
- public Quaternion Log()
+ public readonly Quaternion Log()
{
Vector3 v = GetAxis() * GetAngle();
return new Quaternion(v.x, v.y, v.z, 0);
@@ -358,7 +358,7 @@ namespace Godot
/// Returns a copy of the quaternion, normalized to unit length.
/// </summary>
/// <returns>The normalized quaternion.</returns>
- public Quaternion Normalized()
+ public readonly Quaternion Normalized()
{
return this / Length;
}
@@ -372,7 +372,7 @@ namespace Godot
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting quaternion of the interpolation.</returns>
- public Quaternion Slerp(Quaternion to, real_t weight)
+ public readonly Quaternion Slerp(Quaternion to, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -437,7 +437,7 @@ namespace Godot
/// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting quaternion of the interpolation.</returns>
- public Quaternion Slerpni(Quaternion to, real_t weight)
+ public readonly Quaternion Slerpni(Quaternion to, real_t weight)
{
#if DEBUG
if (!IsNormalized())
@@ -762,7 +762,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the quaternion and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Quaternion other && Equals(other);
}
@@ -772,7 +772,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other quaternion to compare.</param>
/// <returns>Whether or not the quaternions are exactly equal.</returns>
- public bool Equals(Quaternion other)
+ public readonly bool Equals(Quaternion other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -783,7 +783,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other quaternion to compare.</param>
/// <returns>Whether or not the quaternions are approximately equal.</returns>
- public bool IsEqualApprox(Quaternion other)
+ public readonly bool IsEqualApprox(Quaternion other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
}
@@ -792,7 +792,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Quaternion"/>.
/// </summary>
/// <returns>A hash code for this quaternion.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -801,7 +801,7 @@ namespace Godot
/// Converts this <see cref="Quaternion"/> to a string.
/// </summary>
/// <returns>A string representation of this quaternion.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z}, {w})";
}
@@ -810,7 +810,7 @@ namespace Godot
/// Converts this <see cref="Quaternion"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this quaternion.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
index a31fef8360..59b9faf16c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/RID.cs
@@ -12,9 +12,9 @@ namespace Godot
/// classes such as <see cref="RenderingServer"/>.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
- public struct RID
+ public readonly struct RID
{
- private ulong _id; // Default is 0
+ private readonly ulong _id; // Default is 0
internal RID(ulong id)
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index e80d75dacf..b0e0e75a34 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2 Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2 Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector2 End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -53,7 +53,7 @@ namespace Godot
/// The area of this <see cref="Rect2"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public real_t Area
+ public readonly real_t Area
{
get { return GetArea(); }
}
@@ -63,7 +63,7 @@ namespace Godot
/// the top-left corner is the origin and width and height are positive.
/// </summary>
/// <returns>The modified <see cref="Rect2"/>.</returns>
- public Rect2 Abs()
+ public readonly Rect2 Abs()
{
Vector2 end = End;
Vector2 topLeft = new Vector2(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
@@ -79,7 +79,7 @@ namespace Godot
/// The intersection of this <see cref="Rect2"/> and <paramref name="b"/>,
/// or an empty <see cref="Rect2"/> if they do not intersect.
/// </returns>
- public Rect2 Intersection(Rect2 b)
+ public readonly Rect2 Intersection(Rect2 b)
{
Rect2 newRect = b;
@@ -107,7 +107,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="Rect2"/> encloses <paramref name="b"/>.
/// </returns>
- public bool Encloses(Rect2 b)
+ public readonly bool Encloses(Rect2 b)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
b._position.x + b._size.x < _position.x + _size.x &&
@@ -119,7 +119,7 @@ namespace Godot
/// </summary>
/// <param name="to">The point to include.</param>
/// <returns>The expanded <see cref="Rect2"/>.</returns>
- public Rect2 Expand(Vector2 to)
+ public readonly Rect2 Expand(Vector2 to)
{
Rect2 expanded = this;
@@ -154,7 +154,7 @@ namespace Godot
/// Returns the area of the <see cref="Rect2"/>.
/// </summary>
/// <returns>The area.</returns>
- public real_t GetArea()
+ public readonly real_t GetArea()
{
return _size.x * _size.y;
}
@@ -164,7 +164,7 @@ namespace Godot
/// to <see cref="Position"/> + (<see cref="Size"/> / 2).
/// </summary>
/// <returns>The center.</returns>
- public Vector2 GetCenter()
+ public readonly Vector2 GetCenter()
{
return _position + (_size * 0.5f);
}
@@ -177,7 +177,7 @@ namespace Godot
/// <seealso cref="GrowSide(Side, real_t)"/>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 Grow(real_t by)
+ public readonly Rect2 Grow(real_t by)
{
Rect2 g = this;
@@ -200,7 +200,7 @@ namespace Godot
/// <param name="right">The amount to grow by on the right side.</param>
/// <param name="bottom">The amount to grow by on the bottom side.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
+ public readonly Rect2 GrowIndividual(real_t left, real_t top, real_t right, real_t bottom)
{
Rect2 g = this;
@@ -221,7 +221,7 @@ namespace Godot
/// <param name="side">The side to grow.</param>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2"/>.</returns>
- public Rect2 GrowSide(Side side, real_t by)
+ public readonly Rect2 GrowSide(Side side, real_t by)
{
Rect2 g = this;
@@ -242,7 +242,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> has area.
/// </returns>
- public bool HasArea()
+ public readonly bool HasArea()
{
return _size.x > 0.0f && _size.y > 0.0f;
}
@@ -255,7 +255,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector2 point)
+ public readonly bool HasPoint(Vector2 point)
{
if (point.x < _position.x)
return false;
@@ -281,7 +281,7 @@ namespace Godot
/// <param name="b">The other <see cref="Rect2"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
/// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
- public bool Intersects(Rect2 b, bool includeBorders = false)
+ public readonly bool Intersects(Rect2 b, bool includeBorders = false)
{
if (includeBorders)
{
@@ -330,7 +330,7 @@ namespace Godot
/// </summary>
/// <param name="b">The other <see cref="Rect2"/>.</param>
/// <returns>The merged <see cref="Rect2"/>.</returns>
- public Rect2 Merge(Rect2 b)
+ public readonly Rect2 Merge(Rect2 b)
{
Rect2 newRect;
@@ -426,7 +426,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the rect and the other object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Rect2 other && Equals(other);
}
@@ -436,7 +436,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are exactly equal.</returns>
- public bool Equals(Rect2 other)
+ public readonly bool Equals(Rect2 other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
@@ -447,7 +447,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are approximately equal.</returns>
- public bool IsEqualApprox(Rect2 other)
+ public readonly bool IsEqualApprox(Rect2 other)
{
return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size);
}
@@ -456,7 +456,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Rect2"/>.
/// </summary>
/// <returns>A hash code for this rect.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -465,7 +465,7 @@ namespace Godot
/// Converts this <see cref="Rect2"/> to a string.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -474,7 +474,7 @@ namespace Godot
/// Converts this <see cref="Rect2"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
index b2768476cc..faee81a98a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
@@ -20,7 +20,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2i Position
{
- get { return _position; }
+ readonly get { return _position; }
set { _position = value; }
}
@@ -31,7 +31,7 @@ namespace Godot
/// <value>Directly uses a private field.</value>
public Vector2i Size
{
- get { return _size; }
+ readonly get { return _size; }
set { _size = value; }
}
@@ -45,7 +45,7 @@ namespace Godot
/// </value>
public Vector2i End
{
- get { return _position + _size; }
+ readonly get { return _position + _size; }
set { _size = value - _position; }
}
@@ -53,7 +53,7 @@ namespace Godot
/// The area of this <see cref="Rect2i"/>.
/// </summary>
/// <value>Equivalent to <see cref="GetArea()"/>.</value>
- public int Area
+ public readonly int Area
{
get { return GetArea(); }
}
@@ -63,7 +63,7 @@ namespace Godot
/// the top-left corner is the origin and width and height are positive.
/// </summary>
/// <returns>The modified <see cref="Rect2i"/>.</returns>
- public Rect2i Abs()
+ public readonly Rect2i Abs()
{
Vector2i end = End;
Vector2i topLeft = new Vector2i(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y));
@@ -79,7 +79,7 @@ namespace Godot
/// The intersection of this <see cref="Rect2i"/> and <paramref name="b"/>,
/// or an empty <see cref="Rect2i"/> if they do not intersect.
/// </returns>
- public Rect2i Intersection(Rect2i b)
+ public readonly Rect2i Intersection(Rect2i b)
{
Rect2i newRect = b;
@@ -107,7 +107,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not this <see cref="Rect2i"/> encloses <paramref name="b"/>.
/// </returns>
- public bool Encloses(Rect2i b)
+ public readonly bool Encloses(Rect2i b)
{
return b._position.x >= _position.x && b._position.y >= _position.y &&
b._position.x + b._size.x < _position.x + _size.x &&
@@ -119,7 +119,7 @@ namespace Godot
/// </summary>
/// <param name="to">The point to include.</param>
/// <returns>The expanded <see cref="Rect2i"/>.</returns>
- public Rect2i Expand(Vector2i to)
+ public readonly Rect2i Expand(Vector2i to)
{
Rect2i expanded = this;
@@ -154,7 +154,7 @@ namespace Godot
/// Returns the area of the <see cref="Rect2i"/>.
/// </summary>
/// <returns>The area.</returns>
- public int GetArea()
+ public readonly int GetArea()
{
return _size.x * _size.y;
}
@@ -166,7 +166,7 @@ namespace Godot
/// value will be rounded towards <see cref="Position"/>.
/// </summary>
/// <returns>The center.</returns>
- public Vector2i GetCenter()
+ public readonly Vector2i GetCenter()
{
return _position + (_size / 2);
}
@@ -179,7 +179,7 @@ namespace Godot
/// <seealso cref="GrowSide(Side, int)"/>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i Grow(int by)
+ public readonly Rect2i Grow(int by)
{
Rect2i g = this;
@@ -202,7 +202,7 @@ namespace Godot
/// <param name="right">The amount to grow by on the right side.</param>
/// <param name="bottom">The amount to grow by on the bottom side.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i GrowIndividual(int left, int top, int right, int bottom)
+ public readonly Rect2i GrowIndividual(int left, int top, int right, int bottom)
{
Rect2i g = this;
@@ -223,7 +223,7 @@ namespace Godot
/// <param name="side">The side to grow.</param>
/// <param name="by">The amount to grow by.</param>
/// <returns>The grown <see cref="Rect2i"/>.</returns>
- public Rect2i GrowSide(Side side, int by)
+ public readonly Rect2i GrowSide(Side side, int by)
{
Rect2i g = this;
@@ -244,7 +244,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> has area.
/// </returns>
- public bool HasArea()
+ public readonly bool HasArea()
{
return _size.x > 0 && _size.y > 0;
}
@@ -257,7 +257,7 @@ namespace Godot
/// <returns>
/// A <see langword="bool"/> for whether or not the <see cref="Rect2i"/> contains <paramref name="point"/>.
/// </returns>
- public bool HasPoint(Vector2i point)
+ public readonly bool HasPoint(Vector2i point)
{
if (point.x < _position.x)
return false;
@@ -283,7 +283,7 @@ namespace Godot
/// <param name="b">The other <see cref="Rect2i"/> to check for intersections with.</param>
/// <param name="includeBorders">Whether or not to consider borders.</param>
/// <returns>A <see langword="bool"/> for whether or not they are intersecting.</returns>
- public bool Intersects(Rect2i b, bool includeBorders = false)
+ public readonly bool Intersects(Rect2i b, bool includeBorders = false)
{
if (includeBorders)
{
@@ -316,7 +316,7 @@ namespace Godot
/// </summary>
/// <param name="b">The other <see cref="Rect2i"/>.</param>
/// <returns>The merged <see cref="Rect2i"/>.</returns>
- public Rect2i Merge(Rect2i b)
+ public readonly Rect2i Merge(Rect2i b)
{
Rect2i newRect;
@@ -426,7 +426,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The other object to compare.</param>
/// <returns>Whether or not the rect and the other object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Rect2i other && Equals(other);
}
@@ -436,7 +436,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other rect to compare.</param>
/// <returns>Whether or not the rects are equal.</returns>
- public bool Equals(Rect2i other)
+ public readonly bool Equals(Rect2i other)
{
return _position.Equals(other._position) && _size.Equals(other._size);
}
@@ -445,7 +445,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Rect2i"/>.
/// </summary>
/// <returns>A hash code for this rect.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
}
@@ -454,7 +454,7 @@ namespace Godot
/// Converts this <see cref="Rect2i"/> to a string.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"{_position}, {_size}";
}
@@ -463,7 +463,7 @@ namespace Godot
/// Converts this <see cref="Rect2i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this rect.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"{_position.ToString(format)}, {_size.ToString(format)}";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index d77baab24b..f511233fcc 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -229,7 +229,6 @@ namespace Godot
sb.Replace("\v", "\\v");
sb.Replace("\'", "\\'");
sb.Replace("\"", "\\\"");
- sb.Replace("?", "\\?");
return sb.ToString();
}
@@ -253,7 +252,6 @@ namespace Godot
sb.Replace("\\v", "\v");
sb.Replace("\\'", "\'");
sb.Replace("\\\"", "\"");
- sb.Replace("\\?", "?");
sb.Replace("\\\\", "\\");
return sb.ToString();
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index 894667db76..756f71e5b2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -37,7 +37,7 @@ namespace Godot
/// <value>Getting is equivalent to calling <see cref="Mathf.Atan2(real_t, real_t)"/> with the values of <see cref="x"/>.</value>
public real_t Rotation
{
- get
+ readonly get
{
return Mathf.Atan2(x.y, x.x);
}
@@ -57,7 +57,7 @@ namespace Godot
/// <value>Equivalent to the lengths of each column vector, but Y is negative if the determinant is negative.</value>
public Vector2 Scale
{
- get
+ readonly get
{
real_t detSign = Mathf.Sign(BasisDeterminant());
return new Vector2(x.Length(), detSign * y.Length());
@@ -80,7 +80,7 @@ namespace Godot
/// </exception>
public Vector2 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -121,7 +121,7 @@ namespace Godot
/// <param name="row">Which row, the matrix vertical position.</param>
public real_t this[int column, int row]
{
- get
+ readonly get
{
return this[column][row];
}
@@ -139,7 +139,7 @@ namespace Godot
/// </summary>
/// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
- public Transform2D AffineInverse()
+ public readonly Transform2D AffineInverse()
{
real_t det = BasisDeterminant();
@@ -148,9 +148,8 @@ namespace Godot
Transform2D inv = this;
- real_t temp = inv[0, 0];
- inv[0, 0] = inv[1, 1];
- inv[1, 1] = temp;
+ inv[0, 0] = this[1, 1];
+ inv[1, 1] = this[0, 0];
real_t detInv = 1.0f / det;
@@ -171,7 +170,7 @@ namespace Godot
/// and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
- private real_t BasisDeterminant()
+ private readonly real_t BasisDeterminant()
{
return (x.x * y.y) - (x.y * y.x);
}
@@ -183,7 +182,7 @@ namespace Godot
/// <seealso cref="BasisXformInv(Vector2)"/>
/// <param name="v">A vector to transform.</param>
/// <returns>The transformed vector.</returns>
- public Vector2 BasisXform(Vector2 v)
+ public readonly Vector2 BasisXform(Vector2 v)
{
return new Vector2(Tdotx(v), Tdoty(v));
}
@@ -198,7 +197,7 @@ namespace Godot
/// <seealso cref="BasisXform(Vector2)"/>
/// <param name="v">A vector to inversely transform.</param>
/// <returns>The inversely transformed vector.</returns>
- public Vector2 BasisXformInv(Vector2 v)
+ public readonly Vector2 BasisXformInv(Vector2 v)
{
return new Vector2(x.Dot(v), y.Dot(v));
}
@@ -209,7 +208,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform2D InterpolateWith(Transform2D transform, real_t weight)
+ public readonly Transform2D InterpolateWith(Transform2D transform, real_t weight)
{
real_t r1 = Rotation;
real_t r2 = transform.Rotation;
@@ -258,14 +257,13 @@ namespace Godot
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Transform2D Inverse()
+ public readonly Transform2D Inverse()
{
Transform2D inv = this;
// Swap
- real_t temp = inv.x.y;
- inv.x.y = inv.y.x;
- inv.y.x = temp;
+ inv.x.y = y.x;
+ inv.y.x = x.y;
inv.origin = inv.BasisXform(-inv.origin);
@@ -277,7 +275,7 @@ namespace Godot
/// and normalized axis vectors (scale of 1 or -1).
/// </summary>
/// <returns>The orthonormalized transform.</returns>
- public Transform2D Orthonormalized()
+ public readonly Transform2D Orthonormalized()
{
Transform2D on = this;
@@ -301,7 +299,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform2D Rotated(real_t angle)
+ public readonly Transform2D Rotated(real_t angle)
{
return this * new Transform2D(angle, new Vector2());
}
@@ -313,7 +311,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform2D RotatedLocal(real_t angle)
+ public readonly Transform2D RotatedLocal(real_t angle)
{
return new Transform2D(angle, new Vector2()) * this;
}
@@ -325,7 +323,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform2D Scaled(Vector2 scale)
+ public readonly Transform2D Scaled(Vector2 scale)
{
Transform2D copy = this;
copy.x *= scale;
@@ -341,7 +339,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform2D ScaledLocal(Vector2 scale)
+ public readonly Transform2D ScaledLocal(Vector2 scale)
{
Transform2D copy = this;
copy.x *= scale;
@@ -349,12 +347,12 @@ namespace Godot
return copy;
}
- private real_t Tdotx(Vector2 with)
+ private readonly real_t Tdotx(Vector2 with)
{
return (this[0, 0] * with[0]) + (this[1, 0] * with[1]);
}
- private real_t Tdoty(Vector2 with)
+ private readonly real_t Tdoty(Vector2 with)
{
return (this[0, 1] * with[0]) + (this[1, 1] * with[1]);
}
@@ -366,7 +364,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform2D Translated(Vector2 offset)
+ public readonly Transform2D Translated(Vector2 offset)
{
Transform2D copy = this;
copy.origin += offset;
@@ -380,7 +378,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform2D TranslatedLocal(Vector2 offset)
+ public readonly Transform2D TranslatedLocal(Vector2 offset)
{
Transform2D copy = this;
copy.origin += copy.BasisXform(offset);
@@ -603,7 +601,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the transform and the object are exactly equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Transform2D other && Equals(other);
}
@@ -615,7 +613,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are exactly equal.</returns>
- public bool Equals(Transform2D other)
+ public readonly bool Equals(Transform2D other)
{
return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin);
}
@@ -626,7 +624,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform2D other)
+ public readonly bool IsEqualApprox(Transform2D other)
{
return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && origin.IsEqualApprox(other.origin);
}
@@ -635,7 +633,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Transform2D"/>.
/// </summary>
/// <returns>A hash code for this transform.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ origin.GetHashCode();
}
@@ -644,7 +642,7 @@ namespace Godot
/// Converts this <see cref="Transform2D"/> to a string.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {x}, Y: {y}, O: {origin}]";
}
@@ -653,7 +651,7 @@ namespace Godot
/// Converts this <see cref="Transform2D"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {x.ToString(format)}, Y: {y.ToString(format)}, O: {origin.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index 2f7891e7ef..39167bd116 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -37,7 +37,7 @@ namespace Godot
/// </exception>
public Vector3 this[int column]
{
- get
+ readonly get
{
switch (column)
{
@@ -83,7 +83,7 @@ namespace Godot
/// <param name="row">Which row, the matrix vertical position.</param>
public real_t this[int column, int row]
{
- get
+ readonly get
{
if (column == 3)
{
@@ -108,7 +108,7 @@ namespace Godot
/// </summary>
/// <seealso cref="Inverse"/>
/// <returns>The inverse transformation matrix.</returns>
- public Transform3D AffineInverse()
+ public readonly Transform3D AffineInverse()
{
Basis basisInv = basis.Inverse();
return new Transform3D(basisInv, basisInv * -origin);
@@ -120,7 +120,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform3D InterpolateWith(Transform3D transform, real_t weight)
+ public readonly Transform3D InterpolateWith(Transform3D transform, real_t weight)
{
Basis retBasis = basis.Lerp(transform.basis, weight);
Vector3 retOrigin = origin.Lerp(transform.origin, weight);
@@ -133,7 +133,7 @@ namespace Godot
/// (no scaling, use <see cref="AffineInverse"/> for transforms with scaling).
/// </summary>
/// <returns>The inverse matrix.</returns>
- public Transform3D Inverse()
+ public readonly Transform3D Inverse()
{
Basis basisTr = basis.Transposed();
return new Transform3D(basisTr, basisTr * -origin);
@@ -164,7 +164,7 @@ namespace Godot
/// and normalized axis vectors (scale of 1 or -1).
/// </summary>
/// <returns>The orthonormalized transform.</returns>
- public Transform3D Orthonormalized()
+ public readonly Transform3D Orthonormalized()
{
return new Transform3D(basis.Orthonormalized(), origin);
}
@@ -192,7 +192,7 @@ namespace Godot
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
- public Transform3D RotatedLocal(Vector3 axis, real_t angle)
+ public readonly Transform3D RotatedLocal(Vector3 axis, real_t angle)
{
Basis tmpBasis = new Basis(axis, angle);
return new Transform3D(basis * tmpBasis, origin);
@@ -205,7 +205,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform3D Scaled(Vector3 scale)
+ public readonly Transform3D Scaled(Vector3 scale)
{
return new Transform3D(basis.Scaled(scale), origin * scale);
}
@@ -217,7 +217,7 @@ namespace Godot
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
- public Transform3D ScaledLocal(Vector3 scale)
+ public readonly Transform3D ScaledLocal(Vector3 scale)
{
Basis tmpBasis = Basis.FromScale(scale);
return new Transform3D(basis * tmpBasis, origin);
@@ -230,7 +230,7 @@ namespace Godot
/// <param name="transform">The other transform.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated transform.</returns>
- public Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight)
+ public readonly Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight)
{
/* not sure if very "efficient" but good enough? */
@@ -281,7 +281,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform3D Translated(Vector3 offset)
+ public readonly Transform3D Translated(Vector3 offset)
{
return new Transform3D(basis, origin + offset);
}
@@ -293,7 +293,7 @@ namespace Godot
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
- public Transform3D TranslatedLocal(Vector3 offset)
+ public readonly Transform3D TranslatedLocal(Vector3 offset)
{
return new Transform3D(basis, new Vector3
(
@@ -617,7 +617,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other transform to compare.</param>
/// <returns>Whether or not the matrices are approximately equal.</returns>
- public bool IsEqualApprox(Transform3D other)
+ public readonly bool IsEqualApprox(Transform3D other)
{
return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
}
@@ -626,7 +626,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Transform3D"/>.
/// </summary>
/// <returns>A hash code for this transform.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return basis.GetHashCode() ^ origin.GetHashCode();
}
@@ -635,7 +635,7 @@ namespace Godot
/// Converts this <see cref="Transform3D"/> to a string.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"[X: {basis.x}, Y: {basis.y}, Z: {basis.z}, O: {origin}]";
}
@@ -644,7 +644,7 @@ namespace Godot
/// Converts this <see cref="Transform3D"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this transform.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"[X: {basis.x.ToString(format)}, Y: {basis.y.ToString(format)}, Z: {basis.z.ToString(format)}, O: {origin.ToString(format)}]";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 87f397891e..535391f447 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -48,7 +48,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -79,7 +79,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y)
+ public readonly void Deconstruct(out real_t x, out real_t y)
{
x = this.x;
y = this.y;
@@ -105,7 +105,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
- public Vector2 Abs()
+ public readonly Vector2 Abs()
{
return new Vector2(Mathf.Abs(x), Mathf.Abs(y));
}
@@ -117,7 +117,7 @@ namespace Godot
/// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
/// </summary>
/// <returns>The angle of this vector, in radians.</returns>
- public real_t Angle()
+ public readonly real_t Angle()
{
return Mathf.Atan2(y, x);
}
@@ -127,7 +127,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector2 to)
+ public readonly real_t AngleTo(Vector2 to)
{
return Mathf.Atan2(Cross(to), Dot(to));
}
@@ -137,7 +137,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleToPoint(Vector2 to)
+ public readonly real_t AngleToPoint(Vector2 to)
{
return Mathf.Atan2(y - to.y, x - to.x);
}
@@ -146,7 +146,7 @@ namespace Godot
/// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
/// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
- public real_t Aspect()
+ public readonly real_t Aspect()
{
return x / y;
}
@@ -156,7 +156,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
/// <returns>The bounced vector.</returns>
- public Vector2 Bounce(Vector2 normal)
+ public readonly Vector2 Bounce(Vector2 normal)
{
return -Reflect(normal);
}
@@ -165,7 +165,7 @@ namespace Godot
/// Returns a new vector with all components rounded up (towards positive infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
- public Vector2 Ceil()
+ public readonly Vector2 Ceil()
{
return new Vector2(Mathf.Ceil(x), Mathf.Ceil(y));
}
@@ -178,7 +178,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector2 Clamp(Vector2 min, Vector2 max)
+ public readonly Vector2 Clamp(Vector2 min, Vector2 max)
{
return new Vector2
(
@@ -192,7 +192,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product value.</returns>
- public real_t Cross(Vector2 with)
+ public readonly real_t Cross(Vector2 with)
{
return (x * with.y) - (y * with.x);
}
@@ -206,7 +206,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight)
+ public readonly Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight)
{
return new Vector2
(
@@ -229,7 +229,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector2
(
@@ -247,7 +247,7 @@ namespace Godot
/// <param name="end">The destination vector.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
+ public readonly Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
{
// Formula from Wikipedia article on Bezier curves
real_t omt = 1 - t;
@@ -264,7 +264,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector2 DirectionTo(Vector2 to)
+ public readonly Vector2 DirectionTo(Vector2 to)
{
return new Vector2(to.x - x, to.y - y).Normalized();
}
@@ -276,7 +276,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector2 to)
+ public readonly real_t DistanceSquaredTo(Vector2 to)
{
return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y);
}
@@ -286,7 +286,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector2 to)
+ public readonly real_t DistanceTo(Vector2 to)
{
return Mathf.Sqrt((x - to.x) * (x - to.x) + (y - to.y) * (y - to.y));
}
@@ -296,7 +296,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector2 with)
+ public readonly real_t Dot(Vector2 with)
{
return (x * with.x) + (y * with.y);
}
@@ -305,7 +305,7 @@ namespace Godot
/// Returns a new vector with all components rounded down (towards negative infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
- public Vector2 Floor()
+ public readonly Vector2 Floor()
{
return new Vector2(Mathf.Floor(x), Mathf.Floor(y));
}
@@ -314,7 +314,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector2(1 / v.x, 1 / v.y)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector2 Inverse()
+ public readonly Vector2 Inverse()
{
return new Vector2(1 / x, 1 / y);
}
@@ -323,7 +323,7 @@ namespace Godot
/// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
/// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -333,7 +333,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
return Mathf.Sqrt((x * x) + (y * y));
}
@@ -344,7 +344,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public real_t LengthSquared()
+ public readonly real_t LengthSquared()
{
return (x * x) + (y * y);
}
@@ -356,7 +356,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector2 Lerp(Vector2 to, real_t weight)
+ public readonly Vector2 Lerp(Vector2 to, real_t weight)
{
return new Vector2
(
@@ -374,7 +374,7 @@ namespace Godot
/// A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.
/// </param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector2 Lerp(Vector2 to, Vector2 weight)
+ public readonly Vector2 Lerp(Vector2 to, Vector2 weight)
{
return new Vector2
(
@@ -388,7 +388,7 @@ namespace Godot
/// </summary>
/// <param name="length">The length to limit to.</param>
/// <returns>The vector with its length limited.</returns>
- public Vector2 LimitLength(real_t length = 1.0f)
+ public readonly Vector2 LimitLength(real_t length = 1.0f)
{
Vector2 v = this;
real_t l = Length();
@@ -407,7 +407,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? Axis.Y : Axis.X;
}
@@ -417,7 +417,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? Axis.X : Axis.Y;
}
@@ -428,7 +428,7 @@ namespace Godot
/// <param name="to">The vector to move towards.</param>
/// <param name="delta">The amount to move towards by.</param>
/// <returns>The resulting vector.</returns>
- public Vector2 MoveToward(Vector2 to, real_t delta)
+ public readonly Vector2 MoveToward(Vector2 to, real_t delta)
{
Vector2 v = this;
Vector2 vd = to - v;
@@ -443,7 +443,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector2 Normalized()
+ public readonly Vector2 Normalized()
{
Vector2 v = this;
v.Normalize();
@@ -458,7 +458,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector2 PosMod(real_t mod)
+ public readonly Vector2 PosMod(real_t mod)
{
Vector2 v;
v.x = Mathf.PosMod(x, mod);
@@ -474,7 +474,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector2 PosMod(Vector2 modv)
+ public readonly Vector2 PosMod(Vector2 modv)
{
Vector2 v;
v.x = Mathf.PosMod(x, modv.x);
@@ -487,7 +487,7 @@ namespace Godot
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
- public Vector2 Project(Vector2 onNormal)
+ public readonly Vector2 Project(Vector2 onNormal)
{
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
}
@@ -497,7 +497,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
- public Vector2 Reflect(Vector2 normal)
+ public readonly Vector2 Reflect(Vector2 normal)
{
#if DEBUG
if (!normal.IsNormalized())
@@ -513,7 +513,7 @@ namespace Godot
/// </summary>
/// <param name="angle">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
- public Vector2 Rotated(real_t angle)
+ public readonly Vector2 Rotated(real_t angle)
{
real_t sine = Mathf.Sin(angle);
real_t cosi = Mathf.Cos(angle);
@@ -527,7 +527,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector2 Round()
+ public readonly Vector2 Round()
{
return new Vector2(Mathf.Round(x), Mathf.Round(y));
}
@@ -538,7 +538,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector2 Sign()
+ public readonly Vector2 Sign()
{
Vector2 v;
v.x = Mathf.Sign(x);
@@ -557,7 +557,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector2 Slerp(Vector2 to, real_t weight)
+ public readonly Vector2 Slerp(Vector2 to, real_t weight)
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
@@ -577,7 +577,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
- public Vector2 Slide(Vector2 normal)
+ public readonly Vector2 Slide(Vector2 normal)
{
return this - (normal * Dot(normal));
}
@@ -588,7 +588,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector2 Snapped(Vector2 step)
+ public readonly Vector2 Snapped(Vector2 step)
{
return new Vector2(Mathf.Snapped(x, step.x), Mathf.Snapped(y, step.y));
}
@@ -598,7 +598,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2 Orthogonal()
+ public readonly Vector2 Orthogonal()
{
return new Vector2(y, -x);
}
@@ -946,7 +946,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector2 other && Equals(other);
}
@@ -958,7 +958,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector2 other)
+ public readonly bool Equals(Vector2 other)
{
return x == other.x && y == other.y;
}
@@ -969,7 +969,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector2 other)
+ public readonly bool IsEqualApprox(Vector2 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
}
@@ -978,7 +978,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector2"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
}
@@ -987,7 +987,7 @@ namespace Godot
/// Converts this <see cref="Vector2"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y})";
}
@@ -996,7 +996,7 @@ namespace Godot
/// Converts this <see cref="Vector2"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
index bdadf696e3..08f2a3a8af 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -48,7 +48,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -79,7 +79,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y)
+ public readonly void Deconstruct(out int x, out int y)
{
x = this.x;
y = this.y;
@@ -89,7 +89,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
- public Vector2i Abs()
+ public readonly Vector2i Abs()
{
return new Vector2i(Mathf.Abs(x), Mathf.Abs(y));
}
@@ -101,7 +101,7 @@ namespace Godot
/// called with the vector's <see cref="y"/> and <see cref="x"/> as parameters: <c>Mathf.Atan2(v.y, v.x)</c>.
/// </summary>
/// <returns>The angle of this vector, in radians.</returns>
- public real_t Angle()
+ public readonly real_t Angle()
{
return Mathf.Atan2(y, x);
}
@@ -111,7 +111,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector2i to)
+ public readonly real_t AngleTo(Vector2i to)
{
return Mathf.Atan2(Cross(to), Dot(to));
}
@@ -121,7 +121,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The angle between the two vectors, in radians.</returns>
- public real_t AngleToPoint(Vector2i to)
+ public readonly real_t AngleToPoint(Vector2i to)
{
return Mathf.Atan2(y - to.y, x - to.x);
}
@@ -130,7 +130,7 @@ namespace Godot
/// Returns the aspect ratio of this vector, the ratio of <see cref="x"/> to <see cref="y"/>.
/// </summary>
/// <returns>The <see cref="x"/> component divided by the <see cref="y"/> component.</returns>
- public real_t Aspect()
+ public readonly real_t Aspect()
{
return x / (real_t)y;
}
@@ -143,7 +143,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector2i Clamp(Vector2i min, Vector2i max)
+ public readonly Vector2i Clamp(Vector2i min, Vector2i max)
{
return new Vector2i
(
@@ -157,7 +157,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product vector.</returns>
- public int Cross(Vector2i with)
+ public readonly int Cross(Vector2i with)
{
return x * with.y - y * with.x;
}
@@ -169,7 +169,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector2i to)
+ public readonly int DistanceSquaredTo(Vector2i to)
{
return (to - this).LengthSquared();
}
@@ -179,7 +179,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector2i to)
+ public readonly real_t DistanceTo(Vector2i to)
{
return (to - this).Length();
}
@@ -189,7 +189,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector2i with)
+ public readonly int Dot(Vector2i with)
{
return x * with.x + y * with.y;
}
@@ -199,7 +199,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -213,7 +213,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public int LengthSquared()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -226,7 +226,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? Axis.Y : Axis.X;
}
@@ -236,7 +236,7 @@ namespace Godot
/// If both components are equal, this method returns <see cref="Axis.Y"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? Axis.X : Axis.Y;
}
@@ -249,7 +249,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector2i PosMod(int mod)
+ public readonly Vector2i PosMod(int mod)
{
Vector2i v = this;
v.x = Mathf.PosMod(v.x, mod);
@@ -265,7 +265,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector2i PosMod(Vector2i modv)
+ public readonly Vector2i PosMod(Vector2i modv)
{
Vector2i v = this;
v.x = Mathf.PosMod(v.x, modv.x);
@@ -279,7 +279,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector2i Sign()
+ public readonly Vector2i Sign()
{
Vector2i v = this;
v.x = Mathf.Sign(v.x);
@@ -292,7 +292,7 @@ namespace Godot
/// compared to the original, with the same length.
/// </summary>
/// <returns>The perpendicular vector.</returns>
- public Vector2i Orthogonal()
+ public readonly Vector2i Orthogonal()
{
return new Vector2i(y, -x);
}
@@ -665,7 +665,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector2i other && Equals(other);
}
@@ -675,7 +675,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector2i other)
+ public readonly bool Equals(Vector2i other)
{
return x == other.x && y == other.y;
}
@@ -684,7 +684,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector2i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
}
@@ -693,7 +693,7 @@ namespace Godot
/// Converts this <see cref="Vector2i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y})";
}
@@ -702,7 +702,7 @@ namespace Godot
/// Converts this <see cref="Vector2i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 6649f3b784..53bd0b0908 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -94,7 +94,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y, out real_t z)
+ public readonly void Deconstruct(out real_t x, out real_t y, out real_t z)
{
x = this.x;
y = this.y;
@@ -122,7 +122,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
- public Vector3 Abs()
+ public readonly Vector3 Abs()
{
return new Vector3(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
}
@@ -132,7 +132,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to compare this vector to.</param>
/// <returns>The unsigned angle between the two vectors, in radians.</returns>
- public real_t AngleTo(Vector3 to)
+ public readonly real_t AngleTo(Vector3 to)
{
return Mathf.Atan2(Cross(to).Length(), Dot(to));
}
@@ -142,7 +142,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to bounce off. Must be normalized.</param>
/// <returns>The bounced vector.</returns>
- public Vector3 Bounce(Vector3 normal)
+ public readonly Vector3 Bounce(Vector3 normal)
{
return -Reflect(normal);
}
@@ -151,7 +151,7 @@ namespace Godot
/// Returns a new vector with all components rounded up (towards positive infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
- public Vector3 Ceil()
+ public readonly Vector3 Ceil()
{
return new Vector3(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z));
}
@@ -164,7 +164,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector3 Clamp(Vector3 min, Vector3 max)
+ public readonly Vector3 Clamp(Vector3 min, Vector3 max)
{
return new Vector3
(
@@ -179,7 +179,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>The cross product vector.</returns>
- public Vector3 Cross(Vector3 with)
+ public readonly Vector3 Cross(Vector3 with)
{
return new Vector3
(
@@ -198,7 +198,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight)
+ public readonly Vector3 CubicInterpolate(Vector3 b, Vector3 preA, Vector3 postB, real_t weight)
{
return new Vector3
(
@@ -222,7 +222,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector3
(
@@ -241,7 +241,7 @@ namespace Godot
/// <param name="end">The destination vector.</param>
/// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
+ public readonly Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
{
// Formula from Wikipedia article on Bezier curves
real_t omt = 1 - t;
@@ -258,7 +258,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector3 DirectionTo(Vector3 to)
+ public readonly Vector3 DirectionTo(Vector3 to)
{
return new Vector3(to.x - x, to.y - y, to.z - z).Normalized();
}
@@ -270,7 +270,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector3 to)
+ public readonly real_t DistanceSquaredTo(Vector3 to)
{
return (to - this).LengthSquared();
}
@@ -281,7 +281,7 @@ namespace Godot
/// <seealso cref="DistanceSquaredTo(Vector3)"/>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector3 to)
+ public readonly real_t DistanceTo(Vector3 to)
{
return (to - this).Length();
}
@@ -291,7 +291,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector3 with)
+ public readonly real_t Dot(Vector3 with)
{
return (x * with.x) + (y * with.y) + (z * with.z);
}
@@ -300,7 +300,7 @@ namespace Godot
/// Returns a new vector with all components rounded down (towards negative infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
- public Vector3 Floor()
+ public readonly Vector3 Floor()
{
return new Vector3(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z));
}
@@ -309,7 +309,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector3(1 / v.x, 1 / v.y, 1 / v.z)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector3 Inverse()
+ public readonly Vector3 Inverse()
{
return new Vector3(1 / x, 1 / y, 1 / z);
}
@@ -318,7 +318,7 @@ namespace Godot
/// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
/// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -328,7 +328,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -343,7 +343,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public real_t LengthSquared()
+ public readonly real_t LengthSquared()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -359,7 +359,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector3 Lerp(Vector3 to, real_t weight)
+ public readonly Vector3 Lerp(Vector3 to, real_t weight)
{
return new Vector3
(
@@ -376,7 +376,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A vector with components on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector3 Lerp(Vector3 to, Vector3 weight)
+ public readonly Vector3 Lerp(Vector3 to, Vector3 weight)
{
return new Vector3
(
@@ -391,7 +391,7 @@ namespace Godot
/// </summary>
/// <param name="length">The length to limit to.</param>
/// <returns>The vector with its length limited.</returns>
- public Vector3 LimitLength(real_t length = 1.0f)
+ public readonly Vector3 LimitLength(real_t length = 1.0f)
{
Vector3 v = this;
real_t l = Length();
@@ -410,7 +410,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
}
@@ -420,7 +420,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
}
@@ -431,7 +431,7 @@ namespace Godot
/// <param name="to">The vector to move towards.</param>
/// <param name="delta">The amount to move towards by.</param>
/// <returns>The resulting vector.</returns>
- public Vector3 MoveToward(Vector3 to, real_t delta)
+ public readonly Vector3 MoveToward(Vector3 to, real_t delta)
{
Vector3 v = this;
Vector3 vd = to - v;
@@ -446,7 +446,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector3 Normalized()
+ public readonly Vector3 Normalized()
{
Vector3 v = this;
v.Normalize();
@@ -458,7 +458,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector.</param>
/// <returns>A <see cref="Basis"/> representing the outer product matrix.</returns>
- public Basis Outer(Vector3 with)
+ public readonly Basis Outer(Vector3 with)
{
return new Basis(
x * with.x, x * with.y, x * with.z,
@@ -475,7 +475,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector3 PosMod(real_t mod)
+ public readonly Vector3 PosMod(real_t mod)
{
Vector3 v;
v.x = Mathf.PosMod(x, mod);
@@ -492,7 +492,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector3 PosMod(Vector3 modv)
+ public readonly Vector3 PosMod(Vector3 modv)
{
Vector3 v;
v.x = Mathf.PosMod(x, modv.x);
@@ -506,7 +506,7 @@ namespace Godot
/// </summary>
/// <param name="onNormal">The vector to project onto.</param>
/// <returns>The projected vector.</returns>
- public Vector3 Project(Vector3 onNormal)
+ public readonly Vector3 Project(Vector3 onNormal)
{
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
}
@@ -516,7 +516,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to reflect from. Must be normalized.</param>
/// <returns>The reflected vector.</returns>
- public Vector3 Reflect(Vector3 normal)
+ public readonly Vector3 Reflect(Vector3 normal)
{
#if DEBUG
if (!normal.IsNormalized())
@@ -534,7 +534,7 @@ namespace Godot
/// <param name="axis">The vector to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate by, in radians.</param>
/// <returns>The rotated vector.</returns>
- public Vector3 Rotated(Vector3 axis, real_t angle)
+ public readonly Vector3 Rotated(Vector3 axis, real_t angle)
{
#if DEBUG
if (!axis.IsNormalized())
@@ -550,7 +550,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector3 Round()
+ public readonly Vector3 Round()
{
return new Vector3(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z));
}
@@ -561,7 +561,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector3 Sign()
+ public readonly Vector3 Sign()
{
Vector3 v;
v.x = Mathf.Sign(x);
@@ -579,7 +579,7 @@ namespace Godot
/// <param name="to">The other vector to compare this vector to.</param>
/// <param name="axis">The reference axis to use for the angle sign.</param>
/// <returns>The signed angle between the two vectors, in radians.</returns>
- public real_t SignedAngleTo(Vector3 to, Vector3 axis)
+ public readonly real_t SignedAngleTo(Vector3 to, Vector3 axis)
{
Vector3 crossTo = Cross(to);
real_t unsignedAngle = Mathf.Atan2(crossTo.Length(), Dot(to));
@@ -598,7 +598,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector3 Slerp(Vector3 to, real_t weight)
+ public readonly Vector3 Slerp(Vector3 to, real_t weight)
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
@@ -618,7 +618,7 @@ namespace Godot
/// </summary>
/// <param name="normal">The normal vector defining the plane to slide on.</param>
/// <returns>The slid vector.</returns>
- public Vector3 Slide(Vector3 normal)
+ public readonly Vector3 Slide(Vector3 normal)
{
return this - (normal * Dot(normal));
}
@@ -629,7 +629,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector3 Snapped(Vector3 step)
+ public readonly Vector3 Snapped(Vector3 step)
{
return new Vector3
(
@@ -1015,7 +1015,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector3 other && Equals(other);
}
@@ -1027,7 +1027,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector3 other)
+ public readonly bool Equals(Vector3 other)
{
return x == other.x && y == other.y && z == other.z;
}
@@ -1038,7 +1038,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector3 other)
+ public readonly bool IsEqualApprox(Vector3 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
}
@@ -1047,7 +1047,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector3"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
@@ -1056,7 +1056,7 @@ namespace Godot
/// Converts this <see cref="Vector3"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z})";
}
@@ -1065,7 +1065,7 @@ namespace Godot
/// Converts this <see cref="Vector3"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
index e88a043cb3..e631a9f443 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
@@ -58,7 +58,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -94,7 +94,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y, out int z)
+ public readonly void Deconstruct(out int x, out int y, out int z)
{
x = this.x;
y = this.y;
@@ -105,7 +105,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
- public Vector3i Abs()
+ public readonly Vector3i Abs()
{
return new Vector3i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z));
}
@@ -118,7 +118,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector3i Clamp(Vector3i min, Vector3i max)
+ public readonly Vector3i Clamp(Vector3i min, Vector3i max)
{
return new Vector3i
(
@@ -135,7 +135,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public int DistanceSquaredTo(Vector3i to)
+ public readonly int DistanceSquaredTo(Vector3i to)
{
return (to - this).LengthSquared();
}
@@ -146,7 +146,7 @@ namespace Godot
/// <seealso cref="DistanceSquaredTo(Vector3i)"/>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector3i to)
+ public readonly real_t DistanceTo(Vector3i to)
{
return (to - this).Length();
}
@@ -156,7 +156,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public int Dot(Vector3i with)
+ public readonly int Dot(Vector3i with)
{
return x * with.x + y * with.y + z * with.z;
}
@@ -166,7 +166,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -181,7 +181,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public int LengthSquared()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -195,7 +195,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
}
@@ -205,7 +205,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.Z"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
}
@@ -218,7 +218,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector3i PosMod(int mod)
+ public readonly Vector3i PosMod(int mod)
{
Vector3i v = this;
v.x = Mathf.PosMod(v.x, mod);
@@ -235,7 +235,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(int, int)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector3i PosMod(Vector3i modv)
+ public readonly Vector3i PosMod(Vector3i modv)
{
Vector3i v = this;
v.x = Mathf.PosMod(v.x, modv.x);
@@ -250,7 +250,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector3i Sign()
+ public readonly Vector3i Sign()
{
Vector3i v = this;
v.x = Mathf.Sign(v.x);
@@ -674,7 +674,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector3i other && Equals(other);
}
@@ -684,7 +684,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector3i other)
+ public readonly bool Equals(Vector3i other)
{
return x == other.x && y == other.y && z == other.z;
}
@@ -693,7 +693,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector3i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
@@ -702,7 +702,7 @@ namespace Godot
/// Converts this <see cref="Vector3i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z})";
}
@@ -711,7 +711,7 @@ namespace Godot
/// Converts this <see cref="Vector3i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
index e2da41ff47..3191e8adc0 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs
@@ -68,7 +68,7 @@ namespace Godot
/// </value>
public real_t this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -109,7 +109,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w)
+ public readonly void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w)
{
x = this.x;
y = this.y;
@@ -139,7 +139,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns>
- public Vector4 Abs()
+ public readonly Vector4 Abs()
{
return new Vector4(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
}
@@ -148,7 +148,7 @@ namespace Godot
/// Returns a new vector with all components rounded up (towards positive infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns>
- public Vector4 Ceil()
+ public readonly Vector4 Ceil()
{
return new Vector4(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z), Mathf.Ceil(w));
}
@@ -161,7 +161,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector4 Clamp(Vector4 min, Vector4 max)
+ public readonly Vector4 Clamp(Vector4 min, Vector4 max)
{
return new Vector4
(
@@ -181,7 +181,7 @@ namespace Godot
/// <param name="postB">A vector after <paramref name="b"/>.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The interpolated vector.</returns>
- public Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight)
+ public readonly Vector4 CubicInterpolate(Vector4 b, Vector4 preA, Vector4 postB, real_t weight)
{
return new Vector4
(
@@ -206,7 +206,7 @@ namespace Godot
/// <param name="preAT"></param>
/// <param name="postBT"></param>
/// <returns>The interpolated vector.</returns>
- public Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
+ public readonly Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT)
{
return new Vector4
(
@@ -222,7 +222,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to point towards.</param>
/// <returns>The direction from this vector to <paramref name="to"/>.</returns>
- public Vector4 DirectionTo(Vector4 to)
+ public readonly Vector4 DirectionTo(Vector4 to)
{
Vector4 ret = new Vector4(to.x - x, to.y - y, to.z - z, to.w - w);
ret.Normalize();
@@ -236,7 +236,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The squared distance between the two vectors.</returns>
- public real_t DistanceSquaredTo(Vector4 to)
+ public readonly real_t DistanceSquaredTo(Vector4 to)
{
return (to - this).LengthSquared();
}
@@ -246,7 +246,7 @@ namespace Godot
/// </summary>
/// <param name="to">The other vector to use.</param>
/// <returns>The distance between the two vectors.</returns>
- public real_t DistanceTo(Vector4 to)
+ public readonly real_t DistanceTo(Vector4 to)
{
return (to - this).Length();
}
@@ -256,7 +256,7 @@ namespace Godot
/// </summary>
/// <param name="with">The other vector to use.</param>
/// <returns>The dot product of the two vectors.</returns>
- public real_t Dot(Vector4 with)
+ public readonly real_t Dot(Vector4 with)
{
return (x * with.x) + (y * with.y) + (z * with.z) + (w * with.w);
}
@@ -265,7 +265,7 @@ namespace Godot
/// Returns a new vector with all components rounded down (towards negative infinity).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns>
- public Vector4 Floor()
+ public readonly Vector4 Floor()
{
return new Vector4(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z), Mathf.Floor(w));
}
@@ -274,7 +274,7 @@ namespace Godot
/// Returns the inverse of this vector. This is the same as <c>new Vector4(1 / v.x, 1 / v.y, 1 / v.z, 1 / v.w)</c>.
/// </summary>
/// <returns>The inverse of this vector.</returns>
- public Vector4 Inverse()
+ public readonly Vector4 Inverse()
{
return new Vector4(1 / x, 1 / y, 1 / z, 1 / w);
}
@@ -283,7 +283,7 @@ namespace Godot
/// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise.
/// </summary>
/// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns>
- public bool IsNormalized()
+ public readonly bool IsNormalized()
{
return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon;
}
@@ -293,7 +293,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -309,7 +309,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public real_t LengthSquared()
+ public readonly real_t LengthSquared()
{
real_t x2 = x * x;
real_t y2 = y * y;
@@ -326,7 +326,7 @@ namespace Godot
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
/// <returns>The resulting vector of the interpolation.</returns>
- public Vector4 Lerp(Vector4 to, real_t weight)
+ public readonly Vector4 Lerp(Vector4 to, real_t weight)
{
return new Vector4
(
@@ -342,7 +342,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
int max_index = 0;
real_t max_value = x;
@@ -362,7 +362,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.W"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
int min_index = 0;
real_t min_value = x;
@@ -381,7 +381,7 @@ namespace Godot
/// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>.
/// </summary>
/// <returns>A normalized version of the vector.</returns>
- public Vector4 Normalized()
+ public readonly Vector4 Normalized()
{
Vector4 v = this;
v.Normalize();
@@ -396,7 +396,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
/// </returns>
- public Vector4 PosMod(real_t mod)
+ public readonly Vector4 PosMod(real_t mod)
{
return new Vector4(
Mathf.PosMod(x, mod),
@@ -414,7 +414,7 @@ namespace Godot
/// <returns>
/// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="modv"/>'s components.
/// </returns>
- public Vector4 PosMod(Vector4 modv)
+ public readonly Vector4 PosMod(Vector4 modv)
{
return new Vector4(
Mathf.PosMod(x, modv.x),
@@ -429,7 +429,7 @@ namespace Godot
/// with halfway cases rounded towards the nearest multiple of two.
/// </summary>
/// <returns>The rounded vector.</returns>
- public Vector4 Round()
+ public readonly Vector4 Round()
{
return new Vector4(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z), Mathf.Round(w));
}
@@ -440,7 +440,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(real_t)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector4 Sign()
+ public readonly Vector4 Sign()
{
Vector4 v;
v.x = Mathf.Sign(x);
@@ -456,7 +456,7 @@ namespace Godot
/// </summary>
/// <param name="step">A vector value representing the step size to snap to.</param>
/// <returns>The snapped vector.</returns>
- public Vector4 Snapped(Vector4 step)
+ public readonly Vector4 Snapped(Vector4 step)
{
return new Vector4(
Mathf.Snapped(x, step.x),
@@ -828,7 +828,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector4 other && Equals(other);
}
@@ -840,7 +840,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are exactly equal.</returns>
- public bool Equals(Vector4 other)
+ public readonly bool Equals(Vector4 other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -851,7 +851,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector to compare.</param>
/// <returns>Whether or not the vectors are approximately equal.</returns>
- public bool IsEqualApprox(Vector4 other)
+ public readonly bool IsEqualApprox(Vector4 other)
{
return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
}
@@ -860,7 +860,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector4"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -878,7 +878,7 @@ namespace Godot
/// Converts this <see cref="Vector4"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})";
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
index 4b1bb3ba19..8146991fd7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs
@@ -68,7 +68,7 @@ namespace Godot
/// </value>
public int this[int index]
{
- get
+ readonly get
{
switch (index)
{
@@ -109,7 +109,7 @@ namespace Godot
/// <summary>
/// Helper method for deconstruction into a tuple.
/// </summary>
- public void Deconstruct(out int x, out int y, out int z, out int w)
+ public readonly void Deconstruct(out int x, out int y, out int z, out int w)
{
x = this.x;
y = this.y;
@@ -121,7 +121,7 @@ namespace Godot
/// Returns a new vector with all components in absolute values (i.e. positive).
/// </summary>
/// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns>
- public Vector4i Abs()
+ public readonly Vector4i Abs()
{
return new Vector4i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w));
}
@@ -134,7 +134,7 @@ namespace Godot
/// <param name="min">The vector with minimum allowed values.</param>
/// <param name="max">The vector with maximum allowed values.</param>
/// <returns>The vector with all components clamped.</returns>
- public Vector4i Clamp(Vector4i min, Vector4i max)
+ public readonly Vector4i Clamp(Vector4i min, Vector4i max)
{
return new Vector4i
(
@@ -150,7 +150,7 @@ namespace Godot
/// </summary>
/// <seealso cref="LengthSquared"/>
/// <returns>The length of this vector.</returns>
- public real_t Length()
+ public readonly real_t Length()
{
int x2 = x * x;
int y2 = y * y;
@@ -166,7 +166,7 @@ namespace Godot
/// you need to compare vectors or need the squared length for some formula.
/// </summary>
/// <returns>The squared length of this vector.</returns>
- public int LengthSquared()
+ public readonly int LengthSquared()
{
int x2 = x * x;
int y2 = y * y;
@@ -181,7 +181,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.X"/>.
/// </summary>
/// <returns>The index of the highest axis.</returns>
- public Axis MaxAxisIndex()
+ public readonly Axis MaxAxisIndex()
{
int max_index = 0;
int max_value = x;
@@ -201,7 +201,7 @@ namespace Godot
/// If all components are equal, this method returns <see cref="Axis.W"/>.
/// </summary>
/// <returns>The index of the lowest axis.</returns>
- public Axis MinAxisIndex()
+ public readonly Axis MinAxisIndex()
{
int min_index = 0;
int min_value = x;
@@ -222,7 +222,7 @@ namespace Godot
/// by calling <see cref="Mathf.Sign(int)"/> on each component.
/// </summary>
/// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
- public Vector4i Sign()
+ public readonly Vector4i Sign()
{
return new Vector4i(Mathf.Sign(x), Mathf.Sign(y), Mathf.Sign(z), Mathf.Sign(w));
}
@@ -627,7 +627,7 @@ namespace Godot
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>Whether or not the vector and the object are equal.</returns>
- public override bool Equals(object obj)
+ public override readonly bool Equals(object obj)
{
return obj is Vector4i other && Equals(other);
}
@@ -637,7 +637,7 @@ namespace Godot
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>Whether or not the vectors are equal.</returns>
- public bool Equals(Vector4i other)
+ public readonly bool Equals(Vector4i other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
@@ -646,7 +646,7 @@ namespace Godot
/// Serves as the hash function for <see cref="Vector4i"/>.
/// </summary>
/// <returns>A hash code for this vector.</returns>
- public override int GetHashCode()
+ public override readonly int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
@@ -655,7 +655,7 @@ namespace Godot
/// Converts this <see cref="Vector4i"/> to a string.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public override string ToString()
+ public override readonly string ToString()
{
return $"({x}, {y}, {z}, {w})";
}
@@ -664,7 +664,7 @@ namespace Godot
/// Converts this <see cref="Vector4i"/> to a string with the given <paramref name="format"/>.
/// </summary>
/// <returns>A string representation of this vector.</returns>
- public string ToString(string format)
+ public readonly string ToString(string format)
{
return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}), {w.ToString(format)})";
}
diff --git a/editor/debugger/editor_network_profiler.cpp b/modules/multiplayer/editor/editor_network_profiler.cpp
index 8c18eba71d..cce22b9084 100644
--- a/editor/debugger/editor_network_profiler.cpp
+++ b/modules/multiplayer/editor/editor_network_profiler.cpp
@@ -36,13 +36,19 @@
void EditorNetworkProfiler::_bind_methods() {
ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable")));
+ ADD_SIGNAL(MethodInfo("open_request", PropertyInfo(Variant::STRING, "path")));
}
void EditorNetworkProfiler::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ node_icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons"));
+ if (activate->is_pressed()) {
+ activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
+ } else {
+ activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ }
clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
incoming_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons")));
outgoing_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")));
@@ -54,29 +60,104 @@ void EditorNetworkProfiler::_notification(int p_what) {
}
}
-void EditorNetworkProfiler::_update_frame() {
+void EditorNetworkProfiler::_refresh() {
+ if (!dirty) {
+ return;
+ }
+ dirty = false;
+ refresh_rpc_data();
+ refresh_replication_data();
+}
+
+void EditorNetworkProfiler::refresh_rpc_data() {
counters_display->clear();
TreeItem *root = counters_display->create_item();
+ int cols = counters_display->get_columns();
- for (const KeyValue<ObjectID, SceneDebugger::RPCNodeInfo> &E : nodes_data) {
+ for (const KeyValue<ObjectID, RPCNodeInfo> &E : rpc_data) {
TreeItem *node = counters_display->create_item(root);
- for (int j = 0; j < counters_display->get_columns(); ++j) {
+ for (int j = 0; j < cols; ++j) {
node->set_text_alignment(j, j > 0 ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT);
}
node->set_text(0, E.value.node_path);
- node->set_text(1, E.value.incoming_rpc == 0 ? "-" : itos(E.value.incoming_rpc));
- node->set_text(2, E.value.outgoing_rpc == 0 ? "-" : itos(E.value.outgoing_rpc));
+ node->set_text(1, E.value.incoming_rpc == 0 ? "-" : vformat(TTR("%d (%s)"), E.value.incoming_rpc, String::humanize_size(E.value.incoming_size)));
+ node->set_text(2, E.value.outgoing_rpc == 0 ? "-" : vformat(TTR("%d (%s)"), E.value.outgoing_rpc, String::humanize_size(E.value.outgoing_size)));
+ }
+}
+
+void EditorNetworkProfiler::refresh_replication_data() {
+ replication_display->clear();
+
+ TreeItem *root = replication_display->create_item();
+
+ for (const KeyValue<ObjectID, SyncInfo> &E : sync_data) {
+ // Ensure the nodes have at least a temporary cache.
+ ObjectID ids[3] = { E.value.synchronizer, E.value.config, E.value.root_node };
+ for (uint32_t i = 0; i < 3; i++) {
+ const ObjectID &id = ids[i];
+ if (!node_data.has(id)) {
+ missing_node_data.insert(id);
+ node_data[id] = NodeInfo(id);
+ }
+ }
+
+ TreeItem *node = replication_display->create_item(root);
+
+ const NodeInfo &root_info = node_data[E.value.root_node];
+ const NodeInfo &sync_info = node_data[E.value.synchronizer];
+ const NodeInfo &cfg_info = node_data[E.value.config];
+
+ node->set_text(0, root_info.path.get_file());
+ node->set_icon(0, has_theme_icon(root_info.type, SNAME("EditorIcons")) ? get_theme_icon(root_info.type, SNAME("EditorIcons")) : node_icon);
+ node->set_tooltip_text(0, root_info.path);
+
+ node->set_text(1, sync_info.path.get_file());
+ node->set_icon(1, get_theme_icon("MultiplayerSynchronizer", SNAME("EditorIcons")));
+ node->set_tooltip_text(1, sync_info.path);
+
+ int cfg_idx = cfg_info.path.find("::");
+ if (cfg_info.path.begins_with("res://") && ResourceLoader::exists(cfg_info.path) && cfg_idx > 0) {
+ String res_idstr = cfg_info.path.substr(cfg_idx + 2).replace("SceneReplicationConfig_", "");
+ String scene_path = cfg_info.path.substr(0, cfg_idx);
+ node->set_text(2, vformat("%s (%s)", res_idstr, scene_path.get_file()));
+ node->add_button(2, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")));
+ node->set_tooltip_text(2, cfg_info.path);
+ node->set_metadata(2, scene_path);
+ } else {
+ node->set_text(2, cfg_info.path);
+ node->set_metadata(2, "");
+ }
+
+ node->set_text(3, vformat("%d - %d", E.value.incoming_syncs, E.value.outgoing_syncs));
+ node->set_text(4, vformat("%d - %d", E.value.incoming_size, E.value.outgoing_size));
}
}
+Array EditorNetworkProfiler::pop_missing_node_data() {
+ Array out;
+ for (const ObjectID &id : missing_node_data) {
+ out.push_back(id);
+ }
+ missing_node_data.clear();
+ return out;
+}
+
+void EditorNetworkProfiler::add_node_data(const NodeInfo &p_info) {
+ ERR_FAIL_COND(!node_data.has(p_info.id));
+ node_data[p_info.id] = p_info;
+ dirty = true;
+}
+
void EditorNetworkProfiler::_activate_pressed() {
if (activate->is_pressed()) {
+ refresh_timer->start();
activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
activate->set_text(TTR("Stop"));
} else {
+ refresh_timer->stop();
activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
activate->set_text(TTR("Start"));
}
@@ -84,25 +165,55 @@ void EditorNetworkProfiler::_activate_pressed() {
}
void EditorNetworkProfiler::_clear_pressed() {
- nodes_data.clear();
+ rpc_data.clear();
+ sync_data.clear();
+ node_data.clear();
+ missing_node_data.clear();
set_bandwidth(0, 0);
- if (frame_delay->is_stopped()) {
- frame_delay->set_wait_time(0.1);
- frame_delay->start();
+ refresh_rpc_data();
+ refresh_replication_data();
+}
+
+void EditorNetworkProfiler::_replication_button_clicked(TreeItem *p_item, int p_column, int p_idx, MouseButton p_button) {
+ if (!p_item) {
+ return;
+ }
+ String meta = p_item->get_metadata(p_column);
+ if (meta.size() && ResourceLoader::exists(meta)) {
+ emit_signal("open_request", meta);
}
}
-void EditorNetworkProfiler::add_node_frame_data(const SceneDebugger::RPCNodeInfo p_frame) {
- if (!nodes_data.has(p_frame.node)) {
- nodes_data.insert(p_frame.node, p_frame);
+void EditorNetworkProfiler::add_rpc_frame_data(const RPCNodeInfo &p_frame) {
+ dirty = true;
+ if (!rpc_data.has(p_frame.node)) {
+ rpc_data.insert(p_frame.node, p_frame);
} else {
- nodes_data[p_frame.node].incoming_rpc += p_frame.incoming_rpc;
- nodes_data[p_frame.node].outgoing_rpc += p_frame.outgoing_rpc;
+ rpc_data[p_frame.node].incoming_rpc += p_frame.incoming_rpc;
+ rpc_data[p_frame.node].outgoing_rpc += p_frame.outgoing_rpc;
}
+ if (p_frame.incoming_rpc) {
+ rpc_data[p_frame.node].incoming_size = p_frame.incoming_size / p_frame.incoming_rpc;
+ }
+ if (p_frame.outgoing_rpc) {
+ rpc_data[p_frame.node].outgoing_size = p_frame.outgoing_size / p_frame.outgoing_rpc;
+ }
+}
- if (frame_delay->is_stopped()) {
- frame_delay->set_wait_time(0.1);
- frame_delay->start();
+void EditorNetworkProfiler::add_sync_frame_data(const SyncInfo &p_frame) {
+ dirty = true;
+ if (!sync_data.has(p_frame.synchronizer)) {
+ sync_data[p_frame.synchronizer] = p_frame;
+ } else {
+ sync_data[p_frame.synchronizer].incoming_syncs += p_frame.incoming_syncs;
+ sync_data[p_frame.synchronizer].outgoing_syncs += p_frame.outgoing_syncs;
+ }
+ SyncInfo &info = sync_data[p_frame.synchronizer];
+ if (info.incoming_syncs) {
+ info.incoming_size = p_frame.incoming_size / p_frame.incoming_syncs;
+ }
+ if (info.outgoing_syncs) {
+ info.outgoing_size = p_frame.outgoing_size / p_frame.outgoing_syncs;
}
}
@@ -168,9 +279,17 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
// Set initial texts in the incoming/outgoing bandwidth labels
set_bandwidth(0, 0);
+ HSplitContainer *sc = memnew(HSplitContainer);
+ add_child(sc);
+ sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ sc->set_h_size_flags(SIZE_EXPAND_FILL);
+ sc->set_split_offset(100 * EDSCALE);
+
+ // RPC
counters_display = memnew(Tree);
- counters_display->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
+ counters_display->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
counters_display->set_v_size_flags(SIZE_EXPAND_FILL);
+ counters_display->set_h_size_flags(SIZE_EXPAND_FILL);
counters_display->set_hide_folding(true);
counters_display->set_hide_root(true);
counters_display->set_columns(3);
@@ -187,11 +306,42 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
counters_display->set_column_expand(2, false);
counters_display->set_column_clip_content(2, true);
counters_display->set_column_custom_minimum_width(2, 120 * EDSCALE);
- add_child(counters_display);
+ sc->add_child(counters_display);
+
+ // Replication
+ replication_display = memnew(Tree);
+ replication_display->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
+ replication_display->set_v_size_flags(SIZE_EXPAND_FILL);
+ replication_display->set_h_size_flags(SIZE_EXPAND_FILL);
+ replication_display->set_hide_folding(true);
+ replication_display->set_hide_root(true);
+ replication_display->set_columns(5);
+ replication_display->set_column_titles_visible(true);
+ replication_display->set_column_title(0, TTR("Root"));
+ replication_display->set_column_expand(0, true);
+ replication_display->set_column_clip_content(0, true);
+ replication_display->set_column_custom_minimum_width(0, 80 * EDSCALE);
+ replication_display->set_column_title(1, TTR("Synchronizer"));
+ replication_display->set_column_expand(1, true);
+ replication_display->set_column_clip_content(1, true);
+ replication_display->set_column_custom_minimum_width(1, 80 * EDSCALE);
+ replication_display->set_column_title(2, TTR("Config"));
+ replication_display->set_column_expand(2, true);
+ replication_display->set_column_clip_content(2, true);
+ replication_display->set_column_custom_minimum_width(2, 80 * EDSCALE);
+ replication_display->set_column_title(3, TTR("Count"));
+ replication_display->set_column_expand(3, false);
+ replication_display->set_column_clip_content(3, true);
+ replication_display->set_column_custom_minimum_width(3, 80 * EDSCALE);
+ replication_display->set_column_title(4, TTR("Size"));
+ replication_display->set_column_expand(4, false);
+ replication_display->set_column_clip_content(4, true);
+ replication_display->set_column_custom_minimum_width(4, 80 * EDSCALE);
+ replication_display->connect("button_clicked", callable_mp(this, &EditorNetworkProfiler::_replication_button_clicked));
+ sc->add_child(replication_display);
- frame_delay = memnew(Timer);
- frame_delay->set_wait_time(0.1);
- frame_delay->set_one_shot(true);
- add_child(frame_delay);
- frame_delay->connect("timeout", callable_mp(this, &EditorNetworkProfiler::_update_frame));
+ refresh_timer = memnew(Timer);
+ refresh_timer->set_wait_time(0.5);
+ refresh_timer->connect("timeout", callable_mp(this, &EditorNetworkProfiler::_refresh));
+ add_child(refresh_timer);
}
diff --git a/editor/debugger/editor_network_profiler.h b/modules/multiplayer/editor/editor_network_profiler.h
index aea7ce3eec..630747d988 100644
--- a/editor/debugger/editor_network_profiler.h
+++ b/modules/multiplayer/editor/editor_network_profiler.h
@@ -38,31 +38,60 @@
#include "scene/gui/split_container.h"
#include "scene/gui/tree.h"
+#include "../multiplayer_debugger.h"
+
class EditorNetworkProfiler : public VBoxContainer {
GDCLASS(EditorNetworkProfiler, VBoxContainer)
+public:
+ struct NodeInfo {
+ ObjectID id;
+ String type;
+ String path;
+
+ NodeInfo() {}
+ NodeInfo(const ObjectID &p_id) {
+ id = p_id;
+ path = String::num_int64(p_id);
+ }
+ };
+
private:
+ using RPCNodeInfo = MultiplayerDebugger::RPCNodeInfo;
+ using SyncInfo = MultiplayerDebugger::SyncInfo;
+
+ bool dirty = false;
+ Timer *refresh_timer = nullptr;
Button *activate = nullptr;
Button *clear_button = nullptr;
Tree *counters_display = nullptr;
LineEdit *incoming_bandwidth_text = nullptr;
LineEdit *outgoing_bandwidth_text = nullptr;
+ Tree *replication_display = nullptr;
- Timer *frame_delay = nullptr;
-
- HashMap<ObjectID, SceneDebugger::RPCNodeInfo> nodes_data;
-
- void _update_frame();
+ HashMap<ObjectID, RPCNodeInfo> rpc_data;
+ HashMap<ObjectID, SyncInfo> sync_data;
+ HashMap<ObjectID, NodeInfo> node_data;
+ HashSet<ObjectID> missing_node_data;
+ Ref<Texture2D> node_icon;
void _activate_pressed();
void _clear_pressed();
+ void _refresh();
+ void _replication_button_clicked(TreeItem *p_item, int p_column, int p_idx, MouseButton p_button);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
- void add_node_frame_data(const SceneDebugger::RPCNodeInfo p_frame);
+ void refresh_rpc_data();
+ void refresh_replication_data();
+
+ Array pop_missing_node_data();
+ void add_node_data(const NodeInfo &p_info);
+ void add_rpc_frame_data(const RPCNodeInfo &p_frame);
+ void add_sync_frame_data(const SyncInfo &p_frame);
void set_bandwidth(int p_incoming, int p_outgoing);
bool is_profiling();
diff --git a/modules/multiplayer/editor/multiplayer_editor_plugin.cpp b/modules/multiplayer/editor/multiplayer_editor_plugin.cpp
new file mode 100644
index 0000000000..c5cf3e6f24
--- /dev/null
+++ b/modules/multiplayer/editor/multiplayer_editor_plugin.cpp
@@ -0,0 +1,175 @@
+/*************************************************************************/
+/* multiplayer_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "multiplayer_editor_plugin.h"
+
+#include "../multiplayer_synchronizer.h"
+#include "editor_network_profiler.h"
+#include "replication_editor.h"
+
+#include "editor/editor_node.h"
+
+void MultiplayerEditorDebugger::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("open_request", PropertyInfo(Variant::STRING, "path")));
+}
+
+bool MultiplayerEditorDebugger::has_capture(const String &p_capture) const {
+ return p_capture == "multiplayer";
+}
+
+void MultiplayerEditorDebugger::_open_request(const String &p_path) {
+ emit_signal("open_request", p_path);
+}
+
+bool MultiplayerEditorDebugger::capture(const String &p_message, const Array &p_data, int p_session) {
+ ERR_FAIL_COND_V(!profilers.has(p_session), false);
+ EditorNetworkProfiler *profiler = profilers[p_session];
+ if (p_message == "multiplayer:rpc") {
+ MultiplayerDebugger::RPCFrame frame;
+ frame.deserialize(p_data);
+ for (int i = 0; i < frame.infos.size(); i++) {
+ profiler->add_rpc_frame_data(frame.infos[i]);
+ }
+ return true;
+ } else if (p_message == "multiplayer:syncs") {
+ MultiplayerDebugger::ReplicationFrame frame;
+ frame.deserialize(p_data);
+ for (const KeyValue<ObjectID, MultiplayerDebugger::SyncInfo> &E : frame.infos) {
+ profiler->add_sync_frame_data(E.value);
+ }
+ Array missing = profiler->pop_missing_node_data();
+ if (missing.size()) {
+ // Asks for the object information.
+ get_session(p_session)->send_message("multiplayer:cache", missing);
+ }
+ return true;
+ } else if (p_message == "multiplayer:cache") {
+ ERR_FAIL_COND_V(p_data.size() % 3, false);
+ for (int i = 0; i < p_data.size(); i += 3) {
+ EditorNetworkProfiler::NodeInfo info;
+ info.id = p_data[i].operator ObjectID();
+ info.type = p_data[i + 1].operator String();
+ info.path = p_data[i + 2].operator String();
+ profiler->add_node_data(info);
+ }
+ return true;
+ } else if (p_message == "multiplayer:bandwidth") {
+ ERR_FAIL_COND_V(p_data.size() < 2, false);
+ profiler->set_bandwidth(p_data[0], p_data[1]);
+ return true;
+ }
+ return false;
+}
+
+void MultiplayerEditorDebugger::_profiler_activate(bool p_enable, int p_session_id) {
+ Ref<EditorDebuggerSession> session = get_session(p_session_id);
+ ERR_FAIL_COND(session.is_null());
+ session->toggle_profiler("multiplayer:bandwidth", p_enable);
+ session->toggle_profiler("multiplayer:rpc", p_enable);
+ session->toggle_profiler("multiplayer:replication", p_enable);
+}
+
+void MultiplayerEditorDebugger::setup_session(int p_session_id) {
+ Ref<EditorDebuggerSession> session = get_session(p_session_id);
+ ERR_FAIL_COND(session.is_null());
+ EditorNetworkProfiler *profiler = memnew(EditorNetworkProfiler);
+ profiler->connect("enable_profiling", callable_mp(this, &MultiplayerEditorDebugger::_profiler_activate).bind(p_session_id));
+ profiler->connect("open_request", callable_mp(this, &MultiplayerEditorDebugger::_open_request));
+ profiler->set_name(TTR("Network Profiler"));
+ session->add_session_tab(profiler);
+ profilers[p_session_id] = profiler;
+}
+
+/// MultiplayerEditorPlugin
+
+MultiplayerEditorPlugin::MultiplayerEditorPlugin() {
+ repl_editor = memnew(ReplicationEditor);
+ button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Replication"), repl_editor);
+ button->hide();
+ repl_editor->get_pin()->connect("pressed", callable_mp(this, &MultiplayerEditorPlugin::_pinned));
+ debugger.instantiate();
+ debugger->connect("open_request", callable_mp(this, &MultiplayerEditorPlugin::_open_request));
+}
+
+void MultiplayerEditorPlugin::_open_request(const String &p_path) {
+ get_editor_interface()->open_scene_from_path(p_path);
+}
+
+void MultiplayerEditorPlugin::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ get_tree()->connect("node_removed", callable_mp(this, &MultiplayerEditorPlugin::_node_removed));
+ add_debugger_plugin(debugger);
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ remove_debugger_plugin(debugger);
+ }
+ }
+}
+
+void MultiplayerEditorPlugin::_node_removed(Node *p_node) {
+ if (p_node && p_node == repl_editor->get_current()) {
+ repl_editor->edit(nullptr);
+ if (repl_editor->is_visible_in_tree()) {
+ EditorNode::get_singleton()->hide_bottom_panel();
+ }
+ button->hide();
+ repl_editor->get_pin()->set_pressed(false);
+ }
+}
+
+void MultiplayerEditorPlugin::_pinned() {
+ if (!repl_editor->get_pin()->is_pressed()) {
+ if (repl_editor->is_visible_in_tree()) {
+ EditorNode::get_singleton()->hide_bottom_panel();
+ }
+ button->hide();
+ }
+}
+
+void MultiplayerEditorPlugin::edit(Object *p_object) {
+ repl_editor->edit(Object::cast_to<MultiplayerSynchronizer>(p_object));
+}
+
+bool MultiplayerEditorPlugin::handles(Object *p_object) const {
+ return p_object->is_class("MultiplayerSynchronizer");
+}
+
+void MultiplayerEditorPlugin::make_visible(bool p_visible) {
+ if (p_visible) {
+ button->show();
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(repl_editor);
+ } else if (!repl_editor->get_pin()->is_pressed()) {
+ if (repl_editor->is_visible_in_tree()) {
+ EditorNode::get_singleton()->hide_bottom_panel();
+ }
+ button->hide();
+ }
+}
diff --git a/modules/multiplayer/editor/multiplayer_editor_plugin.h b/modules/multiplayer/editor/multiplayer_editor_plugin.h
new file mode 100644
index 0000000000..f29a70e897
--- /dev/null
+++ b/modules/multiplayer/editor/multiplayer_editor_plugin.h
@@ -0,0 +1,85 @@
+/*************************************************************************/
+/* multiplayer_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MULTIPLAYER_EDITOR_PLUGIN_H
+#define MULTIPLAYER_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+
+#include "editor/plugins/editor_debugger_plugin.h"
+
+class EditorNetworkProfiler;
+class MultiplayerEditorDebugger : public EditorDebuggerPlugin {
+ GDCLASS(MultiplayerEditorDebugger, EditorDebuggerPlugin);
+
+private:
+ HashMap<int, EditorNetworkProfiler *> profilers;
+
+ void _open_request(const String &p_path);
+ void _profiler_activate(bool p_enable, int p_session_id);
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual bool has_capture(const String &p_capture) const override;
+ virtual bool capture(const String &p_message, const Array &p_data, int p_index) override;
+ virtual void setup_session(int p_session_id) override;
+
+ MultiplayerEditorDebugger() {}
+};
+
+class ReplicationEditor;
+
+class MultiplayerEditorPlugin : public EditorPlugin {
+ GDCLASS(MultiplayerEditorPlugin, EditorPlugin);
+
+private:
+ Button *button = nullptr;
+ ReplicationEditor *repl_editor = nullptr;
+ Ref<MultiplayerEditorDebugger> debugger;
+
+ void _open_request(const String &p_path);
+ void _node_removed(Node *p_node);
+
+ void _pinned();
+
+protected:
+ void _notification(int p_what);
+
+public:
+ virtual void edit(Object *p_object) override;
+ virtual bool handles(Object *p_object) const override;
+ virtual void make_visible(bool p_visible) override;
+
+ MultiplayerEditorPlugin();
+};
+
+#endif // MULTIPLAYER_EDITOR_PLUGIN_H
diff --git a/modules/multiplayer/editor/replication_editor_plugin.cpp b/modules/multiplayer/editor/replication_editor.cpp
index aee5f5b483..ccde9fed22 100644
--- a/modules/multiplayer/editor/replication_editor_plugin.cpp
+++ b/modules/multiplayer/editor/replication_editor.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* replication_editor_plugin.cpp */
+/* replication_editor.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,15 +28,17 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "replication_editor_plugin.h"
+#include "replication_editor.h"
+
+#include "../multiplayer_synchronizer.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/inspector_dock.h"
+#include "editor/property_selector.h"
#include "editor/scene_tree_editor.h"
-#include "modules/multiplayer/multiplayer_synchronizer.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
@@ -140,7 +142,7 @@ void ReplicationEditor::_add_sync_property(String p_path) {
return;
}
- Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(TTR("Add property to synchronizer"));
if (config.is_null()) {
@@ -200,7 +202,7 @@ ReplicationEditor::ReplicationEditor() {
add_pick_button = memnew(Button);
add_pick_button->connect("pressed", callable_mp(this, &ReplicationEditor::_pick_new_property));
- add_pick_button->set_text(TTR("Add property to sync.."));
+ add_pick_button->set_text(TTR("Add property to sync..."));
hb->add_child(add_pick_button);
VSeparator *vs = memnew(VSeparator);
vs->set_custom_minimum_size(Size2(30 * EDSCALE, 0));
@@ -492,62 +494,3 @@ void ReplicationEditor::_add_property(const NodePath &p_property, bool p_spawn,
item->set_checked(2, p_sync);
item->set_editable(2, true);
}
-
-/// ReplicationEditorPlugin
-ReplicationEditorPlugin::ReplicationEditorPlugin() {
- repl_editor = memnew(ReplicationEditor);
- button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Replication"), repl_editor);
- button->hide();
- repl_editor->get_pin()->connect("pressed", callable_mp(this, &ReplicationEditorPlugin::_pinned));
-}
-
-ReplicationEditorPlugin::~ReplicationEditorPlugin() {
-}
-
-void ReplicationEditorPlugin::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- get_tree()->connect("node_removed", callable_mp(this, &ReplicationEditorPlugin::_node_removed));
- } break;
- }
-}
-
-void ReplicationEditorPlugin::_node_removed(Node *p_node) {
- if (p_node && p_node == repl_editor->get_current()) {
- repl_editor->edit(nullptr);
- if (repl_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- button->hide();
- repl_editor->get_pin()->set_pressed(false);
- }
-}
-
-void ReplicationEditorPlugin::_pinned() {
- if (!repl_editor->get_pin()->is_pressed()) {
- if (repl_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- button->hide();
- }
-}
-
-void ReplicationEditorPlugin::edit(Object *p_object) {
- repl_editor->edit(Object::cast_to<MultiplayerSynchronizer>(p_object));
-}
-
-bool ReplicationEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("MultiplayerSynchronizer");
-}
-
-void ReplicationEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
- button->show();
- EditorNode::get_singleton()->make_bottom_panel_item_visible(repl_editor);
- } else if (!repl_editor->get_pin()->is_pressed()) {
- if (repl_editor->is_visible_in_tree()) {
- EditorNode::get_singleton()->hide_bottom_panel();
- }
- button->hide();
- }
-}
diff --git a/modules/multiplayer/editor/replication_editor_plugin.h b/modules/multiplayer/editor/replication_editor.h
index e60e49cc25..8a48e8dbe7 100644
--- a/modules/multiplayer/editor/replication_editor_plugin.h
+++ b/modules/multiplayer/editor/replication_editor.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* replication_editor_plugin.h */
+/* replication_editor.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,21 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REPLICATION_EDITOR_PLUGIN_H
-#define REPLICATION_EDITOR_PLUGIN_H
+#ifndef REPLICATION_EDITOR_H
+#define REPLICATION_EDITOR_H
#include "editor/editor_plugin.h"
-
-#include "editor/editor_spin_slider.h"
-#include "editor/property_selector.h"
-
-#include "../scene_replication_config.h"
+#include "modules/multiplayer/scene_replication_config.h"
+#include "scene/gui/box_container.h"
class ConfirmationDialog;
class MultiplayerSynchronizer;
-class SceneTreeDialog;
+class AcceptDialog;
+class LineEdit;
class Tree;
class TreeItem;
+class PropertySelector;
+class SceneTreeDialog;
class ReplicationEditor : public VBoxContainer {
GDCLASS(ReplicationEditor, VBoxContainer);
@@ -105,27 +105,4 @@ public:
~ReplicationEditor() {}
};
-class ReplicationEditorPlugin : public EditorPlugin {
- GDCLASS(ReplicationEditorPlugin, EditorPlugin);
-
-private:
- Button *button = nullptr;
- ReplicationEditor *repl_editor = nullptr;
-
- void _node_removed(Node *p_node);
-
- void _pinned();
-
-protected:
- void _notification(int p_what);
-
-public:
- virtual void edit(Object *p_object) override;
- virtual bool handles(Object *p_object) const override;
- virtual void make_visible(bool p_visible) override;
-
- ReplicationEditorPlugin();
- ~ReplicationEditorPlugin();
-};
-
-#endif // REPLICATION_EDITOR_PLUGIN_H
+#endif // REPLICATION_EDITOR_H
diff --git a/modules/multiplayer/multiplayer_debugger.cpp b/modules/multiplayer/multiplayer_debugger.cpp
new file mode 100644
index 0000000000..9086ee6ec9
--- /dev/null
+++ b/modules/multiplayer/multiplayer_debugger.cpp
@@ -0,0 +1,333 @@
+/*************************************************************************/
+/* multiplayer_debugger.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "multiplayer_debugger.h"
+
+#include "multiplayer_synchronizer.h"
+#include "scene_replication_config.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "scene/main/node.h"
+
+List<Ref<EngineProfiler>> multiplayer_profilers;
+
+void MultiplayerDebugger::initialize() {
+ Ref<BandwidthProfiler> bandwidth;
+ bandwidth.instantiate();
+ bandwidth->bind("multiplayer:bandwidth");
+ multiplayer_profilers.push_back(bandwidth);
+
+ Ref<RPCProfiler> rpc_profiler;
+ rpc_profiler.instantiate();
+ rpc_profiler->bind("multiplayer:rpc");
+ multiplayer_profilers.push_back(rpc_profiler);
+
+ Ref<ReplicationProfiler> replication_profiler;
+ replication_profiler.instantiate();
+ replication_profiler->bind("multiplayer:replication");
+ multiplayer_profilers.push_back(replication_profiler);
+
+ EngineDebugger::register_message_capture("multiplayer", EngineDebugger::Capture(nullptr, &_capture));
+}
+
+void MultiplayerDebugger::deinitialize() {
+ multiplayer_profilers.clear();
+}
+
+Error MultiplayerDebugger::_capture(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured) {
+ if (p_msg == "cache") {
+ Array out;
+ for (int i = 0; i < p_args.size(); i++) {
+ ObjectID id = p_args[i].operator ObjectID();
+ Object *obj = ObjectDB::get_instance(id);
+ ERR_CONTINUE(!obj);
+ if (Object::cast_to<SceneReplicationConfig>(obj)) {
+ out.push_back(id);
+ out.push_back(obj->get_class());
+ out.push_back(((SceneReplicationConfig *)obj)->get_path());
+ } else if (Object::cast_to<Node>(obj)) {
+ out.push_back(id);
+ out.push_back(obj->get_class());
+ out.push_back(String(((Node *)obj)->get_path()));
+ } else {
+ ERR_FAIL_V(FAILED);
+ }
+ }
+ EngineDebugger::get_singleton()->send_message("multiplayer:cache", out);
+ return OK;
+ }
+ ERR_FAIL_V(FAILED);
+}
+
+// BandwidthProfiler
+
+int MultiplayerDebugger::BandwidthProfiler::bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer) {
+ ERR_FAIL_COND_V(p_buffer.size() == 0, 0);
+ int total_bandwidth = 0;
+
+ uint64_t timestamp = OS::get_singleton()->get_ticks_msec();
+ uint64_t final_timestamp = timestamp - 1000;
+
+ int i = (p_pointer + p_buffer.size() - 1) % p_buffer.size();
+
+ while (i != p_pointer && p_buffer[i].packet_size > 0) {
+ if (p_buffer[i].timestamp < final_timestamp) {
+ return total_bandwidth;
+ }
+ total_bandwidth += p_buffer[i].packet_size;
+ i = (i + p_buffer.size() - 1) % p_buffer.size();
+ }
+
+ ERR_FAIL_COND_V_MSG(i == p_pointer, total_bandwidth, "Reached the end of the bandwidth profiler buffer, values might be inaccurate.");
+ return total_bandwidth;
+}
+
+void MultiplayerDebugger::BandwidthProfiler::toggle(bool p_enable, const Array &p_opts) {
+ if (!p_enable) {
+ bandwidth_in.clear();
+ bandwidth_out.clear();
+ } else {
+ bandwidth_in_ptr = 0;
+ bandwidth_in.resize(16384); // ~128kB
+ for (int i = 0; i < bandwidth_in.size(); ++i) {
+ bandwidth_in.write[i].packet_size = -1;
+ }
+ bandwidth_out_ptr = 0;
+ bandwidth_out.resize(16384); // ~128kB
+ for (int i = 0; i < bandwidth_out.size(); ++i) {
+ bandwidth_out.write[i].packet_size = -1;
+ }
+ }
+}
+
+void MultiplayerDebugger::BandwidthProfiler::add(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() < 3);
+ const String inout = p_data[0];
+ int time = p_data[1];
+ int size = p_data[2];
+ if (inout == "in") {
+ bandwidth_in.write[bandwidth_in_ptr].timestamp = time;
+ bandwidth_in.write[bandwidth_in_ptr].packet_size = size;
+ bandwidth_in_ptr = (bandwidth_in_ptr + 1) % bandwidth_in.size();
+ } else if (inout == "out") {
+ bandwidth_out.write[bandwidth_out_ptr].timestamp = time;
+ bandwidth_out.write[bandwidth_out_ptr].packet_size = size;
+ bandwidth_out_ptr = (bandwidth_out_ptr + 1) % bandwidth_out.size();
+ }
+}
+
+void MultiplayerDebugger::BandwidthProfiler::tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_bandwidth_time > 200) {
+ last_bandwidth_time = pt;
+ int incoming_bandwidth = bandwidth_usage(bandwidth_in, bandwidth_in_ptr);
+ int outgoing_bandwidth = bandwidth_usage(bandwidth_out, bandwidth_out_ptr);
+
+ Array arr;
+ arr.push_back(incoming_bandwidth);
+ arr.push_back(outgoing_bandwidth);
+ EngineDebugger::get_singleton()->send_message("multiplayer:bandwidth", arr);
+ }
+}
+
+// RPCProfiler
+
+Array MultiplayerDebugger::RPCFrame::serialize() {
+ Array arr;
+ arr.push_back(infos.size() * 6);
+ for (int i = 0; i < infos.size(); ++i) {
+ arr.push_back(uint64_t(infos[i].node));
+ arr.push_back(infos[i].node_path);
+ arr.push_back(infos[i].incoming_rpc);
+ arr.push_back(infos[i].incoming_size);
+ arr.push_back(infos[i].outgoing_rpc);
+ arr.push_back(infos[i].outgoing_size);
+ }
+ return arr;
+}
+
+bool MultiplayerDebugger::RPCFrame::deserialize(const Array &p_arr) {
+ ERR_FAIL_COND_V(p_arr.size() < 1, false);
+ uint32_t size = p_arr[0];
+ ERR_FAIL_COND_V(size % 6, false);
+ ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false);
+ infos.resize(size / 6);
+ int idx = 1;
+ for (uint32_t i = 0; i < size / 6; i++) {
+ infos.write[i].node = uint64_t(p_arr[idx]);
+ infos.write[i].node_path = p_arr[idx + 1];
+ infos.write[i].incoming_rpc = p_arr[idx + 2];
+ infos.write[i].incoming_size = p_arr[idx + 3];
+ infos.write[i].outgoing_rpc = p_arr[idx + 4];
+ infos.write[i].outgoing_size = p_arr[idx + 5];
+ idx += 6;
+ }
+ return true;
+}
+
+void MultiplayerDebugger::RPCProfiler::init_node(const ObjectID p_node) {
+ if (rpc_node_data.has(p_node)) {
+ return;
+ }
+ rpc_node_data.insert(p_node, RPCNodeInfo());
+ rpc_node_data[p_node].node = p_node;
+ rpc_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path();
+}
+
+void MultiplayerDebugger::RPCProfiler::toggle(bool p_enable, const Array &p_opts) {
+ rpc_node_data.clear();
+}
+
+void MultiplayerDebugger::RPCProfiler::add(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() != 3);
+ const String what = p_data[0];
+ const ObjectID id = p_data[1];
+ const int size = p_data[2];
+ init_node(id);
+ RPCNodeInfo &info = rpc_node_data[id];
+ if (what == "rpc_in") {
+ info.incoming_rpc++;
+ info.incoming_size += size;
+ } else if (what == "rpc_out") {
+ info.outgoing_rpc++;
+ info.outgoing_size += size;
+ }
+}
+
+void MultiplayerDebugger::RPCProfiler::tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_profile_time > 100) {
+ last_profile_time = pt;
+ RPCFrame frame;
+ for (const KeyValue<ObjectID, RPCNodeInfo> &E : rpc_node_data) {
+ frame.infos.push_back(E.value);
+ }
+ rpc_node_data.clear();
+ EngineDebugger::get_singleton()->send_message("multiplayer:rpc", frame.serialize());
+ }
+}
+
+// ReplicationProfiler
+
+MultiplayerDebugger::SyncInfo::SyncInfo(MultiplayerSynchronizer *p_sync) {
+ ERR_FAIL_COND(!p_sync);
+ synchronizer = p_sync->get_instance_id();
+ if (p_sync->get_replication_config().is_valid()) {
+ config = p_sync->get_replication_config()->get_instance_id();
+ }
+ if (p_sync->get_root_node()) {
+ root_node = p_sync->get_root_node()->get_instance_id();
+ }
+}
+
+void MultiplayerDebugger::SyncInfo::write_to_array(Array &r_arr) const {
+ r_arr.push_back(synchronizer);
+ r_arr.push_back(config);
+ r_arr.push_back(root_node);
+ r_arr.push_back(incoming_syncs);
+ r_arr.push_back(incoming_size);
+ r_arr.push_back(outgoing_syncs);
+ r_arr.push_back(outgoing_size);
+}
+
+bool MultiplayerDebugger::SyncInfo::read_from_array(const Array &p_arr, int p_offset) {
+ ERR_FAIL_COND_V(p_arr.size() - p_offset < 7, false);
+ synchronizer = int64_t(p_arr[p_offset]);
+ config = int64_t(p_arr[p_offset + 1]);
+ root_node = int64_t(p_arr[p_offset + 2]);
+ incoming_syncs = p_arr[p_offset + 3];
+ incoming_size = p_arr[p_offset + 4];
+ outgoing_syncs = p_arr[p_offset + 5];
+ outgoing_size = p_arr[p_offset + 6];
+ return true;
+}
+
+Array MultiplayerDebugger::ReplicationFrame::serialize() {
+ Array arr;
+ arr.push_back(infos.size() * 7);
+ for (const KeyValue<ObjectID, SyncInfo> &E : infos) {
+ E.value.write_to_array(arr);
+ }
+ return arr;
+}
+
+bool MultiplayerDebugger::ReplicationFrame::deserialize(const Array &p_arr) {
+ ERR_FAIL_COND_V(p_arr.size() < 1, false);
+ uint32_t size = p_arr[0];
+ ERR_FAIL_COND_V(size % 7, false);
+ ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false);
+ int idx = 1;
+ for (uint32_t i = 0; i < size / 7; i++) {
+ SyncInfo info;
+ if (!info.read_from_array(p_arr, idx)) {
+ return false;
+ }
+ infos[info.synchronizer] = info;
+ idx += 7;
+ }
+ return true;
+}
+
+void MultiplayerDebugger::ReplicationProfiler::toggle(bool p_enable, const Array &p_opts) {
+ sync_data.clear();
+}
+
+void MultiplayerDebugger::ReplicationProfiler::add(const Array &p_data) {
+ ERR_FAIL_COND(p_data.size() != 3);
+ const String what = p_data[0];
+ const ObjectID id = p_data[1];
+ const uint64_t size = p_data[2];
+ MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(ObjectDB::get_instance(id));
+ ERR_FAIL_COND(!sync);
+ if (!sync_data.has(id)) {
+ sync_data[id] = SyncInfo(sync);
+ }
+ SyncInfo &info = sync_data[id];
+ if (what == "sync_in") {
+ info.incoming_syncs++;
+ info.incoming_size += size;
+ } else if (what == "sync_out") {
+ info.outgoing_syncs++;
+ info.outgoing_size += size;
+ }
+}
+
+void MultiplayerDebugger::ReplicationProfiler::tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
+ uint64_t pt = OS::get_singleton()->get_ticks_msec();
+ if (pt - last_profile_time > 100) {
+ last_profile_time = pt;
+ ReplicationFrame frame;
+ for (const KeyValue<ObjectID, SyncInfo> &E : sync_data) {
+ frame.infos[E.key] = E.value;
+ }
+ sync_data.clear();
+ EngineDebugger::get_singleton()->send_message("multiplayer:syncs", frame.serialize());
+ }
+}
diff --git a/modules/multiplayer/multiplayer_debugger.h b/modules/multiplayer/multiplayer_debugger.h
new file mode 100644
index 0000000000..f5c092f0f9
--- /dev/null
+++ b/modules/multiplayer/multiplayer_debugger.h
@@ -0,0 +1,134 @@
+/*************************************************************************/
+/* multiplayer_debugger.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MULTIPLAYER_DEBUGGER_H
+#define MULTIPLAYER_DEBUGGER_H
+
+#include "core/debugger/engine_profiler.h"
+
+#include "core/os/os.h"
+
+class MultiplayerSynchronizer;
+
+class MultiplayerDebugger {
+public:
+ struct RPCNodeInfo {
+ ObjectID node;
+ String node_path;
+ int incoming_rpc = 0;
+ int incoming_size = 0;
+ int outgoing_rpc = 0;
+ int outgoing_size = 0;
+ };
+
+ struct RPCFrame {
+ Vector<RPCNodeInfo> infos;
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+ struct SyncInfo {
+ ObjectID synchronizer;
+ ObjectID config;
+ ObjectID root_node;
+ int incoming_syncs = 0;
+ int incoming_size = 0;
+ int outgoing_syncs = 0;
+ int outgoing_size = 0;
+
+ void write_to_array(Array &r_arr) const;
+ bool read_from_array(const Array &p_arr, int p_offset);
+
+ SyncInfo() {}
+ SyncInfo(MultiplayerSynchronizer *p_sync);
+ };
+
+ struct ReplicationFrame {
+ HashMap<ObjectID, SyncInfo> infos;
+
+ Array serialize();
+ bool deserialize(const Array &p_arr);
+ };
+
+private:
+ class BandwidthProfiler : public EngineProfiler {
+ protected:
+ struct BandwidthFrame {
+ uint32_t timestamp;
+ int packet_size;
+ };
+
+ int bandwidth_in_ptr = 0;
+ Vector<BandwidthFrame> bandwidth_in;
+ int bandwidth_out_ptr = 0;
+ Vector<BandwidthFrame> bandwidth_out;
+ uint64_t last_bandwidth_time = 0;
+
+ int bandwidth_usage(const Vector<BandwidthFrame> &p_buffer, int p_pointer);
+
+ public:
+ void toggle(bool p_enable, const Array &p_opts);
+ void add(const Array &p_data);
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
+ };
+
+ class RPCProfiler : public EngineProfiler {
+ private:
+ HashMap<ObjectID, RPCNodeInfo> rpc_node_data;
+ uint64_t last_profile_time = 0;
+
+ void init_node(const ObjectID p_node);
+
+ public:
+ void toggle(bool p_enable, const Array &p_opts);
+ void add(const Array &p_data);
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
+ };
+
+ class ReplicationProfiler : public EngineProfiler {
+ private:
+ HashMap<ObjectID, SyncInfo> sync_data;
+ uint64_t last_profile_time = 0;
+
+ public:
+ void toggle(bool p_enable, const Array &p_opts);
+ void add(const Array &p_data);
+ void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
+ };
+
+ static Error _capture(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured);
+
+public:
+ static void initialize();
+ static void deinitialize();
+};
+
+#endif // MULTIPLAYER_DEBUGGER_H
diff --git a/modules/multiplayer/register_types.cpp b/modules/multiplayer/register_types.cpp
index a2c524da80..ca85a46f31 100644
--- a/modules/multiplayer/register_types.cpp
+++ b/modules/multiplayer/register_types.cpp
@@ -36,9 +36,10 @@
#include "scene_replication_interface.h"
#include "scene_rpc_interface.h"
+#include "multiplayer_debugger.h"
+
#ifdef TOOLS_ENABLED
-#include "editor/editor_plugin.h"
-#include "editor/replication_editor_plugin.h"
+#include "editor/multiplayer_editor_plugin.h"
#endif
void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
@@ -46,15 +47,18 @@ void initialize_multiplayer_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(SceneReplicationConfig);
GDREGISTER_CLASS(MultiplayerSpawner);
GDREGISTER_CLASS(MultiplayerSynchronizer);
+ GDREGISTER_CLASS(OfflineMultiplayerPeer);
GDREGISTER_CLASS(SceneMultiplayer);
MultiplayerAPI::set_default_interface("SceneMultiplayer");
+ MultiplayerDebugger::initialize();
}
#ifdef TOOLS_ENABLED
if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
- EditorPlugins::add_by_type<ReplicationEditorPlugin>();
+ EditorPlugins::add_by_type<MultiplayerEditorPlugin>();
}
#endif
}
void uninitialize_multiplayer_module(ModuleInitializationLevel p_level) {
+ MultiplayerDebugger::deinitialize();
}
diff --git a/modules/multiplayer/scene_cache_interface.cpp b/modules/multiplayer/scene_cache_interface.cpp
index 7df9b95b30..f0da4f9dfc 100644
--- a/modules/multiplayer/scene_cache_interface.cpp
+++ b/modules/multiplayer/scene_cache_interface.cpp
@@ -99,10 +99,6 @@ void SceneCacheInterface::process_simplify_path(int p_from, const uint8_t *p_pac
Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
ERR_FAIL_COND(multiplayer_peer.is_null());
-#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", packet.size());
-#endif
-
multiplayer_peer->set_transfer_channel(0);
multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
multiplayer->send_command(p_from, packet.ptr(), packet.size());
@@ -155,10 +151,6 @@ Error SceneCacheInterface::_send_confirm_path(Node *p_node, NodePath p_path, Pat
Ref<MultiplayerPeer> multiplayer_peer = multiplayer->get_multiplayer_peer();
ERR_FAIL_COND_V(multiplayer_peer.is_null(), ERR_BUG);
-#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", packet.size() * p_peers.size());
-#endif
-
Error err = OK;
for (int peer_id : p_peers) {
multiplayer_peer->set_transfer_channel(0);
diff --git a/modules/multiplayer/scene_multiplayer.cpp b/modules/multiplayer/scene_multiplayer.cpp
index db7c5037cd..5042a0502d 100644
--- a/modules/multiplayer/scene_multiplayer.cpp
+++ b/modules/multiplayer/scene_multiplayer.cpp
@@ -40,13 +40,13 @@
#endif
#ifdef DEBUG_ENABLED
-void SceneMultiplayer::profile_bandwidth(const String &p_inout, int p_size) {
- if (EngineDebugger::is_profiling("multiplayer")) {
+_FORCE_INLINE_ void SceneMultiplayer::_profile_bandwidth(const String &p_what, int p_value) {
+ if (EngineDebugger::is_profiling("multiplayer:bandwidth")) {
Array values;
- values.push_back(p_inout);
+ values.push_back(p_what);
values.push_back(OS::get_singleton()->get_ticks_msec());
- values.push_back(p_size);
- EngineDebugger::profiler_add_frame_data("multiplayer", values);
+ values.push_back(p_value);
+ EngineDebugger::profiler_add_frame_data("multiplayer:bandwidth", values);
}
}
#endif
@@ -91,6 +91,10 @@ Error SceneMultiplayer::poll() {
Error err = multiplayer_peer->get_packet(&packet, len);
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Error getting packet! %d", err));
+#ifdef DEBUG_ENABLED
+ _profile_bandwidth("in", len);
+#endif
+
if (pending_peers.has(sender)) {
if (pending_peers[sender].local) {
// If the auth is over, admit the peer at the first packet.
@@ -220,10 +224,6 @@ void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int
ERR_FAIL_COND_MSG(root_path.is_empty(), "Multiplayer root was not initialized. If you are using custom multiplayer, remember to set the root path via SceneMultiplayer.set_root_path before using it.");
ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small.");
-#ifdef DEBUG_ENABLED
- profile_bandwidth("in", p_packet_len);
-#endif
-
// Extract the `packet_type` from the LSB three bits:
uint8_t packet_type = p_packet[0] & CMD_MASK;
@@ -258,6 +258,13 @@ void SceneMultiplayer::_process_packet(int p_from, const uint8_t *p_packet, int
}
}
+#ifdef DEBUG_ENABLED
+_FORCE_INLINE_ Error SceneMultiplayer::_send(const uint8_t *p_packet, int p_packet_len) {
+ _profile_bandwidth("out", p_packet_len);
+ return multiplayer_peer->put_packet(p_packet, p_packet_len);
+}
+#endif
+
Error SceneMultiplayer::send_command(int p_to, const uint8_t *p_packet, int p_packet_len) {
if (server_relay && get_unique_id() != 1 && p_to != 1 && multiplayer_peer->is_server_relay_supported()) {
// Send relay packet.
@@ -268,19 +275,19 @@ Error SceneMultiplayer::send_command(int p_to, const uint8_t *p_packet, int p_pa
relay_buffer->put_data(p_packet, p_packet_len);
multiplayer_peer->set_target_peer(1);
const Vector<uint8_t> data = relay_buffer->get_data_array();
- return multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
+ return _send(data.ptr(), relay_buffer->get_position());
}
if (p_to > 0) {
ERR_FAIL_COND_V(!connected_peers.has(p_to), ERR_BUG);
multiplayer_peer->set_target_peer(p_to);
- return multiplayer_peer->put_packet(p_packet, p_packet_len);
+ return _send(p_packet, p_packet_len);
} else {
for (const int &pid : connected_peers) {
if (p_to && pid == -p_to) {
continue;
}
multiplayer_peer->set_target_peer(pid);
- multiplayer_peer->put_packet(p_packet, p_packet_len);
+ _send(p_packet, p_packet_len);
}
return OK;
}
@@ -319,7 +326,7 @@ void SceneMultiplayer::_process_sys(int p_from, const uint8_t *p_packet, int p_p
multiplayer_peer->set_transfer_channel(p_channel);
if (peer > 0) {
multiplayer_peer->set_target_peer(peer);
- multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
+ _send(data.ptr(), relay_buffer->get_position());
} else {
for (const int &P : connected_peers) {
// Not to sender, nor excluded.
@@ -327,7 +334,7 @@ void SceneMultiplayer::_process_sys(int p_from, const uint8_t *p_packet, int p_p
continue;
}
multiplayer_peer->set_target_peer(P);
- multiplayer_peer->put_packet(data.ptr(), relay_buffer->get_position());
+ _send(data.ptr(), relay_buffer->get_position());
}
}
if (peer == 0 || peer == -1) {
@@ -373,11 +380,11 @@ void SceneMultiplayer::_admit_peer(int p_id) {
// Send new peer to already connected.
encode_uint32(p_id, &buf[2]);
multiplayer_peer->set_target_peer(P);
- multiplayer_peer->put_packet(buf, sizeof(buf));
+ _send(buf, sizeof(buf));
// Send already connected to new peer.
encode_uint32(P, &buf[2]);
multiplayer_peer->set_target_peer(p_id);
- multiplayer_peer->put_packet(buf, sizeof(buf));
+ _send(buf, sizeof(buf));
}
}
@@ -412,7 +419,7 @@ void SceneMultiplayer::_del_peer(int p_id) {
continue;
}
multiplayer_peer->set_target_peer(P);
- multiplayer_peer->put_packet(buf, sizeof(buf));
+ _send(buf, sizeof(buf));
}
}
@@ -468,7 +475,7 @@ Error SceneMultiplayer::send_auth(int p_to, Vector<uint8_t> p_data) {
multiplayer_peer->set_target_peer(p_to);
multiplayer_peer->set_transfer_channel(0);
multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
- return multiplayer_peer->put_packet(packet_cache.ptr(), p_data.size() + 2);
+ return _send(packet_cache.ptr(), p_data.size() + 2);
}
Error SceneMultiplayer::complete_auth(int p_peer) {
@@ -478,7 +485,7 @@ Error SceneMultiplayer::complete_auth(int p_peer) {
pending_peers[p_peer].local = true;
// Notify the remote peer that the authentication has completed.
uint8_t buf[2] = { NETWORK_COMMAND_SYS, SYS_COMMAND_AUTH };
- Error err = multiplayer_peer->put_packet(buf, 2);
+ Error err = _send(buf, 2);
// The remote peer already reported the authentication as completed, so admit the peer.
// May generate new packets, so it must happen after sending confirmation.
if (pending_peers[p_peer].remote) {
@@ -654,6 +661,7 @@ SceneMultiplayer::SceneMultiplayer() {
replicator = Ref<SceneReplicationInterface>(memnew(SceneReplicationInterface(this)));
rpc = Ref<SceneRPCInterface>(memnew(SceneRPCInterface(this)));
cache = Ref<SceneCacheInterface>(memnew(SceneCacheInterface(this)));
+ set_multiplayer_peer(Ref<OfflineMultiplayerPeer>(memnew(OfflineMultiplayerPeer)));
}
SceneMultiplayer::~SceneMultiplayer() {
diff --git a/modules/multiplayer/scene_multiplayer.h b/modules/multiplayer/scene_multiplayer.h
index b0ecc48f8c..1a8de11f3f 100644
--- a/modules/multiplayer/scene_multiplayer.h
+++ b/modules/multiplayer/scene_multiplayer.h
@@ -37,6 +37,31 @@
#include "scene_replication_interface.h"
#include "scene_rpc_interface.h"
+class OfflineMultiplayerPeer : public MultiplayerPeer {
+ GDCLASS(OfflineMultiplayerPeer, MultiplayerPeer);
+
+public:
+ virtual int get_available_packet_count() const override { return 0; }
+ virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override {
+ *r_buffer = nullptr;
+ r_buffer_size = 0;
+ return OK;
+ }
+ virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override { return OK; }
+ virtual int get_max_packet_size() const override { return 0; }
+
+ virtual void set_target_peer(int p_peer_id) override {}
+ virtual int get_packet_peer() const override { return 0; }
+ virtual TransferMode get_packet_mode() const override { return TRANSFER_MODE_RELIABLE; };
+ virtual int get_packet_channel() const override { return 0; }
+ virtual void disconnect_peer(int p_peer, bool p_force = false) override {}
+ virtual bool is_server() const override { return true; }
+ virtual void poll() override {}
+ virtual void close() override {}
+ virtual int get_unique_id() const override { return TARGET_PEER_SERVER; }
+ virtual ConnectionStatus get_connection_status() const override { return CONNECTION_CONNECTED; };
+};
+
class SceneMultiplayer : public MultiplayerAPI {
GDCLASS(SceneMultiplayer, MultiplayerAPI);
@@ -103,6 +128,15 @@ private:
Ref<SceneReplicationInterface> replicator;
Ref<SceneRPCInterface> rpc;
+#ifdef DEBUG_ENABLED
+ _FORCE_INLINE_ void _profile_bandwidth(const String &p_what, int p_value);
+ _FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len); // Also profiles.
+#else
+ _FORCE_INLINE_ Error _send(const uint8_t *p_packet, int p_packet_len) {
+ return multiplayer_peer->put_packet(p_packet, p_packet_len);
+ }
+#endif
+
protected:
static void _bind_methods();
@@ -162,10 +196,7 @@ public:
bool is_server_relay_enabled() const;
Ref<SceneCacheInterface> get_path_cache() { return cache; }
-
-#ifdef DEBUG_ENABLED
- void profile_bandwidth(const String &p_inout, int p_size);
-#endif
+ Ref<SceneReplicationInterface> get_replicator() { return replicator; }
SceneMultiplayer();
~SceneMultiplayer();
diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp
index f1bab7327a..7d9437936a 100644
--- a/modules/multiplayer/scene_replication_interface.cpp
+++ b/modules/multiplayer/scene_replication_interface.cpp
@@ -32,6 +32,7 @@
#include "scene_multiplayer.h"
+#include "core/debugger/engine_debugger.h"
#include "core/io/marshalls.h"
#include "scene/main/node.h"
#include "scene/scene_string_names.h"
@@ -40,6 +41,18 @@
if (packet_cache.size() < m_amount) \
packet_cache.resize(m_amount);
+#ifdef DEBUG_ENABLED
+_FORCE_INLINE_ void SceneReplicationInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
+ if (EngineDebugger::is_profiling("multiplayer:replication")) {
+ Array values;
+ values.push_back(p_what);
+ values.push_back(p_id);
+ values.push_back(p_size);
+ EngineDebugger::profiler_add_frame_data("multiplayer:replication", values);
+ }
+}
+#endif
+
SceneReplicationInterface::TrackedNode &SceneReplicationInterface::_track(const ObjectID &p_id) {
if (!tracked_nodes.has(p_id)) {
tracked_nodes[p_id] = TrackedNode(p_id);
@@ -244,15 +257,54 @@ void SceneReplicationInterface::_visibility_changed(int p_peer, ObjectID p_sid)
Node *node = sync->get_root_node();
ERR_FAIL_COND(!node); // Bug.
const ObjectID oid = node->get_instance_id();
- if (spawned_nodes.has(oid)) {
+ if (spawned_nodes.has(oid) && p_peer != multiplayer->get_unique_id()) {
_update_spawn_visibility(p_peer, oid);
}
_update_sync_visibility(p_peer, sync);
}
+bool SceneReplicationInterface::is_rpc_visible(const ObjectID &p_oid, int p_peer) const {
+ if (!tracked_nodes.has(p_oid)) {
+ return true; // Untracked nodes are always visible to RPCs.
+ }
+ ERR_FAIL_COND_V(p_peer < 0, false);
+ const TrackedNode &tnode = tracked_nodes[p_oid];
+ if (tnode.synchronizers.is_empty()) {
+ return true; // No synchronizers means no visibility restrictions.
+ }
+ if (tnode.remote_peer && uint32_t(p_peer) == tnode.remote_peer) {
+ return true; // RPCs on spawned nodes are always visible to spawner.
+ } else if (spawned_nodes.has(p_oid)) {
+ // It's a spwaned node we control, this can be fast
+ if (p_peer) {
+ return peers_info.has(p_peer) && peers_info[p_peer].spawn_nodes.has(p_oid);
+ } else {
+ for (const KeyValue<int, PeerInfo> &E : peers_info) {
+ if (!E.value.spawn_nodes.has(p_oid)) {
+ return false; // Not public.
+ }
+ }
+ return true; // All peers have this node.
+ }
+ } else {
+ // Cycle object synchronizers to check visibility.
+ for (const ObjectID &sid : tnode.synchronizers) {
+ MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(sid);
+ ERR_CONTINUE(!sync);
+ // RPC visibility is composed using OR when multiple synchronizers are present.
+ // Note that we don't really care about authority here which may lead to unexpected
+ // results when using multiple synchronizers to control the same node.
+ if (sync->is_visible_to(p_peer)) {
+ return true;
+ }
+ }
+ return false; // Not visible.
+ }
+}
+
Error SceneReplicationInterface::_update_sync_visibility(int p_peer, MultiplayerSynchronizer *p_sync) {
ERR_FAIL_COND_V(!p_sync, ERR_BUG);
- if (!multiplayer->has_multiplayer_peer() || !p_sync->is_multiplayer_authority()) {
+ if (!multiplayer->has_multiplayer_peer() || !p_sync->is_multiplayer_authority() || p_peer == multiplayer->get_unique_id()) {
return OK;
}
@@ -362,13 +414,8 @@ Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const Obje
Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable) {
ERR_FAIL_COND_V(!p_buffer || p_size < 1, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(!multiplayer, ERR_UNCONFIGURED);
ERR_FAIL_COND_V(!multiplayer->has_multiplayer_peer(), ERR_UNCONFIGURED);
-#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", p_size);
-#endif
-
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
peer->set_transfer_channel(0);
peer->set_transfer_mode(p_reliable ? MultiplayerPeer::TRANSFER_MODE_RELIABLE : MultiplayerPeer::TRANSFER_MODE_UNRELIABLE);
@@ -640,6 +687,9 @@ void SceneReplicationInterface::_send_sync(int p_peer, const HashSet<ObjectID> p
MultiplayerAPI::encode_and_compress_variants(varp.ptrw(), varp.size(), &ptr[ofs], size);
ofs += size;
}
+#ifdef DEBUG_ENABLED
+ _profile_node_data("sync_out", oid, size);
+#endif
}
if (ofs > 3) {
// Got some left over to send.
@@ -687,6 +737,9 @@ Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_bu
err = MultiplayerSynchronizer::set_state(props, node, vars);
ERR_FAIL_COND_V(err, err);
ofs += size;
+#ifdef DEBUG_ENABLED
+ _profile_node_data("sync_in", sync->get_instance_id(), size);
+#endif
}
return OK;
}
diff --git a/modules/multiplayer/scene_replication_interface.h b/modules/multiplayer/scene_replication_interface.h
index c8bd96eb87..30d58f7129 100644
--- a/modules/multiplayer/scene_replication_interface.h
+++ b/modules/multiplayer/scene_replication_interface.h
@@ -105,6 +105,10 @@ private:
return p_id.is_valid() ? Object::cast_to<T>(ObjectDB::get_instance(p_id)) : nullptr;
}
+#ifdef DEBUG_ENABLED
+ _FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id, int p_size);
+#endif
+
public:
static void make_default();
@@ -121,6 +125,8 @@ public:
Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len);
+ bool is_rpc_visible(const ObjectID &p_oid, int p_peer) const;
+
SceneReplicationInterface(SceneMultiplayer *p_multiplayer) {
multiplayer = p_multiplayer;
}
diff --git a/modules/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp
index acc113c901..dbf2b3751e 100644
--- a/modules/multiplayer/scene_rpc_interface.cpp
+++ b/modules/multiplayer/scene_rpc_interface.cpp
@@ -52,16 +52,15 @@
#define BYTE_ONLY_OR_NO_ARGS_FLAG (1 << BYTE_ONLY_OR_NO_ARGS_SHIFT)
#ifdef DEBUG_ENABLED
-_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) {
- if (EngineDebugger::is_profiling("rpc")) {
+_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
+ if (EngineDebugger::is_profiling("multiplayer:rpc")) {
Array values;
- values.push_back(p_id);
values.push_back(p_what);
- EngineDebugger::profiler_add_frame_data("rpc", values);
+ values.push_back(p_id);
+ values.push_back(p_size);
+ EngineDebugger::profiler_add_frame_data("multiplayer:rpc", values);
}
}
-#else
-_FORCE_INLINE_ void SceneRPCInterface::_profile_node_data(const String &p_what, ObjectID p_id) {}
#endif
// Returns the packet size stripping the node path added when the node is not yet cached.
@@ -277,7 +276,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
argp.resize(argc);
#ifdef DEBUG_ENABLED
- _profile_node_data("rpc_in", p_node->get_instance_id());
+ _profile_node_data("rpc_in", p_node->get_instance_id(), p_packet_len);
#endif
int out;
@@ -296,7 +295,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
}
}
-void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
+void SceneRPCInterface::_send_rpc(Node *p_node, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount) {
Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
ERR_FAIL_COND_MSG(peer.is_null(), "Attempt to call RPC without active multiplayer peer.");
@@ -312,12 +311,35 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
ERR_FAIL_MSG("Attempt to call RPC with unknown peer ID: " + itos(p_to) + ".");
}
- // See if all peers have cached path (if so, call can be fast).
- int psc_id;
- const bool has_all_peers = multiplayer->get_path_cache()->send_object_cache(p_from, p_to, psc_id);
+ // See if all peers have cached path (if so, call can be fast) while building the RPC target list.
+ HashSet<int> targets;
+ Ref<SceneCacheInterface> cache = multiplayer->get_path_cache();
+ int psc_id = -1;
+ bool has_all_peers = true;
+ const ObjectID oid = p_node->get_instance_id();
+ if (p_to > 0) {
+ ERR_FAIL_COND_MSG(!multiplayer->get_replicator()->is_rpc_visible(oid, p_to), "Attempt to call an RPC to a peer that cannot see this node. Peer ID: " + itos(p_to));
+ targets.insert(p_to);
+ has_all_peers = cache->send_object_cache(p_node, p_to, psc_id);
+ } else {
+ bool restricted = !multiplayer->get_replicator()->is_rpc_visible(oid, 0);
+ for (const int &P : multiplayer->get_connected_peers()) {
+ if (p_to < 0 && P == -p_to) {
+ continue; // Excluded peer.
+ }
+ if (restricted && !multiplayer->get_replicator()->is_rpc_visible(oid, P)) {
+ continue; // Not visible to this peer.
+ }
+ targets.insert(P);
+ bool has_peer = cache->send_object_cache(p_node, P, psc_id);
+ has_all_peers = has_all_peers && has_peer;
+ }
+ }
+ if (targets.is_empty()) {
+ return; // No one in sight.
+ }
// Create base packet, lots of hardcode because it must be tight.
-
int ofs = 0;
#define MAKE_ROOM(m_amount) \
@@ -399,20 +421,21 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
ERR_FAIL_COND(node_id_compression > 3);
ERR_FAIL_COND(name_id_compression > 1);
- // We can now set the meta
- packet_cache.write[0] = command_type + (node_id_compression << NODE_ID_COMPRESSION_SHIFT) + (name_id_compression << NAME_ID_COMPRESSION_SHIFT) + (byte_only_or_no_args ? BYTE_ONLY_OR_NO_ARGS_FLAG : 0);
-
#ifdef DEBUG_ENABLED
- multiplayer->profile_bandwidth("out", ofs);
+ _profile_node_data("rpc_out", p_node->get_instance_id(), ofs);
#endif
+ // We can now set the meta
+ packet_cache.write[0] = command_type + (node_id_compression << NODE_ID_COMPRESSION_SHIFT) + (name_id_compression << NAME_ID_COMPRESSION_SHIFT) + (byte_only_or_no_args ? BYTE_ONLY_OR_NO_ARGS_FLAG : 0);
+
// Take chance and set transfer mode, since all send methods will use it.
peer->set_transfer_channel(p_config.channel);
peer->set_transfer_mode(p_config.transfer_mode);
if (has_all_peers) {
- // They all have verified paths, so send fast.
- multiplayer->send_command(p_to, packet_cache.ptr(), ofs);
+ for (const int P : targets) {
+ multiplayer->send_command(P, packet_cache.ptr(), ofs);
+ }
} else {
// Unreachable because the node ID is never compressed if the peers doesn't know it.
CRASH_COND(node_id_compression != NETWORK_NODE_ID_COMPRESSION_32);
@@ -420,23 +443,15 @@ void SceneRPCInterface::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, con
// Not all verified path, so send one by one.
// Append path at the end, since we will need it for some packets.
- NodePath from_path = multiplayer->get_root_path().rel_path_to(p_from->get_path());
+ NodePath from_path = multiplayer->get_root_path().rel_path_to(p_node->get_path());
CharString pname = String(from_path).utf8();
int path_len = encode_cstring(pname.get_data(), nullptr);
MAKE_ROOM(ofs + path_len);
encode_cstring(pname.get_data(), &(packet_cache.write[ofs]));
- for (const int &P : multiplayer->get_connected_peers()) {
- if (p_to < 0 && P == -p_to) {
- continue; // Continue, excluded.
- }
-
- if (p_to > 0 && P != p_to) {
- continue; // Continue, not for this peer.
- }
-
+ // Not all verified path, so check which needs the longer packet.
+ for (const int P : targets) {
bool confirmed = multiplayer->get_path_cache()->is_cache_confirmed(from_path, P);
-
if (confirmed) {
// This one confirmed path, so use id.
encode_uint32(psc_id, &(packet_cache.write[1]));
@@ -477,10 +492,6 @@ Error SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_
}
if (p_peer_id != caller_id) {
-#ifdef DEBUG_ENABLED
- _profile_node_data("rpc_out", node->get_instance_id());
-#endif
-
_send_rpc(node, p_peer_id, rpc_id, config, p_method, p_arg, p_argcount);
}
diff --git a/modules/multiplayer/scene_rpc_interface.h b/modules/multiplayer/scene_rpc_interface.h
index aa9be525a2..800293714c 100644
--- a/modules/multiplayer/scene_rpc_interface.h
+++ b/modules/multiplayer/scene_rpc_interface.h
@@ -81,8 +81,11 @@ private:
HashMap<ObjectID, RPCConfigCache> rpc_cache;
+#ifdef DEBUG_ENABLED
+ _FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id, int p_size);
+#endif
+
protected:
- _FORCE_INLINE_ void _profile_node_data(const String &p_what, ObjectID p_id);
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);
diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.h b/modules/navigation/editor/navigation_mesh_editor_plugin.h
index bc9e4185b7..b7bde98131 100644
--- a/modules/navigation/editor/navigation_mesh_editor_plugin.h
+++ b/modules/navigation/editor/navigation_mesh_editor_plugin.h
@@ -35,6 +35,8 @@
#include "editor/editor_plugin.h"
+class AcceptDialog;
+class HBoxContainer;
class NavigationRegion3D;
class NavigationMeshEditor : public Control {
diff --git a/modules/navigation/nav_link.h b/modules/navigation/nav_link.h
index 8d57f076c0..8f51a63951 100644
--- a/modules/navigation/nav_link.h
+++ b/modules/navigation/nav_link.h
@@ -37,8 +37,8 @@
class NavLink : public NavBase {
NavMap *map = nullptr;
bool bidirectional = true;
- Vector3 start_location = Vector3();
- Vector3 end_location = Vector3();
+ Vector3 start_location;
+ Vector3 end_location;
bool link_dirty = true;
diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp
index e8e73e4fd9..47f5f8f819 100644
--- a/modules/noise/editor/noise_editor_plugin.cpp
+++ b/modules/noise/editor/noise_editor_plugin.cpp
@@ -32,7 +32,9 @@
#ifdef TOOLS_ENABLED
+#include "editor/editor_inspector.h"
#include "editor/editor_scale.h"
+#include "scene/gui/texture_rect.h"
#include "modules/noise/noise.h"
#include "modules/noise/noise_texture_2d.h"
diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
index 4d996e6283..29208efb20 100644
--- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
+++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp
@@ -91,8 +91,6 @@ bool OpenXRHTCViveTrackerExtension::is_path_supported(const String &p_path) {
return available;
} else if (p_path == "/user/vive_tracker_htcx/role/chest") {
return available;
- } else if (p_path == "/user/vive_tracker_htcx/role/chest") {
- return available;
} else if (p_path == "/user/vive_tracker_htcx/role/camera") {
return available;
} else if (p_path == "/user/vive_tracker_htcx/role/keyboard") {
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index be6b7e4411..77660eb6f0 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -666,6 +666,7 @@ Transform3D OpenXRInterface::get_camera_transform() {
Transform3D OpenXRInterface::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, Transform3D());
+ ERR_FAIL_UNSIGNED_INDEX_V_MSG(p_view, get_view_count(), Transform3D(), "View index outside bounds.");
Transform3D t;
if (openxr_api && openxr_api->get_view_transform(p_view, t)) {
@@ -685,6 +686,7 @@ Transform3D OpenXRInterface::get_transform_for_view(uint32_t p_view, const Trans
Projection OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
Projection cm;
+ ERR_FAIL_UNSIGNED_INDEX_V_MSG(p_view, get_view_count(), cm, "View index outside bounds.");
if (openxr_api) {
if (openxr_api->get_view_projection(p_view, p_z_near, p_z_far, cm)) {
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index bd208a8429..3c7a89b705 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -39,6 +39,9 @@ thirdparty_obj = []
freetype_enabled = "freetype" in env.module_list
msdfgen_enabled = "msdfgen" in env.module_list
+if "svg" in env.module_list:
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/thorvg/inc", "#thirdparty/thorvg/src/lib"])
+
if env["builtin_harfbuzz"]:
env_harfbuzz = env_modules.Clone()
env_harfbuzz.disable_warnings()
diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct
index 65b41e46ce..4a363fdd7a 100644
--- a/modules/text_server_adv/gdextension_build/SConstruct
+++ b/modules/text_server_adv/gdextension_build/SConstruct
@@ -23,6 +23,7 @@ opts.Add(BoolVariable("brotli_enabled", "Use Brotli library", True))
opts.Add(BoolVariable("freetype_enabled", "Use FreeType library", True))
opts.Add(BoolVariable("msdfgen_enabled", "Use MSDFgen library (require FreeType)", True))
opts.Add(BoolVariable("graphite_enabled", "Use Graphite library (require FreeType)", True))
+opts.Add(BoolVariable("thorvg_enabled", "Use ThorVG library (require FreeType)", True))
opts.Add(BoolVariable("static_icu_data", "Use built-in ICU data", True))
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
@@ -34,6 +35,79 @@ if not env["verbose"]:
if env["platform"] == "windows" and not env["use_mingw"]:
env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding.
+# ThorVG
+if env["thorvg_enabled"] and env["freetype_enabled"]:
+ env_tvg = env.Clone()
+ env_tvg.disable_warnings()
+
+ thirdparty_tvg_dir = "../../../thirdparty/thorvg/"
+ thirdparty_tvg_sources = [
+ "src/lib/sw_engine/tvgSwFill.cpp",
+ "src/lib/sw_engine/tvgSwImage.cpp",
+ "src/lib/sw_engine/tvgSwMath.cpp",
+ "src/lib/sw_engine/tvgSwMemPool.cpp",
+ "src/lib/sw_engine/tvgSwRaster.cpp",
+ "src/lib/sw_engine/tvgSwRenderer.cpp",
+ "src/lib/sw_engine/tvgSwRle.cpp",
+ "src/lib/sw_engine/tvgSwShape.cpp",
+ "src/lib/sw_engine/tvgSwStroke.cpp",
+ "src/lib/tvgAccessor.cpp",
+ "src/lib/tvgBezier.cpp",
+ "src/lib/tvgCanvas.cpp",
+ "src/lib/tvgFill.cpp",
+ "src/lib/tvgGlCanvas.cpp",
+ "src/lib/tvgInitializer.cpp",
+ "src/lib/tvgLinearGradient.cpp",
+ "src/lib/tvgLoader.cpp",
+ "src/lib/tvgLzw.cpp",
+ "src/lib/tvgPaint.cpp",
+ "src/lib/tvgPicture.cpp",
+ "src/lib/tvgRadialGradient.cpp",
+ "src/lib/tvgRender.cpp",
+ "src/lib/tvgSaver.cpp",
+ "src/lib/tvgScene.cpp",
+ "src/lib/tvgShape.cpp",
+ "src/lib/tvgSwCanvas.cpp",
+ "src/lib/tvgTaskScheduler.cpp",
+ "src/loaders/external_png/tvgPngLoader.cpp",
+ "src/loaders/jpg/tvgJpgd.cpp",
+ "src/loaders/jpg/tvgJpgLoader.cpp",
+ "src/loaders/raw/tvgRawLoader.cpp",
+ "src/loaders/svg/tvgSvgCssStyle.cpp",
+ "src/loaders/svg/tvgSvgLoader.cpp",
+ "src/loaders/svg/tvgSvgPath.cpp",
+ "src/loaders/svg/tvgSvgSceneBuilder.cpp",
+ "src/loaders/svg/tvgSvgUtil.cpp",
+ "src/loaders/svg/tvgXmlParser.cpp",
+ "src/loaders/tvg/tvgTvgBinInterpreter.cpp",
+ "src/loaders/tvg/tvgTvgLoader.cpp",
+ "src/savers/tvg/tvgTvgSaver.cpp",
+ ]
+ thirdparty_tvg_sources = [thirdparty_tvg_dir + file for file in thirdparty_tvg_sources]
+
+ env_tvg.Append(
+ CPPPATH=[
+ "../../../thirdparty/thorvg/inc",
+ "../../../thirdparty/thorvg/src/lib",
+ "../../../thirdparty/thorvg/src/lib/sw_engine",
+ "../../../thirdparty/thorvg/src/loaders/external_png",
+ "../../../thirdparty/thorvg/src/loaders/jpg",
+ "../../../thirdparty/thorvg/src/loaders/raw",
+ "../../../thirdparty/thorvg/src/loaders/svg",
+ "../../../thirdparty/thorvg/src/loaders/tvg",
+ "../../../thirdparty/thorvg/src/savers/tvg",
+ "../../../thirdparty/libpng",
+ ]
+ )
+ env.Append(CPPPATH=["../../../thirdparty/thorvg/inc", "../../../thirdparty/thorvg/src/lib"])
+ env.Append(CPPDEFINES=["MODULE_SVG_ENABLED"])
+
+ lib = env_tvg.Library(
+ f'tvg_builtin{env["suffix"]}{env["LIBSUFFIX"]}',
+ thirdparty_tvg_sources,
+ )
+ env.Append(LIBS=[lib])
+
# MSDFGEN
if env["msdfgen_enabled"] and env["freetype_enabled"]:
env_msdfgen = env.Clone()
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 155da3c67b..166325c551 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -41,6 +41,8 @@
using namespace godot;
+#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
+
#else
// Headers for building as built-in module.
@@ -50,7 +52,7 @@ using namespace godot;
#include "core/string/print_string.h"
#include "core/string/translation.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -69,6 +71,10 @@ using namespace godot;
#include "msdfgen.h"
#endif
+#ifdef MODULE_SVG_ENABLED
+#include "thorvg_svg_in_ot.h"
+#endif
+
/*************************************************************************/
/* bmp_font_t HarfBuzz Bitmap font interface */
/*************************************************************************/
@@ -1346,6 +1352,9 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
}
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
memset(&fd->stream, 0, sizeof(FT_StreamRec));
@@ -1888,6 +1897,9 @@ int64_t TextServerAdvanced::_font_get_face_count(const RID &p_font_rid) const {
if (!ft_library) {
error = FT_Init_FreeType(&ft_library);
ERR_FAIL_COND_V_MSG(error != 0, false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
FT_StreamRec stream;
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 33fa1e117e..10fe3c2316 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -88,7 +88,7 @@ using namespace godot;
#include "core/templates/rid_owner.h"
#include "scene/resources/texture.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -117,6 +117,7 @@ using namespace godot;
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_BBOX_H
+#include FT_MODULE_H
#include FT_CONFIG_OPTIONS_H
#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER)
#warning FreeType is configured without Brotli support, built-in fonts will not be available.
diff --git a/modules/text_server_adv/thorvg_bounds_iterator.cpp b/modules/text_server_adv/thorvg_bounds_iterator.cpp
new file mode 100644
index 0000000000..54a6136134
--- /dev/null
+++ b/modules/text_server_adv/thorvg_bounds_iterator.cpp
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+
+#include <tvgIteratorAccessor.h>
+#include <tvgPaint.h>
+
+// This function uses private ThorVG API to get bounding box of top level children elements.
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y) {
+ tvg::IteratorAccessor itrAccessor;
+ if (tvg::Iterator *it = itrAccessor.iterator(p_picture)) {
+ while (const tvg::Paint *child = it->next()) {
+ float x = 0, y = 0, w = 0, h = 0;
+ child->bounds(&x, &y, &w, &h, true);
+ r_min_x = MIN(x, r_min_x);
+ r_min_y = MIN(y, r_min_y);
+ r_max_x = MAX(x + w, r_max_x);
+ r_max_y = MAX(y + h, r_max_y);
+ }
+ delete (it);
+ }
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_adv/thorvg_bounds_iterator.h b/modules/text_server_adv/thorvg_bounds_iterator.h
new file mode 100644
index 0000000000..e54e30eaa2
--- /dev/null
+++ b/modules/text_server_adv/thorvg_bounds_iterator.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef THORVG_BOUNDS_ITERATOR_H
+#define THORVG_BOUNDS_ITERATOR_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <thorvg.h>
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y);
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_BOUNDS_ITERATOR_H
diff --git a/modules/text_server_adv/thorvg_svg_in_ot.cpp b/modules/text_server_adv/thorvg_svg_in_ot.cpp
new file mode 100644
index 0000000000..7863ab67fa
--- /dev/null
+++ b/modules/text_server_adv/thorvg_svg_in_ot.cpp
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/classes/xml_parser.hpp>
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/vector.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/error/error_macros.h"
+#include "core/io/xml_parser.h"
+#include "core/os/memory.h"
+#include "core/os/os.h"
+#include "core/string/ustring.h"
+#include "core/typedefs.h"
+#include "core/variant/variant.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+#include "thorvg_svg_in_ot.h"
+
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+
+#include <math.h>
+#include <stdlib.h>
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state) {
+ *p_state = memnew(TVG_State);
+
+ return FT_Err_Ok;
+}
+
+void tvg_svg_in_ot_free(FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ memdelete(state);
+}
+
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ FT_SVG_Document document = (FT_SVG_Document)p_slot->other;
+ FT_Size_Metrics metrics = document->metrics;
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ if (!gl_state.ready) {
+ Ref<XMLParser> parser;
+ parser.instantiate();
+#ifdef GDEXTENSION
+ PackedByteArray data;
+ data.resize(document->svg_document_length);
+ memcpy(data.ptrw(), document->svg_document, document->svg_document_length);
+ parser->open_buffer(data);
+#else
+ parser->_open_buffer((const uint8_t *)document->svg_document, document->svg_document_length);
+#endif
+
+ float aspect = 1.0f;
+ String xml_body;
+ while (parser->read() == OK) {
+ if (parser->has_attribute("id")) {
+#ifdef GDEXTENSION
+ const String &gl_name = parser->get_named_attribute_value("id");
+#else
+ const String &gl_name = parser->get_attribute_value("id");
+#endif
+ if (gl_name.begins_with("glyph")) {
+ int dot_pos = gl_name.find(".");
+ int64_t gl_idx = gl_name.substr(5, (dot_pos > 0) ? dot_pos - 5 : -1).to_int();
+ if (p_slot->glyph_index != gl_idx) {
+ parser->skip_section();
+ continue;
+ }
+ }
+ }
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name() == "svg") {
+ if (parser->has_attribute("viewBox")) {
+#ifdef GDEXTENSION
+ PackedStringArray vb = parser->get_named_attribute_value("viewBox").split(" ");
+#else
+ Vector<String> vb = parser->get_attribute_value("viewBox").split(" ");
+#endif
+
+ if (vb.size() == 4) {
+ aspect = vb[2].to_float() / vb[3].to_float();
+ }
+ }
+ continue;
+ }
+#ifdef GDEXTENSION
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body = xml_body + "<" + parser->get_node_name();
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body = xml_body + " " + parser->get_attribute_name(i) + "=\"" + parser->get_attribute_value(i) + "\"";
+ }
+ xml_body = xml_body + ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body = xml_body + parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body = xml_body + "</" + parser->get_node_name() + ">";
+ }
+#else
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body += vformat("<%s", parser->get_node_name());
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body += vformat(" %s=\"%s\"", parser->get_attribute_name(i), parser->get_attribute_value(i));
+ }
+ xml_body += ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body += parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body += vformat("</%s>", parser->get_node_name());
+ }
+#endif
+ }
+ String temp_xml = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 0 0\">" + xml_body;
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result result = picture->load(temp_xml.utf8().get_data(), temp_xml.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (bounds detection).");
+ }
+
+ float min_x = INFINITY, min_y = INFINITY, max_x = -INFINITY, max_y = -INFINITY;
+ tvg_get_bounds(picture.get(), min_x, min_y, max_x, max_y);
+
+ float new_h = (max_y - min_y);
+ float new_w = (max_x - min_x);
+
+ if (new_h * aspect >= new_w) {
+ new_w = (new_h * aspect);
+ } else {
+ new_h = (new_w / aspect);
+ }
+
+#ifdef GDEXTENSION
+ gl_state.xml_code = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"" + rtos(min_x) + " " + rtos(min_y) + " " + rtos(new_w) + " " + rtos(new_h) + "\">" + xml_body;
+#else
+ gl_state.xml_code = vformat("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%f %f %f %f\">", min_x, min_y, new_w, new_h) + xml_body;
+#endif
+
+ picture = tvg::Picture::gen();
+ result = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph metrics).");
+ }
+
+ float x_svg_to_out, y_svg_to_out;
+ x_svg_to_out = (float)metrics.x_ppem / new_w;
+ y_svg_to_out = (float)metrics.y_ppem / new_h;
+
+ gl_state.m.e11 = (double)document->transform.xx / (1 << 16) * x_svg_to_out;
+ gl_state.m.e12 = -(double)document->transform.xy / (1 << 16) * x_svg_to_out;
+ gl_state.m.e21 = -(double)document->transform.yx / (1 << 16) * y_svg_to_out;
+ gl_state.m.e22 = (double)document->transform.yy / (1 << 16) * y_svg_to_out;
+ gl_state.m.e13 = (double)document->delta.x / 64 * new_w / metrics.x_ppem;
+ gl_state.m.e23 = -(double)document->delta.y / 64 * new_h / metrics.y_ppem;
+ gl_state.m.e31 = 0;
+ gl_state.m.e32 = 0;
+ gl_state.m.e33 = 1;
+
+ result = picture->transform(gl_state.m);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ result = picture->bounds(&gl_state.x, &gl_state.y, &gl_state.w, &gl_state.h, true);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to get SVG bounds.");
+ }
+
+ gl_state.bmp_y = -min_y * gl_state.h / new_h;
+ gl_state.bmp_x = min_x * gl_state.w / new_w;
+
+ gl_state.ready = true;
+ }
+
+ p_slot->bitmap_left = (FT_Int)gl_state.bmp_x;
+ p_slot->bitmap_top = (FT_Int)gl_state.bmp_y;
+
+ float tmp = ceil(gl_state.h);
+ p_slot->bitmap.rows = (unsigned int)tmp;
+ tmp = ceil(gl_state.w);
+ p_slot->bitmap.width = (unsigned int)tmp;
+ p_slot->bitmap.pitch = (int)p_slot->bitmap.width * 4;
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+
+ float metrics_width, metrics_height;
+ float horiBearingX, horiBearingY;
+ float vertBearingX, vertBearingY;
+
+ metrics_width = (float)gl_state.w;
+ metrics_height = (float)gl_state.h;
+ horiBearingX = (float)gl_state.x;
+ horiBearingY = (float)-gl_state.y;
+ vertBearingX = p_slot->metrics.horiBearingX / 64.0f - p_slot->metrics.horiAdvance / 64.0f / 2;
+ vertBearingY = (p_slot->metrics.vertAdvance / 64.0f - p_slot->metrics.height / 64.0f) / 2;
+
+ tmp = roundf(metrics_width * 64);
+ p_slot->metrics.width = (FT_Pos)tmp;
+ tmp = roundf(metrics_height * 64);
+ p_slot->metrics.height = (FT_Pos)tmp;
+
+ p_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64);
+ p_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64);
+ p_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64);
+ p_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64);
+
+ if (p_slot->metrics.vertAdvance == 0) {
+ p_slot->metrics.vertAdvance = (FT_Pos)(metrics_height * 1.2f * 64);
+ }
+
+ return FT_Err_Ok;
+}
+
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ if (!state->glyph_map.has(p_slot->glyph_index)) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG glyph not loaded.");
+ }
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ ERR_FAIL_COND_V_MSG(!gl_state.ready, FT_Err_Invalid_SVG_Document, "SVG glyph not ready.");
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result res = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph rendering).");
+ }
+ res = picture->transform(gl_state.m);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
+ res = sw_canvas->target((uint32_t *)p_slot->bitmap.buffer, (int)p_slot->bitmap.width, (int)p_slot->bitmap.width, (int)p_slot->bitmap.rows, tvg::SwCanvas::ARGB8888_STRAIGHT);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to create SVG canvas.");
+ }
+ res = sw_canvas->push(std::move(picture));
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to set SVG canvas source.");
+ }
+ res = sw_canvas->draw();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to draw to SVG canvas.");
+ }
+ res = sw_canvas->sync();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to sync SVG canvas.");
+ }
+
+ state->glyph_map.erase(p_slot->glyph_index);
+
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+ p_slot->bitmap.num_grays = 256;
+ p_slot->format = FT_GLYPH_FORMAT_BITMAP;
+
+ return FT_Err_Ok;
+}
+
+SVG_RendererHooks tvg_svg_in_ot_hooks = {
+ (SVG_Lib_Init_Func)tvg_svg_in_ot_init,
+ (SVG_Lib_Free_Func)tvg_svg_in_ot_free,
+ (SVG_Lib_Render_Func)tvg_svg_in_ot_render,
+ (SVG_Lib_Preset_Slot_Func)tvg_svg_in_ot_preset_slot,
+};
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks() {
+ return &tvg_svg_in_ot_hooks;
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_adv/thorvg_svg_in_ot.h b/modules/text_server_adv/thorvg_svg_in_ot.h
new file mode 100644
index 0000000000..b2816193d9
--- /dev/null
+++ b/modules/text_server_adv/thorvg_svg_in_ot.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef THORVG_SVG_IN_OT_H
+#define THORVG_SVG_IN_OT_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/hash_map.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/os/mutex.h"
+#include "core/templates/hash_map.h"
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <freetype/freetype.h>
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+#include <thorvg.h>
+
+struct GL_State {
+ bool ready = false;
+ float bmp_x = 0;
+ float bmp_y = 0;
+ float x = 0;
+ float y = 0;
+ float w = 0;
+ float h = 0;
+ String xml_code;
+ tvg::Matrix m;
+};
+
+struct TVG_State {
+ Mutex mutex;
+ HashMap<uint32_t, GL_State> glyph_map;
+};
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state);
+void tvg_svg_in_ot_free(FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state);
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks();
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_SVG_IN_OT_H
diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub
index 429d2e1fdc..f1d57ec4d3 100644
--- a/modules/text_server_fb/SCsub
+++ b/modules/text_server_fb/SCsub
@@ -8,6 +8,9 @@ msdfgen_enabled = "msdfgen" in env.module_list
env_text_server_fb = env_modules.Clone()
+if "svg" in env.module_list:
+ env_text_server_fb.Prepend(CPPPATH=["#thirdparty/thorvg/inc", "#thirdparty/thorvg/src/lib"])
+
if env["builtin_msdfgen"] and msdfgen_enabled:
env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"])
diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct
index 8ed8f61a43..7b4c548a21 100644
--- a/modules/text_server_fb/gdextension_build/SConstruct
+++ b/modules/text_server_fb/gdextension_build/SConstruct
@@ -22,6 +22,7 @@ opts = Variables([], ARGUMENTS)
opts.Add(BoolVariable("brotli_enabled", "Use Brotli library", True))
opts.Add(BoolVariable("freetype_enabled", "Use FreeType library", True))
opts.Add(BoolVariable("msdfgen_enabled", "Use MSDFgen library (require FreeType)", True))
+opts.Add(BoolVariable("thorvg_enabled", "Use ThorVG library (require FreeType)", True))
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
opts.Update(env)
@@ -29,6 +30,79 @@ opts.Update(env)
if not env["verbose"]:
methods.no_verbose(sys, env)
+# ThorVG
+if env["thorvg_enabled"] and env["freetype_enabled"]:
+ env_tvg = env.Clone()
+ env_tvg.disable_warnings()
+
+ thirdparty_tvg_dir = "../../../thirdparty/thorvg/"
+ thirdparty_tvg_sources = [
+ "src/lib/sw_engine/tvgSwFill.cpp",
+ "src/lib/sw_engine/tvgSwImage.cpp",
+ "src/lib/sw_engine/tvgSwMath.cpp",
+ "src/lib/sw_engine/tvgSwMemPool.cpp",
+ "src/lib/sw_engine/tvgSwRaster.cpp",
+ "src/lib/sw_engine/tvgSwRenderer.cpp",
+ "src/lib/sw_engine/tvgSwRle.cpp",
+ "src/lib/sw_engine/tvgSwShape.cpp",
+ "src/lib/sw_engine/tvgSwStroke.cpp",
+ "src/lib/tvgAccessor.cpp",
+ "src/lib/tvgBezier.cpp",
+ "src/lib/tvgCanvas.cpp",
+ "src/lib/tvgFill.cpp",
+ "src/lib/tvgGlCanvas.cpp",
+ "src/lib/tvgInitializer.cpp",
+ "src/lib/tvgLinearGradient.cpp",
+ "src/lib/tvgLoader.cpp",
+ "src/lib/tvgLzw.cpp",
+ "src/lib/tvgPaint.cpp",
+ "src/lib/tvgPicture.cpp",
+ "src/lib/tvgRadialGradient.cpp",
+ "src/lib/tvgRender.cpp",
+ "src/lib/tvgSaver.cpp",
+ "src/lib/tvgScene.cpp",
+ "src/lib/tvgShape.cpp",
+ "src/lib/tvgSwCanvas.cpp",
+ "src/lib/tvgTaskScheduler.cpp",
+ "src/loaders/external_png/tvgPngLoader.cpp",
+ "src/loaders/jpg/tvgJpgd.cpp",
+ "src/loaders/jpg/tvgJpgLoader.cpp",
+ "src/loaders/raw/tvgRawLoader.cpp",
+ "src/loaders/svg/tvgSvgCssStyle.cpp",
+ "src/loaders/svg/tvgSvgLoader.cpp",
+ "src/loaders/svg/tvgSvgPath.cpp",
+ "src/loaders/svg/tvgSvgSceneBuilder.cpp",
+ "src/loaders/svg/tvgSvgUtil.cpp",
+ "src/loaders/svg/tvgXmlParser.cpp",
+ "src/loaders/tvg/tvgTvgBinInterpreter.cpp",
+ "src/loaders/tvg/tvgTvgLoader.cpp",
+ "src/savers/tvg/tvgTvgSaver.cpp",
+ ]
+ thirdparty_tvg_sources = [thirdparty_tvg_dir + file for file in thirdparty_tvg_sources]
+
+ env_tvg.Append(
+ CPPPATH=[
+ "../../../thirdparty/thorvg/inc",
+ "../../../thirdparty/thorvg/src/lib",
+ "../../../thirdparty/thorvg/src/lib/sw_engine",
+ "../../../thirdparty/thorvg/src/loaders/external_png",
+ "../../../thirdparty/thorvg/src/loaders/jpg",
+ "../../../thirdparty/thorvg/src/loaders/raw",
+ "../../../thirdparty/thorvg/src/loaders/svg",
+ "../../../thirdparty/thorvg/src/loaders/tvg",
+ "../../../thirdparty/thorvg/src/savers/tvg",
+ "../../../thirdparty/libpng",
+ ]
+ )
+ env.Append(CPPPATH=["../../../thirdparty/thorvg/inc", "../../../thirdparty/thorvg/src/lib"])
+ env.Append(CPPDEFINES=["MODULE_SVG_ENABLED"])
+
+ lib = env_tvg.Library(
+ f'tvg_builtin{env["suffix"]}{env["LIBSUFFIX"]}',
+ thirdparty_tvg_sources,
+ )
+ env.Append(LIBS=[lib])
+
# MSDFGEN
if env["msdfgen_enabled"] and env["freetype_enabled"]:
env_msdfgen = env.Clone()
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 999870b904..aaef9c9a3d 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -41,6 +41,8 @@
using namespace godot;
+#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
+
#else
// Headers for building as built-in module.
@@ -49,7 +51,7 @@ using namespace godot;
#include "core/string/print_string.h"
#include "core/string/ucaps.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -62,6 +64,10 @@ using namespace godot;
#include "msdfgen.h"
#endif
+#ifdef MODULE_SVG_ENABLED
+#include "thorvg_svg_in_ot.h"
+#endif
+
/*************************************************************************/
#define OT_TAG(c1, c2, c3, c4) ((int32_t)((((uint32_t)(c1)&0xff) << 24) | (((uint32_t)(c2)&0xff) << 16) | (((uint32_t)(c3)&0xff) << 8) | ((uint32_t)(c4)&0xff)))
@@ -771,6 +777,9 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f
memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
}
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
memset(&fd->stream, 0, sizeof(FT_StreamRec));
@@ -992,6 +1001,9 @@ int64_t TextServerFallback::_font_get_face_count(const RID &p_font_rid) const {
if (!ft_library) {
error = FT_Init_FreeType(&ft_library);
ERR_FAIL_COND_V_MSG(error != 0, false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
+#ifdef MODULE_SVG_ENABLED
+ FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
+#endif
}
FT_StreamRec stream;
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 151ae13904..7e0bc99618 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -87,7 +87,7 @@ using namespace godot;
#include "core/templates/rid_owner.h"
#include "scene/resources/texture.h"
-#include "modules/modules_enabled.gen.h" // For freetype, msdfgen.
+#include "modules/modules_enabled.gen.h" // For freetype, msdfgen, svg.
#endif
@@ -101,6 +101,7 @@ using namespace godot;
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#include FT_BBOX_H
+#include FT_MODULE_H
#include FT_CONFIG_OPTIONS_H
#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER)
#warning FreeType is configured without Brotli support, built-in fonts will not be available.
diff --git a/modules/text_server_fb/thorvg_bounds_iterator.cpp b/modules/text_server_fb/thorvg_bounds_iterator.cpp
new file mode 100644
index 0000000000..54a6136134
--- /dev/null
+++ b/modules/text_server_fb/thorvg_bounds_iterator.cpp
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+
+#include <tvgIteratorAccessor.h>
+#include <tvgPaint.h>
+
+// This function uses private ThorVG API to get bounding box of top level children elements.
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y) {
+ tvg::IteratorAccessor itrAccessor;
+ if (tvg::Iterator *it = itrAccessor.iterator(p_picture)) {
+ while (const tvg::Paint *child = it->next()) {
+ float x = 0, y = 0, w = 0, h = 0;
+ child->bounds(&x, &y, &w, &h, true);
+ r_min_x = MIN(x, r_min_x);
+ r_min_y = MIN(y, r_min_y);
+ r_max_x = MAX(x + w, r_max_x);
+ r_max_y = MAX(y + h, r_max_y);
+ }
+ delete (it);
+ }
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_fb/thorvg_bounds_iterator.h b/modules/text_server_fb/thorvg_bounds_iterator.h
new file mode 100644
index 0000000000..e54e30eaa2
--- /dev/null
+++ b/modules/text_server_fb/thorvg_bounds_iterator.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* thorvg_bounds_iterator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef THORVG_BOUNDS_ITERATOR_H
+#define THORVG_BOUNDS_ITERATOR_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <thorvg.h>
+
+void tvg_get_bounds(tvg::Picture *p_picture, float &r_min_x, float &r_min_y, float &r_max_x, float &r_max_y);
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_BOUNDS_ITERATOR_H
diff --git a/modules/text_server_fb/thorvg_svg_in_ot.cpp b/modules/text_server_fb/thorvg_svg_in_ot.cpp
new file mode 100644
index 0000000000..7863ab67fa
--- /dev/null
+++ b/modules/text_server_fb/thorvg_svg_in_ot.cpp
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/classes/xml_parser.hpp>
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/vector.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/error/error_macros.h"
+#include "core/io/xml_parser.h"
+#include "core/os/memory.h"
+#include "core/os/os.h"
+#include "core/string/ustring.h"
+#include "core/typedefs.h"
+#include "core/variant/variant.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include "thorvg_bounds_iterator.h"
+#include "thorvg_svg_in_ot.h"
+
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+
+#include <math.h>
+#include <stdlib.h>
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state) {
+ *p_state = memnew(TVG_State);
+
+ return FT_Err_Ok;
+}
+
+void tvg_svg_in_ot_free(FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ memdelete(state);
+}
+
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ FT_SVG_Document document = (FT_SVG_Document)p_slot->other;
+ FT_Size_Metrics metrics = document->metrics;
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ if (!gl_state.ready) {
+ Ref<XMLParser> parser;
+ parser.instantiate();
+#ifdef GDEXTENSION
+ PackedByteArray data;
+ data.resize(document->svg_document_length);
+ memcpy(data.ptrw(), document->svg_document, document->svg_document_length);
+ parser->open_buffer(data);
+#else
+ parser->_open_buffer((const uint8_t *)document->svg_document, document->svg_document_length);
+#endif
+
+ float aspect = 1.0f;
+ String xml_body;
+ while (parser->read() == OK) {
+ if (parser->has_attribute("id")) {
+#ifdef GDEXTENSION
+ const String &gl_name = parser->get_named_attribute_value("id");
+#else
+ const String &gl_name = parser->get_attribute_value("id");
+#endif
+ if (gl_name.begins_with("glyph")) {
+ int dot_pos = gl_name.find(".");
+ int64_t gl_idx = gl_name.substr(5, (dot_pos > 0) ? dot_pos - 5 : -1).to_int();
+ if (p_slot->glyph_index != gl_idx) {
+ parser->skip_section();
+ continue;
+ }
+ }
+ }
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name() == "svg") {
+ if (parser->has_attribute("viewBox")) {
+#ifdef GDEXTENSION
+ PackedStringArray vb = parser->get_named_attribute_value("viewBox").split(" ");
+#else
+ Vector<String> vb = parser->get_attribute_value("viewBox").split(" ");
+#endif
+
+ if (vb.size() == 4) {
+ aspect = vb[2].to_float() / vb[3].to_float();
+ }
+ }
+ continue;
+ }
+#ifdef GDEXTENSION
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body = xml_body + "<" + parser->get_node_name();
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body = xml_body + " " + parser->get_attribute_name(i) + "=\"" + parser->get_attribute_value(i) + "\"";
+ }
+ xml_body = xml_body + ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body = xml_body + parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body = xml_body + "</" + parser->get_node_name() + ">";
+ }
+#else
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+ xml_body += vformat("<%s", parser->get_node_name());
+ for (int i = 0; i < parser->get_attribute_count(); i++) {
+ xml_body += vformat(" %s=\"%s\"", parser->get_attribute_name(i), parser->get_attribute_value(i));
+ }
+ xml_body += ">";
+ } else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
+ xml_body += parser->get_node_data();
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
+ xml_body += vformat("</%s>", parser->get_node_name());
+ }
+#endif
+ }
+ String temp_xml = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 0 0\">" + xml_body;
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result result = picture->load(temp_xml.utf8().get_data(), temp_xml.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (bounds detection).");
+ }
+
+ float min_x = INFINITY, min_y = INFINITY, max_x = -INFINITY, max_y = -INFINITY;
+ tvg_get_bounds(picture.get(), min_x, min_y, max_x, max_y);
+
+ float new_h = (max_y - min_y);
+ float new_w = (max_x - min_x);
+
+ if (new_h * aspect >= new_w) {
+ new_w = (new_h * aspect);
+ } else {
+ new_h = (new_w / aspect);
+ }
+
+#ifdef GDEXTENSION
+ gl_state.xml_code = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"" + rtos(min_x) + " " + rtos(min_y) + " " + rtos(new_w) + " " + rtos(new_h) + "\">" + xml_body;
+#else
+ gl_state.xml_code = vformat("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%f %f %f %f\">", min_x, min_y, new_w, new_h) + xml_body;
+#endif
+
+ picture = tvg::Picture::gen();
+ result = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph metrics).");
+ }
+
+ float x_svg_to_out, y_svg_to_out;
+ x_svg_to_out = (float)metrics.x_ppem / new_w;
+ y_svg_to_out = (float)metrics.y_ppem / new_h;
+
+ gl_state.m.e11 = (double)document->transform.xx / (1 << 16) * x_svg_to_out;
+ gl_state.m.e12 = -(double)document->transform.xy / (1 << 16) * x_svg_to_out;
+ gl_state.m.e21 = -(double)document->transform.yx / (1 << 16) * y_svg_to_out;
+ gl_state.m.e22 = (double)document->transform.yy / (1 << 16) * y_svg_to_out;
+ gl_state.m.e13 = (double)document->delta.x / 64 * new_w / metrics.x_ppem;
+ gl_state.m.e23 = -(double)document->delta.y / 64 * new_h / metrics.y_ppem;
+ gl_state.m.e31 = 0;
+ gl_state.m.e32 = 0;
+ gl_state.m.e33 = 1;
+
+ result = picture->transform(gl_state.m);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ result = picture->bounds(&gl_state.x, &gl_state.y, &gl_state.w, &gl_state.h, true);
+ if (result != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to get SVG bounds.");
+ }
+
+ gl_state.bmp_y = -min_y * gl_state.h / new_h;
+ gl_state.bmp_x = min_x * gl_state.w / new_w;
+
+ gl_state.ready = true;
+ }
+
+ p_slot->bitmap_left = (FT_Int)gl_state.bmp_x;
+ p_slot->bitmap_top = (FT_Int)gl_state.bmp_y;
+
+ float tmp = ceil(gl_state.h);
+ p_slot->bitmap.rows = (unsigned int)tmp;
+ tmp = ceil(gl_state.w);
+ p_slot->bitmap.width = (unsigned int)tmp;
+ p_slot->bitmap.pitch = (int)p_slot->bitmap.width * 4;
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+
+ float metrics_width, metrics_height;
+ float horiBearingX, horiBearingY;
+ float vertBearingX, vertBearingY;
+
+ metrics_width = (float)gl_state.w;
+ metrics_height = (float)gl_state.h;
+ horiBearingX = (float)gl_state.x;
+ horiBearingY = (float)-gl_state.y;
+ vertBearingX = p_slot->metrics.horiBearingX / 64.0f - p_slot->metrics.horiAdvance / 64.0f / 2;
+ vertBearingY = (p_slot->metrics.vertAdvance / 64.0f - p_slot->metrics.height / 64.0f) / 2;
+
+ tmp = roundf(metrics_width * 64);
+ p_slot->metrics.width = (FT_Pos)tmp;
+ tmp = roundf(metrics_height * 64);
+ p_slot->metrics.height = (FT_Pos)tmp;
+
+ p_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64);
+ p_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64);
+ p_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64);
+ p_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64);
+
+ if (p_slot->metrics.vertAdvance == 0) {
+ p_slot->metrics.vertAdvance = (FT_Pos)(metrics_height * 1.2f * 64);
+ }
+
+ return FT_Err_Ok;
+}
+
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state) {
+ TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
+ if (!state) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
+ }
+ MutexLock lock(state->mutex);
+
+ if (!state->glyph_map.has(p_slot->glyph_index)) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG glyph not loaded.");
+ }
+
+ GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
+ ERR_FAIL_COND_V_MSG(!gl_state.ready, FT_Err_Invalid_SVG_Document, "SVG glyph not ready.");
+
+ std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
+ tvg::Result res = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph rendering).");
+ }
+ res = picture->transform(gl_state.m);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
+ }
+
+ std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
+ res = sw_canvas->target((uint32_t *)p_slot->bitmap.buffer, (int)p_slot->bitmap.width, (int)p_slot->bitmap.width, (int)p_slot->bitmap.rows, tvg::SwCanvas::ARGB8888_STRAIGHT);
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to create SVG canvas.");
+ }
+ res = sw_canvas->push(std::move(picture));
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to set SVG canvas source.");
+ }
+ res = sw_canvas->draw();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to draw to SVG canvas.");
+ }
+ res = sw_canvas->sync();
+ if (res != tvg::Result::Success) {
+ ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to sync SVG canvas.");
+ }
+
+ state->glyph_map.erase(p_slot->glyph_index);
+
+ p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+ p_slot->bitmap.num_grays = 256;
+ p_slot->format = FT_GLYPH_FORMAT_BITMAP;
+
+ return FT_Err_Ok;
+}
+
+SVG_RendererHooks tvg_svg_in_ot_hooks = {
+ (SVG_Lib_Init_Func)tvg_svg_in_ot_init,
+ (SVG_Lib_Free_Func)tvg_svg_in_ot_free,
+ (SVG_Lib_Render_Func)tvg_svg_in_ot_render,
+ (SVG_Lib_Preset_Slot_Func)tvg_svg_in_ot_preset_slot,
+};
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks() {
+ return &tvg_svg_in_ot_hooks;
+}
+
+#endif // MODULE_SVG_ENABLED
diff --git a/modules/text_server_fb/thorvg_svg_in_ot.h b/modules/text_server_fb/thorvg_svg_in_ot.h
new file mode 100644
index 0000000000..b2816193d9
--- /dev/null
+++ b/modules/text_server_fb/thorvg_svg_in_ot.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* thorvg_svg_in_ot.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef THORVG_SVG_IN_OT_H
+#define THORVG_SVG_IN_OT_H
+
+#ifdef GDEXTENSION
+// Headers for building as GDExtension plug-in.
+
+#include <godot_cpp/core/mutex_lock.hpp>
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/templates/hash_map.hpp>
+
+using namespace godot;
+
+#else
+// Headers for building as built-in module.
+
+#include "core/os/mutex.h"
+#include "core/templates/hash_map.h"
+#include "core/typedefs.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#endif
+
+#ifdef MODULE_SVG_ENABLED
+
+#include <freetype/freetype.h>
+#include <freetype/otsvg.h>
+#include <ft2build.h>
+#include <thorvg.h>
+
+struct GL_State {
+ bool ready = false;
+ float bmp_x = 0;
+ float bmp_y = 0;
+ float x = 0;
+ float y = 0;
+ float w = 0;
+ float h = 0;
+ String xml_code;
+ tvg::Matrix m;
+};
+
+struct TVG_State {
+ Mutex mutex;
+ HashMap<uint32_t, GL_State> glyph_map;
+};
+
+FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state);
+void tvg_svg_in_ot_free(FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state);
+FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state);
+
+SVG_RendererHooks *get_tvg_svg_in_ot_hooks();
+
+#endif // MODULE_SVG_ENABLED
+
+#endif // THORVG_SVG_IN_OT_H
diff --git a/modules/theora/SCsub b/modules/theora/SCsub
index 6038ea086a..ca666050dd 100644
--- a/modules/theora/SCsub
+++ b/modules/theora/SCsub
@@ -15,7 +15,7 @@ if env["builtin_libtheora"]:
# "analyze.c",
# "apiwrapper.c",
"bitpack.c",
- "cpu.c",
+ # "collect.c",
# "decapiwrapper.c",
"decinfo.c",
"decode.c",
@@ -47,8 +47,12 @@ if env["builtin_libtheora"]:
"x86/mmxfrag.c",
"x86/mmxidct.c",
"x86/mmxstate.c",
+ # "x86/sse2encfrag.c",
# "x86/sse2fdct.c",
+ "x86/sse2idct.c",
+ "x86/x86cpu.c",
# "x86/x86enc.c",
+ # "x86/x86enquant.c"
"x86/x86state.c",
]
@@ -58,6 +62,7 @@ if env["builtin_libtheora"]:
"x86_vc/mmxfrag.c",
"x86_vc/mmxidct.c",
"x86_vc/mmxstate.c",
+ "x86_vc/x86cpu.c",
# "x86_vc/x86enc.c",
"x86_vc/x86state.c",
]
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 792103cd31..63909257d9 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -438,9 +438,7 @@ void AudioStreamOggVorbis::maybe_update_info() {
}
if (i == 0) {
packet->b_o_s = 1;
- }
- if (i == 0) {
ERR_FAIL_COND(!vorbis_synthesis_idheader(packet));
}
diff --git a/modules/webp/webp_common.cpp b/modules/webp/webp_common.cpp
index af98788420..572a33653e 100644
--- a/modules/webp/webp_common.cpp
+++ b/modules/webp/webp_common.cpp
@@ -41,40 +41,21 @@ namespace WebPCommon {
Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quality) {
ERR_FAIL_COND_V(p_image.is_null() || p_image->is_empty(), Vector<uint8_t>());
- Ref<Image> img = p_image->duplicate();
- if (img->detect_alpha()) {
- img->convert(Image::FORMAT_RGBA8);
- } else {
- img->convert(Image::FORMAT_RGB8);
- }
-
- Size2 s(img->get_width(), img->get_height());
- Vector<uint8_t> data = img->get_data();
- const uint8_t *r = data.ptr();
-
- uint8_t *dst_buff = nullptr;
- size_t dst_size = 0;
- if (img->get_format() == Image::FORMAT_RGB8) {
- dst_size = WebPEncodeRGB(r, s.width, s.height, 3 * s.width, CLAMP(p_quality * 100.0f, 0.0f, 100.0f), &dst_buff);
- } else {
- dst_size = WebPEncodeRGBA(r, s.width, s.height, 4 * s.width, CLAMP(p_quality * 100.0f, 0.0f, 100.0f), &dst_buff);
- }
-
- ERR_FAIL_COND_V(dst_size == 0, Vector<uint8_t>());
- Vector<uint8_t> dst;
- dst.resize(dst_size);
- uint8_t *w = dst.ptrw();
- memcpy(w, dst_buff, dst_size);
- WebPFree(dst_buff);
-
- return dst;
+ return _webp_packer(p_image, CLAMP(p_quality * 100.0f, 0.0f, 100.0f), false);
}
Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image) {
ERR_FAIL_COND_V(p_image.is_null() || p_image->is_empty(), Vector<uint8_t>());
- int compression_level = GLOBAL_GET("rendering/textures/lossless_compression/webp_compression_level");
- compression_level = CLAMP(compression_level, 0, 9);
+ float compression_factor = GLOBAL_GET("rendering/textures/webp_compression/lossless_compression_factor");
+ compression_factor = CLAMP(compression_factor, 0.0f, 100.0f);
+
+ return _webp_packer(p_image, compression_factor, true);
+}
+
+Vector<uint8_t> _webp_packer(const Ref<Image> &p_image, float p_quality, bool p_lossless) {
+ int compression_method = GLOBAL_GET("rendering/textures/webp_compression/compression_method");
+ compression_method = CLAMP(compression_method, 0, 6);
Ref<Image> img = p_image->duplicate();
if (img->detect_alpha()) {
@@ -87,16 +68,21 @@ Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image) {
Vector<uint8_t> data = img->get_data();
const uint8_t *r = data.ptr();
- // we need to use the more complex API in order to access the 'exact' flag...
+ // we need to use the more complex API in order to access specific flags...
WebPConfig config;
WebPPicture pic;
- if (!WebPConfigInit(&config) || !WebPConfigLosslessPreset(&config, compression_level) || !WebPPictureInit(&pic)) {
+ if (!WebPConfigInit(&config) || !WebPPictureInit(&pic)) {
ERR_FAIL_V(Vector<uint8_t>());
}
WebPMemoryWriter wrt;
- config.exact = 1;
+ if (p_lossless) {
+ config.lossless = 1;
+ config.exact = 1;
+ }
+ config.method = compression_method;
+ config.quality = p_quality;
pic.use_argb = 1;
pic.width = s.width;
pic.height = s.height;
diff --git a/modules/webp/webp_common.h b/modules/webp/webp_common.h
index 11bef40256..23b433ad79 100644
--- a/modules/webp/webp_common.h
+++ b/modules/webp/webp_common.h
@@ -37,6 +37,8 @@ namespace WebPCommon {
// Given an image, pack this data into a WebP file.
Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quality);
Vector<uint8_t> _webp_lossless_pack(const Ref<Image> &p_image);
+// Helper function for those above.
+Vector<uint8_t> _webp_packer(const Ref<Image> &p_image, float p_quality, bool p_lossless);
// Given a WebP file, unpack it into an image.
Ref<Image> _webp_unpack(const Vector<uint8_t> &p_buffer);
Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p_buffer_len);
diff --git a/modules/webxr/native/library_godot_webxr.js b/modules/webxr/native/library_godot_webxr.js
index c476a54c59..714768347c 100644
--- a/modules/webxr/native/library_godot_webxr.js
+++ b/modules/webxr/native/library_godot_webxr.js
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
const GodotWebXR = {
- $GodotWebXR__deps: ['$Browser', '$GL', '$GodotRuntime'],
+ $GodotWebXR__deps: ['$Browser', '$GL', '$GodotRuntime', '$runtimeKeepalivePush', '$runtimeKeepalivePop'],
$GodotWebXR: {
gl: null,
@@ -69,7 +69,9 @@ const GodotWebXR = {
// gets picked up automatically, however, in the Oculus Browser
// on the Quest, we need to pause and resume the main loop.
Browser.mainLoop.pause();
+ runtimeKeepalivePush(); // eslint-disable-line no-undef
window.setTimeout(function () {
+ runtimeKeepalivePop(); // eslint-disable-line no-undef
Browser.mainLoop.resume();
}, 0);
},
diff --git a/modules/zip/zip_packer.cpp b/modules/zip/zip_packer.cpp
index e62700f191..5566848087 100644
--- a/modules/zip/zip_packer.cpp
+++ b/modules/zip/zip_packer.cpp
@@ -46,7 +46,11 @@ Error ZIPPacker::open(String p_path, ZipAppend p_append) {
Error ZIPPacker::close() {
ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker cannot be closed because it is not open.");
- return zipClose(zf, NULL) == ZIP_OK ? OK : FAILED;
+ Error err = zipClose(zf, NULL) == ZIP_OK ? OK : FAILED;
+ if (err == OK) {
+ zf = NULL;
+ }
+ return err;
}
Error ZIPPacker::start_file(String p_path) {
@@ -79,11 +83,7 @@ Error ZIPPacker::write_file(Vector<uint8_t> p_data) {
Error ZIPPacker::close_file() {
ERR_FAIL_COND_V_MSG(fa.is_null(), FAILED, "ZIPPacker must be opened before use.");
- Error err = zipCloseFileInZip(zf) == ZIP_OK ? OK : FAILED;
- if (err == OK) {
- zf = NULL;
- }
- return err;
+ return zipCloseFileInZip(zf) == ZIP_OK ? OK : FAILED;
}
void ZIPPacker::_bind_methods() {
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 9919268375..c3fba625c6 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -802,7 +802,7 @@ void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset>
}
void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, bool p_debug) {
- print_verbose("Building temporary manifest..");
+ print_verbose("Building temporary manifest...");
String manifest_text =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
@@ -2491,7 +2491,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
// Clear the APK assets directory
if (da_res->dir_exists(APK_ASSETS_DIRECTORY)) {
- print_verbose("Clearing APK assets directory..");
+ print_verbose("Clearing APK assets directory...");
Ref<DirAccess> da_assets = DirAccess::open(APK_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(APK_ASSETS_DIRECTORY);
@@ -2499,7 +2499,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
// Clear the AAB assets directory
if (da_res->dir_exists(AAB_ASSETS_DIRECTORY)) {
- print_verbose("Clearing AAB assets directory..");
+ print_verbose("Clearing AAB assets directory...");
Ref<DirAccess> da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(AAB_ASSETS_DIRECTORY);
@@ -2615,10 +2615,10 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
}
if (use_custom_build) {
- print_verbose("Starting custom build..");
+ print_verbose("Starting custom build...");
//test that installed build version is alright
{
- print_verbose("Checking build version..");
+ print_verbose("Checking build version...");
Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::READ);
if (f.is_null()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
@@ -2651,7 +2651,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
_clear_assets_directory();
_remove_copied_libs();
if (!apk_expansion) {
- print_verbose("Exporting project files..");
+ print_verbose("Exporting project files...");
CustomExportData user_data;
user_data.assets_directory = assets_directory;
user_data.debug = p_debug;
@@ -2665,14 +2665,14 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
fa->store_string(JSON::stringify(user_data.libs, "\t"));
}
} else {
- print_verbose("Saving apk expansion file..");
+ print_verbose("Saving apk expansion file...");
err = save_apk_expansion_file(p_preset, p_debug, p_path);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!"));
return err;
}
}
- print_verbose("Storing command line flags..");
+ print_verbose("Storing command line flags...");
store_file_at_path(assets_directory + "/_cl_", command_line_flags);
print_verbose("Updating ANDROID_HOME environment to " + sdk_path);
@@ -2825,7 +2825,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return OK;
}
// This is the start of the Legacy build system
- print_verbose("Starting legacy build system..");
+ print_verbose("Starting legacy build system...");
if (p_debug) {
src_apk = p_preset->get("custom_template/debug");
} else {
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
index 489a81fc1a..46a334ef38 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
@@ -37,10 +37,12 @@ import android.os.Build
import android.os.Bundle
import android.os.Debug
import android.os.Environment
+import android.util.Log
import android.widget.Toast
import androidx.window.layout.WindowMetricsCalculator
import org.godotengine.godot.FullScreenGodotApp
import org.godotengine.godot.utils.PermissionsUtil
+import org.godotengine.godot.utils.ProcessPhoenix
import java.util.*
import kotlin.math.min
@@ -56,12 +58,17 @@ import kotlin.math.min
open class GodotEditor : FullScreenGodotApp() {
companion object {
+ private val TAG = GodotEditor::class.java.simpleName
+
private const val WAIT_FOR_DEBUGGER = false
private const val COMMAND_LINE_PARAMS = "command_line_params"
private const val EDITOR_ARG = "--editor"
+ private const val EDITOR_ARG_SHORT = "-e"
+
private const val PROJECT_MANAGER_ARG = "--project-manager"
+ private const val PROJECT_MANAGER_ARG_SHORT = "-p"
}
private val commandLineParams = ArrayList<String>()
@@ -105,13 +112,13 @@ open class GodotEditor : FullScreenGodotApp() {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && (isInMultiWindowMode || isLargeScreen)
for (arg in args) {
- if (EDITOR_ARG == arg) {
+ if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) {
targetClass = GodotEditor::class.java
launchAdjacent = false
break
}
- if (PROJECT_MANAGER_ARG == arg) {
+ if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) {
targetClass = GodotProjectManager::class.java
launchAdjacent = false
break
@@ -125,7 +132,13 @@ open class GodotEditor : FullScreenGodotApp() {
if (launchAdjacent) {
newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT)
}
- startActivity(newInstance)
+ if (targetClass == javaClass) {
+ Log.d(TAG, "Restarting $targetClass")
+ ProcessPhoenix.triggerRebirth(this, newInstance)
+ } else {
+ Log.d(TAG, "Starting $targetClass")
+ startActivity(newInstance)
+ }
}
// Get the screen's density scale
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index 92e5e59496..a002a37ab9 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -299,7 +299,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
plugin.onRegisterPluginWithGodotNative();
}
- setKeepScreenOn("True".equals(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
+ setKeepScreenOn(Boolean.parseBoolean(GodotLib.getGlobal("display/window/energy_saving/keep_screen_on")));
});
// Include the returned non-null views in the Godot view hierarchy.
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index b5cb9d341d..c2c25601d7 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -71,6 +71,39 @@ static Vector3 gravity;
static Vector3 magnetometer;
static Vector3 gyroscope;
+static void _terminate(JNIEnv *env, bool p_restart = false) {
+ step.set(-1); // Ensure no further steps are attempted and no further events are sent
+
+ // lets cleanup
+ if (java_class_wrapper) {
+ memdelete(java_class_wrapper);
+ }
+ if (input_handler) {
+ delete input_handler;
+ }
+ // Whether restarting is handled by 'Main::cleanup()'
+ bool restart_on_cleanup = false;
+ if (os_android) {
+ restart_on_cleanup = os_android->is_restart_on_exit_set();
+ os_android->main_loop_end();
+ Main::cleanup();
+ delete os_android;
+ }
+ if (godot_io_java) {
+ delete godot_io_java;
+ }
+ if (godot_java) {
+ if (!restart_on_cleanup) {
+ if (p_restart) {
+ godot_java->restart(env);
+ } else {
+ godot_java->force_quit(env);
+ }
+ }
+ delete godot_java;
+ }
+}
+
extern "C" {
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height) {
@@ -104,23 +137,7 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz) {
- // lets cleanup
- if (java_class_wrapper) {
- memdelete(java_class_wrapper);
- }
- if (godot_io_java) {
- delete godot_io_java;
- }
- if (godot_java) {
- delete godot_java;
- }
- if (input_handler) {
- delete input_handler;
- }
- if (os_android) {
- os_android->main_loop_end();
- delete os_android;
- }
+ _terminate(env, false);
}
JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) {
@@ -196,9 +213,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en
}
} else {
// Rendering context recreated because it was lost; restart app to let it reload everything
- step.set(-1); // Ensure no further steps are attempted and no further events are sent
- os_android->main_loop_end();
- godot_java->restart(env);
+ _terminate(env, true);
}
}
}
@@ -249,7 +264,7 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env,
bool should_swap_buffers = false;
if (os_android->main_loop_iterate(&should_swap_buffers)) {
- godot_java->force_quit(env);
+ _terminate(env, false);
}
return should_swap_buffers;
diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp
index 498977ad49..5a7123b833 100644
--- a/platform/android/plugin/godot_plugin_jni.cpp
+++ b/platform/android/plugin/godot_plugin_jni.cpp
@@ -135,7 +135,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
}
// Retrieve the current list of gdnative libraries.
- Array singletons = Array();
+ Array singletons;
if (ProjectSettings::get_singleton()->has_setting("gdnative/singletons")) {
singletons = GLOBAL_GET("gdnative/singletons");
}
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 8e4d91ac50..0dad4a2c1c 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -49,6 +49,46 @@ Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_ge
return archs;
}
+struct IconInfo {
+ const char *preset_key;
+ const char *idiom;
+ const char *export_name;
+ const char *actual_size_side;
+ const char *scale;
+ const char *unscaled_size;
+ const bool force_opaque;
+};
+
+static const IconInfo icon_infos[] = {
+ // Home screen on iPhone
+ { PNAME("icons/iphone_120x120"), "iphone", "Icon-120.png", "120", "2x", "60x60", false },
+ { PNAME("icons/iphone_120x120"), "iphone", "Icon-120.png", "120", "3x", "40x40", false },
+ { PNAME("icons/iphone_180x180"), "iphone", "Icon-180.png", "180", "3x", "60x60", false },
+
+ // Home screen on iPad
+ { PNAME("icons/ipad_76x76"), "ipad", "Icon-76.png", "76", "1x", "76x76", false },
+ { PNAME("icons/ipad_152x152"), "ipad", "Icon-152.png", "152", "2x", "76x76", false },
+ { PNAME("icons/ipad_167x167"), "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false },
+
+ // App Store
+ { PNAME("icons/app_store_1024x1024"), "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024", true },
+
+ // Spotlight
+ { PNAME("icons/spotlight_40x40"), "ipad", "Icon-40.png", "40", "1x", "40x40", false },
+ { PNAME("icons/spotlight_80x80"), "iphone", "Icon-80.png", "80", "2x", "40x40", false },
+ { PNAME("icons/spotlight_80x80"), "ipad", "Icon-80.png", "80", "2x", "40x40", false },
+
+ // Settings
+ { PNAME("icons/settings_58x58"), "iphone", "Icon-58.png", "58", "2x", "29x29", false },
+ { PNAME("icons/settings_58x58"), "ipad", "Icon-58.png", "58", "2x", "29x29", false },
+ { PNAME("icons/settings_87x87"), "iphone", "Icon-87.png", "87", "3x", "29x29", false },
+
+ // Notification
+ { PNAME("icons/notification_40x40"), "iphone", "Icon-40.png", "40", "2x", "20x20", false },
+ { PNAME("icons/notification_40x40"), "ipad", "Icon-40.png", "40", "2x", "20x20", false },
+ { PNAME("icons/notification_60x60"), "iphone", "Icon-60.png", "60", "3x", "20x20", false }
+};
+
struct LoadingScreenInfo {
const char *preset_key;
const char *export_name;
@@ -97,6 +137,9 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/launch_screens_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
+
Vector<PluginConfigIOS> found_plugins = get_plugins();
for (int i = 0; i < found_plugins.size(); i++) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("plugins"), found_plugins[i].name)), false));
@@ -139,18 +182,13 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone/iPod Touch with Retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPhone with Retina HD display
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_152x152", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad with Retina display
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/ipad_167x167", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Home screen on iPad Pro
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // App Store
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), "")); // Spotlight on devices with Retina display
-
+ HashSet<String> used_names;
+ for (uint64_t i = 0; i < sizeof(icon_infos) / sizeof(icon_infos[0]); ++i) {
+ if (!used_names.has(icon_infos[i].preset_key)) {
+ used_names.insert(icon_infos[i].preset_key);
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, icon_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), ""));
+ }
+ }
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "storyboard/use_launch_screen_storyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "storyboard/image_scale_mode", PROPERTY_HINT_ENUM, "Same as Logo,Center,Scale to Fit,Scale to Fill,Scale"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "storyboard/custom_image@2x", PROPERTY_HINT_FILE, "*.png,*.jpg,*.jpeg"), ""));
@@ -531,36 +569,6 @@ void EditorExportPlatformIOS::_blend_and_rotate(Ref<Image> &p_dst, Ref<Image> &p
}
}
-struct IconInfo {
- const char *preset_key;
- const char *idiom;
- const char *export_name;
- const char *actual_size_side;
- const char *scale;
- const char *unscaled_size;
- const bool force_opaque;
-};
-
-static const IconInfo icon_infos[] = {
- // Home screen on iPhone
- { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60", false },
- { "icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40", false },
- { "icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60", false },
-
- // Home screen on iPad
- { "icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76", false },
- { "icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76", false },
- { "icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false },
-
- // App Store
- { "icons/app_store_1024x1024", "ios-marketing", "Icon-1024.png", "1024", "1x", "1024x1024", true },
-
- // Spotlight
- { "icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40", false },
- { "icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40", false },
- { "icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40", false }
-};
-
Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) {
String json_description = "{\"images\":[";
String sizes;
@@ -568,6 +576,8 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
Ref<DirAccess> da = DirAccess::open(p_iconset_dir);
ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
+ Color boot_bg_color = GLOBAL_GET("application/boot_splash/bg_color");
+
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
IconInfo info = icon_infos[i];
int side_size = String(info.actual_size_side).to_int();
@@ -580,13 +590,17 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
return ERR_UNCONFIGURED;
+ } else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ Ref<Image> new_img = Image::create_empty(side_size, side_size, false, Image::FORMAT_RGBA8);
+ new_img->fill(boot_bg_color);
+ _blend_and_rotate(new_img, img, false);
+ err = new_img->save_png(p_iconset_dir + info.export_name);
+ } else {
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ err = img->save_png(p_iconset_dir + info.export_name);
}
- if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
- return ERR_UNCONFIGURED;
- }
- img->resize(side_size, side_size);
- err = img->save_png(p_iconset_dir + info.export_name);
if (err) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Failed to export icon (%s): '%s'.", info.preset_key, icon_path));
return err;
@@ -598,14 +612,16 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
return ERR_UNCONFIGURED;
- }
- if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
- return ERR_UNCONFIGURED;
- }
- if (img->get_width() != side_size || img->get_height() != side_size) {
+ } else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s) must be opaque.", info.preset_key));
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ Ref<Image> new_img = Image::create_empty(side_size, side_size, false, Image::FORMAT_RGBA8);
+ new_img->fill(boot_bg_color);
+ _blend_and_rotate(new_img, img, false);
+ err = new_img->save_png(p_iconset_dir + info.export_name);
+ } else if (img->get_width() != side_size || img->get_height() != side_size) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Export Icons"), vformat("Icon (%s): '%s' has incorrect size %s and was automatically resized to %s.", info.preset_key, icon_path, img->get_size(), Vector2i(side_size, side_size)));
- img->resize(side_size, side_size);
+ img->resize(side_size, side_size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
err = img->save_png(p_iconset_dir + info.export_name);
} else {
err = da->copy(icon_path, p_iconset_dir + info.export_name);
@@ -735,9 +751,9 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
float aspect_ratio = (float)img->get_width() / (float)img->get_height();
if (boot_logo_scale) {
if (info.height * aspect_ratio <= info.width) {
- img->resize(info.height * aspect_ratio, info.height);
+ img->resize(info.height * aspect_ratio, info.height, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
} else {
- img->resize(info.width, info.width / aspect_ratio);
+ img->resize(info.width, info.width / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
}
}
Ref<Image> new_img = Image::create_empty(info.width, info.height, false, Image::FORMAT_RGBA8);
@@ -771,17 +787,17 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
if (info.rotate) {
if (boot_logo_scale) {
if (info.width * aspect_ratio <= info.height) {
- img_bs->resize(info.width * aspect_ratio, info.width);
+ img_bs->resize(info.width * aspect_ratio, info.width, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
} else {
- img_bs->resize(info.height, info.height / aspect_ratio);
+ img_bs->resize(info.height, info.height / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
}
}
} else {
if (boot_logo_scale) {
if (info.height * aspect_ratio <= info.width) {
- img_bs->resize(info.height * aspect_ratio, info.height);
+ img_bs->resize(info.height * aspect_ratio, info.height, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
} else {
- img_bs->resize(info.width, info.width / aspect_ratio);
+ img_bs->resize(info.width, info.width / aspect_ratio, (Image::Interpolation)(p_preset->get("application/launch_screens_interpolation").operator int()));
}
}
}
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index ac69f3806b..004bcb8674 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -356,7 +356,6 @@ def configure(env: "Environment"):
if env["opengl3"]:
env.Append(CPPDEFINES=["GLES3_ENABLED"])
- env.ParseConfig("pkg-config gl --cflags --libs")
env.Append(LIBS=["pthread"])
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 22c5f063c3..e14e4fb52d 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -128,6 +128,8 @@ void OS_LinuxBSD::initialize() {
crash_handler.initialize();
OS_Unix::initialize_core();
+
+ system_dir_desktop_cache = get_system_dir(SYSTEM_DIR_DESKTOP);
}
void OS_LinuxBSD::initialize_joypads() {
@@ -632,6 +634,8 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold,
ERR_FAIL_V_MSG(String(), "Unable to load fontconfig, system font support is disabled.");
}
+ bool allow_substitutes = (p_font_name.to_lower() == "sans-serif") || (p_font_name.to_lower() == "serif") || (p_font_name.to_lower() == "monospace") || (p_font_name.to_lower() == "cursive") || (p_font_name.to_lower() == "fantasy");
+
String ret;
FcConfig *config = FcInitLoadConfigAndFonts();
@@ -653,6 +657,19 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold,
FcResult result;
FcPattern *match = FcFontMatch(0, pattern, &result);
if (match) {
+ if (!allow_substitutes) {
+ char *family_name = nullptr;
+ if (FcPatternGetString(match, FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
+ if (family_name && String::utf8(family_name).to_lower() != p_font_name.to_lower()) {
+ FcPatternDestroy(match);
+ FcPatternDestroy(pattern);
+ FcObjectSetDestroy(object_set);
+ FcConfigDestroy(config);
+
+ return String();
+ }
+ }
+ }
char *file_name = nullptr;
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
if (file_name) {
@@ -719,6 +736,10 @@ String OS_LinuxBSD::get_cache_path() const {
}
String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
+ if (p_dir == SYSTEM_DIR_DESKTOP && !system_dir_desktop_cache.is_empty()) {
+ return system_dir_desktop_cache;
+ }
+
String xdgparam;
switch (p_dir) {
@@ -727,31 +748,24 @@ String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const
} break;
case SYSTEM_DIR_DCIM: {
xdgparam = "PICTURES";
-
} break;
case SYSTEM_DIR_DOCUMENTS: {
xdgparam = "DOCUMENTS";
-
} break;
case SYSTEM_DIR_DOWNLOADS: {
xdgparam = "DOWNLOAD";
-
} break;
case SYSTEM_DIR_MOVIES: {
xdgparam = "VIDEOS";
-
} break;
case SYSTEM_DIR_MUSIC: {
xdgparam = "MUSIC";
-
} break;
case SYSTEM_DIR_PICTURES: {
xdgparam = "PICTURES";
-
} break;
case SYSTEM_DIR_RINGTONES: {
xdgparam = "MUSIC";
-
} break;
}
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index aea04c1363..aa7af92aa1 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -72,6 +72,8 @@ class OS_LinuxBSD : public OS_Unix {
Vector<String> lspci_device_filter(Vector<String> vendor_device_id_mapping, String class_suffix, String check_column, String whitelist) const;
Vector<String> lspci_get_device_value(Vector<String> vendor_device_id_mapping, String check_column, String blacklist) const;
+ String system_dir_desktop_cache;
+
protected:
virtual void initialize() override;
virtual void finalize() override;
diff --git a/platform/linuxbsd/platform_config.h b/platform/linuxbsd/platform_config.h
index 3c05c67444..79e15e2512 100644
--- a/platform/linuxbsd/platform_config.h
+++ b/platform/linuxbsd/platform_config.h
@@ -44,4 +44,4 @@
#endif
#endif
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub
index 974ad98fb9..30c6080355 100644
--- a/platform/linuxbsd/x11/SCsub
+++ b/platform/linuxbsd/x11/SCsub
@@ -11,7 +11,7 @@ if env["vulkan"]:
source_files.append("vulkan_context_x11.cpp")
if env["opengl3"]:
- source_files.append(["gl_manager_x11.cpp", "detect_prime_x11.cpp"])
+ source_files.append(["gl_manager_x11.cpp", "detect_prime_x11.cpp", "#thirdparty/glad/glx.c"])
objects = []
diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index 78a10fa2b0..ed046432d8 100644
--- a/platform/linuxbsd/x11/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -38,8 +38,9 @@
#include <stdlib.h>
-#include <GL/gl.h>
-#include <GL/glx.h>
+#include "thirdparty/glad/glad/gl.h"
+#include "thirdparty/glad/glad/glx.h"
+
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -77,8 +78,6 @@ void create_context() {
Window x11_window;
GLXContext glx_context;
- GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
-
static int visual_attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
@@ -101,7 +100,7 @@ void create_context() {
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
if (!fbc) {
- exit(1);
+ quick_exit(1);
}
vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
@@ -122,7 +121,7 @@ void create_context() {
x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, 10, 10, 0, vi->depth, InputOutput, vi->visual, valuemask, &swa);
if (!x11_window) {
- exit(1);
+ quick_exit(1);
}
glXMakeCurrent(x11_display, x11_window, glx_context);
@@ -189,8 +188,20 @@ int detect_prime() {
if (i) {
setenv("DRI_PRIME", "1", 1);
}
+
+ if (gladLoaderLoadGLX(NULL, 0) == 0) {
+ print_verbose("Unable to load GLX, GPU detection skipped.");
+ quick_exit(1);
+ }
+
create_context();
+ PFNGLGETSTRINGPROC glGetString = (PFNGLGETSTRINGPROC)glXGetProcAddressARB((GLubyte *)"glGetString");
+ if (!glGetString) {
+ print_verbose("Unable to get glGetString, GPU detection skipped.");
+ quick_exit(1);
+ }
+
const char *vendor = (const char *)glGetString(GL_VENDOR);
const char *renderer = (const char *)glGetString(GL_RENDERER);
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 2e60ad8f45..cf50748ac8 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -1319,7 +1319,10 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
- return (int64_t)gl_manager->get_glx_context(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_glx_context(p_window);
+ }
+ return 0;
}
#endif
default: {
@@ -4411,7 +4414,7 @@ void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo
#if defined(GLES3_ENABLED)
if (gl_manager) {
- gl_manager->set_use_vsync(p_vsync_mode == DisplayServer::VSYNC_ENABLED);
+ gl_manager->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
#endif
}
@@ -4672,6 +4675,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
if (gl_manager) {
Error err = gl_manager->window_create(id, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL window");
+ window_set_vsync_mode(p_vsync_mode, id);
}
#endif
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index 893a22e75e..bcefcf9695 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -37,9 +37,7 @@
#include <stdlib.h>
#include <unistd.h>
-#define GLX_GLXEXT_PROTOTYPES
-#include <GL/glx.h>
-#include <GL/glxext.h>
+#include "thirdparty/glad/glad/glx.h"
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
@@ -324,15 +322,14 @@ void GLManager_X11::swap_buffers() {
}
Error GLManager_X11::initialize() {
+ if (!gladLoaderLoadGLX(nullptr, 0)) {
+ return ERR_CANT_CREATE;
+ }
+
return OK;
}
void GLManager_X11::set_use_vsync(bool p_use) {
- static bool setup = false;
- static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
-
// force vsync in the editor for now, as a safety measure
bool is_editor = Engine::get_singleton()->is_editor_hint();
if (is_editor) {
@@ -345,25 +342,12 @@ void GLManager_X11::set_use_vsync(bool p_use) {
}
const GLDisplay &disp = get_current_display();
- if (!setup) {
- setup = true;
- String extensions = glXQueryExtensionsString(disp.x11_display, DefaultScreen(disp.x11_display));
- if (extensions.find("GLX_EXT_swap_control") != -1) {
- glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT");
- }
- if (extensions.find("GLX_MESA_swap_control") != -1) {
- glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA");
- }
- if (extensions.find("GLX_SGI_swap_control") != -1) {
- glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI");
- }
- }
int val = p_use ? 1 : 0;
- if (glXSwapIntervalMESA) {
+ if (GLAD_GLX_MESA_swap_control) {
glXSwapIntervalMESA(val);
- } else if (glXSwapIntervalSGI) {
+ } else if (GLAD_GLX_SGI_swap_control) {
glXSwapIntervalSGI(val);
- } else if (glXSwapIntervalEXT) {
+ } else if (GLAD_GLX_EXT_swap_control) {
GLXDrawable drawable = glXGetCurrentDrawable();
glXSwapIntervalEXT(disp.x11_display, drawable, val);
} else {
diff --git a/platform/macos/detect.py b/platform/macos/detect.py
index e73c5322ea..67e4b49b14 100644
--- a/platform/macos/detect.py
+++ b/platform/macos/detect.py
@@ -242,18 +242,24 @@ def configure(env: "Environment"):
if not env["use_volk"]:
env.Append(LINKFLAGS=["-lMoltenVK"])
mvk_found = False
+
+ mkv_list = [get_mvk_sdk_path(), "/opt/homebrew/lib", "/usr/local/homebrew/lib", "/opt/local/lib"]
if env["vulkan_sdk_path"] != "":
- mvk_path = os.path.join(
- os.path.expanduser(env["vulkan_sdk_path"]), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/"
+ mkv_list.insert(0, os.path.expanduser(env["vulkan_sdk_path"]))
+ mkv_list.insert(
+ 0,
+ os.path.join(
+ os.path.expanduser(env["vulkan_sdk_path"]), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/"
+ ),
)
- if os.path.isfile(os.path.join(mvk_path, "libMoltenVK.a")):
- mvk_found = True
- env.Append(LINKFLAGS=["-L" + mvk_path])
- if not mvk_found:
- mvk_path = get_mvk_sdk_path()
+
+ for mvk_path in mkv_list:
if mvk_path and os.path.isfile(os.path.join(mvk_path, "libMoltenVK.a")):
mvk_found = True
+ print("MoltenVK found at: " + mvk_path)
env.Append(LINKFLAGS=["-L" + mvk_path])
+ break
+
if not mvk_found:
print(
"MoltenVK SDK installation directory not found, use 'vulkan_sdk_path' SCons parameter to specify SDK path."
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 618da6b388..8e75b98302 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -106,6 +106,7 @@ public:
bool layered_window = false;
bool fullscreen = false;
+ bool exclusive_fullscreen = false;
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 8b596379a0..3557511c28 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -166,6 +166,7 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
Error err = gl_manager->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context");
}
+ window_set_vsync_mode(p_vsync_mode, window_id_counter);
#endif
[wd.window_view updateLayerDelegate];
id = window_id_counter++;
@@ -2584,7 +2585,13 @@ void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
}
[wd.window_object toggleFullScreen:nil];
+
+ if (old_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
+ [NSApp setPresentationOptions:NSApplicationPresentationDefault];
+ }
+
wd.fullscreen = false;
+ wd.exclusive_fullscreen = false;
} break;
case WINDOW_MODE_MAXIMIZED: {
if ([wd.window_object isZoomed]) {
@@ -2609,7 +2616,15 @@ void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) {
[wd.window_object setContentMinSize:NSMakeSize(0, 0)];
[wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[wd.window_object toggleFullScreen:nil];
+
wd.fullscreen = true;
+ if (p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
+ const NSUInteger presentationOptions = NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
+ [NSApp setPresentationOptions:presentationOptions];
+ wd.exclusive_fullscreen = true;
+ } else {
+ wd.exclusive_fullscreen = false;
+ }
} break;
case WINDOW_MODE_MAXIMIZED: {
if (![wd.window_object isZoomed]) {
@@ -2626,7 +2641,11 @@ DisplayServer::WindowMode DisplayServerMacOS::window_get_mode(WindowID p_window)
const WindowData &wd = windows[p_window];
if (wd.fullscreen) { // If fullscreen, it's not in another mode.
- return WINDOW_MODE_FULLSCREEN;
+ if (wd.exclusive_fullscreen) {
+ return WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
+ } else {
+ return WINDOW_MODE_FULLSCREEN;
+ }
}
if ([wd.window_object isZoomed] && !wd.resize_disabled) {
return WINDOW_MODE_MAXIMIZED;
@@ -2945,7 +2964,10 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W
}
#ifdef GLES3_ENABLED
case OPENGL_CONTEXT: {
- return (int64_t)gl_manager->get_context(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_context(p_window);
+ }
+ return 0;
}
#endif
default: {
@@ -2978,7 +3000,7 @@ void DisplayServerMacOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_
_THREAD_SAFE_METHOD_
#if defined(GLES3_ENABLED)
if (gl_manager) {
- gl_manager->set_use_vsync(p_vsync_mode);
+ gl_manager->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
#endif
#if defined(VULKAN_ENABLED)
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index de6016cb9b..ae8c802caf 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -116,7 +116,8 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.icns,*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_category", PROPERTY_HINT_ENUM, "Business,Developer-tools,Education,Entertainment,Finance,Games,Action-games,Adventure-games,Arcade-games,Board-games,Card-games,Casino-games,Dice-games,Educational-games,Family-games,Kids-games,Music-games,Puzzle-games,Racing-games,Role-playing-games,Simulation-games,Sports-games,Strategy-games,Trivia-games,Word-games,Graphics-design,Healthcare-fitness,Lifestyle,Medical,Music,News,Photography,Productivity,Reference,Social-networking,Sports,Travel,Utilities,Video,Weather"), "Games"));
@@ -268,7 +269,7 @@ void _rgba8_to_packbits_encode(int p_ch, int p_size, Vector<uint8_t> &p_source,
memcpy(&p_dest.write[ofs], result.ptr(), res_size);
}
-void EditorExportPlatformMacOS::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
+void EditorExportPlatformMacOS::_make_icon(const Ref<EditorExportPreset> &p_preset, const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
Ref<ImageTexture> it = memnew(ImageTexture);
Vector<uint8_t> data;
@@ -302,7 +303,7 @@ void EditorExportPlatformMacOS::_make_icon(const Ref<Image> &p_icon, Vector<uint
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
Ref<Image> copy = p_icon; // does this make sense? doesn't this just increase the reference count instead of making a copy? Do we even need a copy?
copy->convert(Image::FORMAT_RGBA8);
- copy->resize(icon_infos[i].size, icon_infos[i].size);
+ copy->resize(icon_infos[i].size, icon_infos[i].size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
if (icon_infos[i].is_png) {
// Encode PNG icon.
@@ -726,7 +727,7 @@ Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pre
String str;
int exitcode = 0;
- Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true);
+ Error err = OS::get_singleton()->execute("codesign", args, &str, &exitcode, true);
if (err != OK) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start codesign executable, make sure Xcode command line tools are installed."));
return err;
@@ -1268,11 +1269,9 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
icon->get_buffer(&data.write[0], icon->get_length());
}
} else {
- Ref<Image> icon;
- icon.instantiate();
- icon->load(iconpath);
- if (!icon->is_empty()) {
- _make_icon(icon, data);
+ Ref<Image> icon = Image::load_from_file(iconpath);
+ if (icon.is_valid() && !icon->is_empty()) {
+ _make_icon(p_preset, icon, data);
}
}
}
diff --git a/platform/macos/export/export_plugin.h b/platform/macos/export/export_plugin.h
index b6ad587caa..af7570c394 100644
--- a/platform/macos/export/export_plugin.h
+++ b/platform/macos/export/export_plugin.h
@@ -53,7 +53,7 @@ class EditorExportPlatformMacOS : public EditorExportPlatform {
Ref<ImageTexture> logo;
void _fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary);
- void _make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
+ void _make_icon(const Ref<EditorExportPreset> &p_preset, const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
Error _notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path);
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn = true);
diff --git a/platform/macos/godot_application_delegate.mm b/platform/macos/godot_application_delegate.mm
index bacdcc2bc4..f1168c685a 100644
--- a/platform/macos/godot_application_delegate.mm
+++ b/platform/macos/godot_application_delegate.mm
@@ -61,7 +61,9 @@
- (void)applicationDidFinishLaunching:(NSNotification *)notice {
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
- if (nsappname == nil || isatty(STDOUT_FILENO) || isatty(STDIN_FILENO) || isatty(STDERR_FILENO)) {
+ NSString *nsbundleid_env = [NSString stringWithUTF8String:getenv("__CFBundleIdentifier")];
+ NSString *nsbundleid = [[NSBundle mainBundle] bundleIdentifier];
+ if (nsappname == nil || isatty(STDOUT_FILENO) || isatty(STDIN_FILENO) || isatty(STDERR_FILENO) || ![nsbundleid isEqualToString:nsbundleid_env]) {
// If the executable is started from terminal or is not bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
[self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
}
diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm
index 279fd2a359..3bdbc8c5ec 100644
--- a/platform/macos/godot_window_delegate.mm
+++ b/platform/macos/godot_window_delegate.mm
@@ -147,7 +147,12 @@
}
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
+ if (wd.exclusive_fullscreen) {
+ [NSApp setPresentationOptions:NSApplicationPresentationDefault];
+ }
+
wd.fullscreen = false;
+ wd.exclusive_fullscreen = false;
[(GodotWindow *)wd.window_object setAnimDuration:-1.0f];
diff --git a/platform/macos/platform_config.h b/platform/macos/platform_config.h
index e114606b82..46c46b8803 100644
--- a/platform/macos/platform_config.h
+++ b/platform/macos/platform_config.h
@@ -30,5 +30,5 @@
#include <alloca.h>
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
#define PTHREAD_RENAME_SELF
diff --git a/platform/windows/console_wrapper_windows.cpp b/platform/windows/console_wrapper_windows.cpp
index 749f51e6e4..258176426b 100644
--- a/platform/windows/console_wrapper_windows.cpp
+++ b/platform/windows/console_wrapper_windows.cpp
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
}
}
- // Enable virtual termial sequences processing.
+ // Enable virtual terminal sequences processing.
HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD out_mode = ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(stdout_handle, out_mode);
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 2c8058fdc5..0b878feb7f 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -743,10 +743,16 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type,
}
#if defined(GLES3_ENABLED)
case WINDOW_VIEW: {
- return (int64_t)gl_manager->get_hdc(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_hdc(p_window);
+ }
+ return 0;
}
case OPENGL_CONTEXT: {
- return (int64_t)gl_manager->get_hglrc(p_window);
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_hglrc(p_window);
+ }
+ return 0;
}
#endif
default: {
@@ -1886,7 +1892,7 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
pos += sizeof(WORD);
f->seek(pos);
- icon_dir = (ICONDIR *)memrealloc(icon_dir, 3 * sizeof(WORD) + icon_dir->idCount * sizeof(ICONDIRENTRY));
+ icon_dir = (ICONDIR *)memrealloc(icon_dir, sizeof(ICONDIR) - sizeof(ICONDIRENTRY) + icon_dir->idCount * sizeof(ICONDIRENTRY));
f->get_buffer((uint8_t *)&icon_dir->idEntries[0], icon_dir->idCount * sizeof(ICONDIRENTRY));
int small_icon_index = -1; // Select 16x16 with largest color count.
@@ -2017,6 +2023,12 @@ void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsyn
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
}
#endif
+
+#if defined(GLES3_ENABLED)
+ if (gl_manager) {
+ gl_manager->set_use_vsync(p_window, p_vsync_mode != DisplayServer::VSYNC_DISABLED);
+ }
+#endif
}
DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const {
@@ -2026,6 +2038,13 @@ DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_
return context_vulkan->get_vsync_mode(p_window);
}
#endif
+
+#if defined(GLES3_ENABLED)
+ if (gl_manager) {
+ return gl_manager->is_using_vsync(p_window) ? DisplayServer::VSYNC_ENABLED : DisplayServer::VSYNC_DISABLED;
+ }
+#endif
+
return DisplayServer::VSYNC_ENABLED;
}
@@ -3595,6 +3614,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
windows.erase(id);
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create an OpenGL window.");
}
+ window_set_vsync_mode(p_vsync_mode, id);
}
#endif
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index d15380ac7a..bfd40e1c9c 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -32,6 +32,118 @@
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
+
+Error EditorExportPlatformWindows::_process_icon(const Ref<EditorExportPreset> &p_preset, const String &p_src_path, const String &p_dst_path) {
+ static const uint8_t icon_size[] = { 16, 32, 48, 64, 128, 0 /*256*/ };
+
+ struct IconData {
+ Vector<uint8_t> data;
+ uint8_t pal_colors = 0;
+ uint16_t planes = 0;
+ uint16_t bpp = 32;
+ };
+
+ HashMap<uint8_t, IconData> images;
+ Error err;
+
+ if (p_src_path.get_extension() == "ico") {
+ Ref<FileAccess> f = FileAccess::open(p_src_path, FileAccess::READ, &err);
+ if (err != OK) {
+ return err;
+ }
+
+ // Read ICONDIR.
+ f->get_16(); // Reserved.
+ uint16_t icon_type = f->get_16(); // Image type: 1 - ICO.
+ uint16_t icon_count = f->get_16(); // Number of images.
+ ERR_FAIL_COND_V(icon_type != 1, ERR_CANT_OPEN);
+
+ for (uint16_t i = 0; i < icon_count; i++) {
+ // Read ICONDIRENTRY.
+ uint16_t w = f->get_8(); // Width in pixels.
+ uint16_t h = f->get_8(); // Height in pixels.
+ uint8_t pal_colors = f->get_8(); // Number of colors in the palette (0 - no palette).
+ f->get_8(); // Reserved.
+ uint16_t planes = f->get_16(); // Number of color planes.
+ uint16_t bpp = f->get_16(); // Bits per pixel.
+ uint32_t img_size = f->get_32(); // Image data size in bytes.
+ uint32_t img_offset = f->get_32(); // Image data offset.
+ if (w != h) {
+ continue;
+ }
+
+ // Read image data.
+ uint64_t prev_offset = f->get_position();
+ images[w].pal_colors = pal_colors;
+ images[w].planes = planes;
+ images[w].bpp = bpp;
+ images[w].data.resize(img_size);
+ f->seek(img_offset);
+ f->get_buffer(images[w].data.ptrw(), img_size);
+ f->seek(prev_offset);
+ }
+ } else {
+ Ref<Image> src_image = Image::load_from_file(p_src_path);
+ ERR_FAIL_COND_V(src_image.is_null() || src_image->is_empty(), ERR_CANT_OPEN);
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ int size = (icon_size[i] == 0) ? 256 : icon_size[i];
+
+ Ref<Image> res_image = src_image->duplicate();
+ ERR_FAIL_COND_V(res_image.is_null() || res_image->is_empty(), ERR_CANT_OPEN);
+ res_image->resize(size, size, (Image::Interpolation)(p_preset->get("application/icon_interpolation").operator int()));
+ images[icon_size[i]].data = res_image->save_png_to_buffer();
+ }
+ }
+
+ uint16_t valid_icon_count = 0;
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ if (images.has(icon_size[i])) {
+ valid_icon_count++;
+ } else {
+ int size = (icon_size[i] == 0) ? 256 : icon_size[i];
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("Icon size \"%d\" is missing."), size));
+ }
+ }
+ ERR_FAIL_COND_V(valid_icon_count == 0, ERR_CANT_OPEN);
+
+ Ref<FileAccess> fw = FileAccess::open(p_dst_path, FileAccess::WRITE, &err);
+ if (err != OK) {
+ return err;
+ }
+
+ // Write ICONDIR.
+ fw->store_16(0); // Reserved.
+ fw->store_16(1); // Image type: 1 - ICO.
+ fw->store_16(valid_icon_count); // Number of images.
+
+ // Write ICONDIRENTRY.
+ uint32_t img_offset = 6 + 16 * valid_icon_count;
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ if (images.has(icon_size[i])) {
+ const IconData &di = images[icon_size[i]];
+ fw->store_8(icon_size[i]); // Width in pixels.
+ fw->store_8(icon_size[i]); // Height in pixels.
+ fw->store_8(di.pal_colors); // Number of colors in the palette (0 - no palette).
+ fw->store_8(0); // Reserved.
+ fw->store_16(di.planes); // Number of color planes.
+ fw->store_16(di.bpp); // Bits per pixel.
+ fw->store_32(di.data.size()); // Image data size in bytes.
+ fw->store_32(img_offset); // Image data offset.
+
+ img_offset += di.data.size();
+ }
+ }
+
+ // Write image data.
+ for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
+ if (images.has(icon_size[i])) {
+ const IconData &di = images[icon_size[i]];
+ fw->store_buffer(di.data.ptr(), di.data.size());
+ }
+ }
+ return OK;
+}
Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
if (p_preset->get("codesign/enable")) {
@@ -110,7 +222,9 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/modify_resources"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico,*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/console_wrapper_icon", PROPERTY_HINT_FILE, "*.ico.*.png,*.webp,*.svg"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), ""));
@@ -120,7 +234,7 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), ""));
}
-Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_set_icon) {
+Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_console_icon) {
String rcedit_path = EDITOR_GET("export/windows/rcedit");
if (rcedit_path != String() && !FileAccess::exists(rcedit_path)) {
@@ -147,6 +261,21 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
#endif
String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon"));
+ if (p_console_icon) {
+ String console_icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/console_wrapper_icon"));
+ if (!console_icon_path.is_empty() && FileAccess::exists(console_icon_path)) {
+ icon_path = console_icon_path;
+ }
+ }
+
+ String tmp_icon_path = EditorPaths::get_singleton()->get_cache_dir().path_join("_rcedit.ico");
+ if (!icon_path.is_empty()) {
+ if (_process_icon(p_preset, icon_path, tmp_icon_path) != OK) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("Invalid icon file \"%s\"."), icon_path));
+ icon_path = String();
+ }
+ }
+
String file_verion = p_preset->get("application/file_version");
String product_version = p_preset->get("application/product_version");
String company_name = p_preset->get("application/company_name");
@@ -158,9 +287,9 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
List<String> args;
args.push_back(p_path);
- if (!icon_path.is_empty() && p_set_icon) {
+ if (!icon_path.is_empty()) {
args.push_back("--set-icon");
- args.push_back(icon_path);
+ args.push_back(tmp_icon_path);
}
if (!file_verion.is_empty()) {
args.push_back("--set-file-version");
@@ -204,6 +333,11 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
String str;
Error err = OS::get_singleton()->execute(rcedit_path, args, &str, nullptr, true);
+
+ if (FileAccess::exists(tmp_icon_path)) {
+ DirAccess::remove_file_or_error(tmp_icon_path);
+ }
+
if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) {
add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable. Configure rcedit path in the Editor Settings (Export > Windows > rcedit), or disable \"Application > Modify Resources\" in the export preset."));
return err;
diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h
index ec3b60aa76..a9e6d51b9d 100644
--- a/platform/windows/export/export_plugin.h
+++ b/platform/windows/export/export_plugin.h
@@ -38,7 +38,8 @@
#include "platform/windows/logo.gen.h"
class EditorExportPlatformWindows : public EditorExportPlatformPC {
- Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_set_icon);
+ Error _process_icon(const Ref<EditorExportPreset> &p_preset, const String &p_src_path, const String &p_dst_path);
+ Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_console_icon);
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
public:
diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp
index 900bca8258..5b39c56ea3 100644
--- a/platform/windows/gl_manager_windows.cpp
+++ b/platform/windows/gl_manager_windows.cpp
@@ -185,6 +185,10 @@ Error GLManager_Windows::_create_context(GLWindow &win, GLDisplay &gl_display) {
return ERR_CANT_CREATE;
}
+ if (!wglSwapIntervalEXT) {
+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
+ }
+
return OK;
}
@@ -293,50 +297,30 @@ void GLManager_Windows::swap_buffers() {
}
Error GLManager_Windows::initialize() {
- wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
- wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
- //glWrapperInit(wrapper_get_proc_address);
-
return OK;
}
-void GLManager_Windows::set_use_vsync(bool p_use) {
- /*
- static bool setup = false;
- static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = nullptr;
- static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
-
- if (!setup) {
- setup = true;
- String extensions = glXQueryExtensionsString(x11_display, DefaultScreen(x11_display));
- if (extensions.find("GLX_EXT_swap_control") != -1) {
- glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT");
- }
- if (extensions.find("GLX_MESA_swap_control") != -1) {
- glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA");
- }
- if (extensions.find("GLX_SGI_swap_control") != -1) {
- glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI");
- }
+void GLManager_Windows::set_use_vsync(DisplayServer::WindowID p_window_id, bool p_use) {
+ GLWindow &win = get_window(p_window_id);
+ GLWindow *current = _current_window;
+
+ if (&win != _current_window) {
+ window_make_current(p_window_id);
}
- int val = p_use ? 1 : 0;
- if (glXSwapIntervalMESA) {
- glXSwapIntervalMESA(val);
- } else if (glXSwapIntervalSGI) {
- glXSwapIntervalSGI(val);
- } else if (glXSwapIntervalEXT) {
- GLXDrawable drawable = glXGetCurrentDrawable();
- glXSwapIntervalEXT(x11_display, drawable, val);
- } else {
- return;
+
+ if (wglSwapIntervalEXT) {
+ win.use_vsync = p_use;
+ wglSwapIntervalEXT(p_use ? 1 : 0);
+ }
+
+ if (current != _current_window) {
+ _current_window = current;
+ make_current();
}
- use_vsync = p_use;
- */
}
-bool GLManager_Windows::is_using_vsync() const {
- return use_vsync;
+bool GLManager_Windows::is_using_vsync(DisplayServer::WindowID p_window_id) const {
+ return get_window(p_window_id).use_vsync;
}
HDC GLManager_Windows::get_hdc(DisplayServer::WindowID p_window_id) {
@@ -354,7 +338,6 @@ GLManager_Windows::GLManager_Windows(ContextType p_context_type) {
direct_render = false;
glx_minor = glx_major = 0;
- use_vsync = false;
_current_window = nullptr;
}
diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h
index c6d5f9f855..94f3ce9860 100644
--- a/platform/windows/gl_manager_windows.h
+++ b/platform/windows/gl_manager_windows.h
@@ -54,6 +54,7 @@ private:
struct GLWindow {
int width = 0;
int height = 0;
+ bool use_vsync = false;
// windows specific
HDC hDC;
@@ -72,8 +73,8 @@ private:
GLWindow *_current_window = nullptr;
- PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
- PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
+ PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr;
+ PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr;
// funcs
void _internal_set_current_window(GLWindow *p_win);
@@ -86,7 +87,6 @@ private:
bool direct_render;
int glx_minor, glx_major;
- bool use_vsync;
ContextType context_type;
private:
@@ -110,8 +110,8 @@ public:
Error initialize();
- void set_use_vsync(bool p_use);
- bool is_using_vsync() const;
+ void set_use_vsync(DisplayServer::WindowID p_window_id, bool p_use);
+ bool is_using_vsync(DisplayServer::WindowID p_window_id) const;
HDC get_hdc(DisplayServer::WindowID p_window_id);
HGLRC get_hglrc(DisplayServer::WindowID p_window_id);
diff --git a/platform/windows/godot_res_wrap.rc b/platform/windows/godot_res_wrap.rc
index ed93bb1ec3..9877ff6075 100644
--- a/platform/windows/godot_res_wrap.rc
+++ b/platform/windows/godot_res_wrap.rc
@@ -4,6 +4,8 @@
#define _MKSTR(m_x) _STR(m_x)
#endif
+GODOT_ICON ICON platform/windows/godot.ico
+
1 VERSIONINFO
FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 08897bb190..d8548eb545 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -849,7 +849,19 @@ String OS_Windows::get_system_font_path(const String &p_font_name, bool p_bold,
if (FAILED(hr)) {
continue;
}
- return String::utf16((const char16_t *)&file_path[0]);
+ String fpath = String::utf16((const char16_t *)&file_path[0]);
+
+ WIN32_FIND_DATAW d;
+ HANDLE fnd = FindFirstFileW((LPCWSTR)&file_path[0], &d);
+ if (fnd != INVALID_HANDLE_VALUE) {
+ String fname = String::utf16((const char16_t *)d.cFileName);
+ if (!fname.is_empty()) {
+ fpath = fpath.get_base_dir().path_join(fname);
+ }
+ FindClose(fnd);
+ }
+
+ return fpath;
}
return String();
}
diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h
index 8e80f8cacb..7f0042d76f 100644
--- a/platform/windows/platform_config.h
+++ b/platform/windows/platform_config.h
@@ -30,4 +30,4 @@
#include <malloc.h>
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h
index 616d7fdb60..5bc9083488 100644
--- a/scene/2d/audio_stream_player_2d.h
+++ b/scene/2d/audio_stream_player_2d.h
@@ -82,7 +82,7 @@ private:
float attenuation = 1.0;
float panning_strength = 1.0f;
- float cached_global_panning_strength = 1.0f;
+ float cached_global_panning_strength = 0.5f;
protected:
void _validate_property(PropertyInfo &p_property) const;
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index e18f2bd1a1..c8f5d7f5a6 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -299,10 +299,6 @@ bool GPUParticles2D::get_interpolate() const {
PackedStringArray GPUParticles2D::get_configuration_warnings() const {
PackedStringArray warnings = Node2D::get_configuration_warnings();
- if (RenderingServer::get_singleton()->is_low_end()) {
- warnings.push_back(RTR("GPU-based particles are not supported by the OpenGL video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles2D\" option for this purpose."));
- }
-
if (process_material.is_null()) {
warnings.push_back(RTR("A material to process the particles is not assigned, so no behavior is imprinted."));
} else {
diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h
index 7fba174357..94555e0bb0 100644
--- a/scene/2d/gpu_particles_2d.h
+++ b/scene/2d/gpu_particles_2d.h
@@ -64,7 +64,7 @@ private:
#endif
Ref<Material> process_material;
- DrawOrder draw_order;
+ DrawOrder draw_order = DRAW_ORDER_LIFETIME;
Ref<Texture2D> texture;
diff --git a/scene/2d/joint_2d.cpp b/scene/2d/joint_2d.cpp
index 6000508f36..8de4c281f4 100644
--- a/scene/2d/joint_2d.cpp
+++ b/scene/2d/joint_2d.cpp
@@ -133,7 +133,13 @@ void Joint2D::set_node_a(const NodePath &p_node_a) {
}
a = p_node_a;
- _update_joint();
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // When in editor, the setter may be called as a result of node rename.
+ // It happens before the node actually changes its name, which triggers false warning.
+ callable_mp(this, &Joint2D::_update_joint).call_deferred();
+ } else {
+ _update_joint();
+ }
}
NodePath Joint2D::get_node_a() const {
@@ -150,7 +156,11 @@ void Joint2D::set_node_b(const NodePath &p_node_b) {
}
b = p_node_b;
- _update_joint();
+ if (Engine::get_singleton()->is_editor_hint()) {
+ callable_mp(this, &Joint2D::_update_joint).call_deferred();
+ } else {
+ _update_joint();
+ }
}
NodePath Joint2D::get_node_b() const {
diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h
index 2a5092216d..9d36f80dd6 100644
--- a/scene/2d/navigation_link_2d.h
+++ b/scene/2d/navigation_link_2d.h
@@ -37,11 +37,11 @@ class NavigationLink2D : public Node2D {
GDCLASS(NavigationLink2D, Node2D);
bool enabled = true;
- RID link = RID();
+ RID link;
bool bidirectional = true;
uint32_t navigation_layers = 1;
- Vector2 end_location = Vector2();
- Vector2 start_location = Vector2();
+ Vector2 end_location;
+ Vector2 start_location;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 0f3e6c7529..7f46ec4c1e 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -34,8 +34,8 @@
#include "scene/scene_string_names.h"
void PhysicsBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions);
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with);
@@ -54,8 +54,8 @@ PhysicsBody2D::~PhysicsBody2D() {
}
}
-Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p_test_only, real_t p_margin, bool p_recovery_as_collision) {
- PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
+Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision) {
+ PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
parameters.recovery_as_collision = p_recovery_as_collision;
PhysicsServer2D::MotionResult result;
@@ -128,7 +128,7 @@ bool PhysicsBody2D::move_and_collide(const PhysicsServer2D::MotionParameters &p_
return colliding;
}
-bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision, real_t p_margin, bool p_recovery_as_collision) {
+bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision, real_t p_margin, bool p_recovery_as_collision) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer2D::MotionResult *r = nullptr;
@@ -140,7 +140,7 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distan
r = &temp_result;
}
- PhysicsServer2D::MotionParameters parameters(p_from, p_distance, p_margin);
+ PhysicsServer2D::MotionParameters parameters(p_from, p_motion, p_margin);
parameters.recovery_as_collision = p_recovery_as_collision;
return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
@@ -162,14 +162,14 @@ TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
void PhysicsBody2D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
- ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody2D type.");
+ ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
PhysicsServer2D::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid());
}
void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
- ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody2D type.");
+ ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two nodes that inherit from PhysicsBody2D.");
PhysicsServer2D::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid());
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 932ec1de16..504e1dc333 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -47,11 +47,11 @@ protected:
Ref<KinematicCollision2D> motion_cache;
- Ref<KinematicCollision2D> _move(const Vector2 &p_distance, bool p_test_only = false, real_t p_margin = 0.08, bool p_recovery_as_collision = false);
+ Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_test_only = false, real_t p_margin = 0.08, bool p_recovery_as_collision = false);
public:
bool move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
- bool test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08, bool p_recovery_as_collision = false);
+ bool test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08, bool p_recovery_as_collision = false);
TypedArray<PhysicsBody2D> get_collision_exceptions();
void add_collision_exception_with(Node *p_node); //must be physicsbody
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 5e77902977..2c825e8f7b 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -114,7 +114,7 @@ void Polygon2D::_notification(int p_what) {
ObjectID new_skeleton_id;
- if (skeleton_node) {
+ if (skeleton_node && !invert && bone_weights.size()) {
RS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton());
new_skeleton_id = skeleton_node->get_instance_id();
} else {
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 02d8e20ce8..62787d4488 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -213,7 +213,7 @@ void Bone2D::_notification(int p_what) {
}
// Undo scaling
- Transform2D editor_gizmo_trans = Transform2D();
+ Transform2D editor_gizmo_trans;
editor_gizmo_trans.set_scale(Vector2(1, 1) / get_global_scale());
RenderingServer::get_singleton()->canvas_item_set_transform(editor_gizmo_rid, editor_gizmo_trans);
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 7f3e241871..eaf100631e 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -115,7 +115,7 @@ public:
class TerrainConstraint {
private:
const TileMap *tile_map;
- Vector2i base_cell_coords = Vector2i();
+ Vector2i base_cell_coords;
int bit = -1;
int terrain = -1;
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index 913cc9fc00..806b250ba7 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -117,7 +117,7 @@ private:
float _get_attenuation_db(float p_distance) const;
float panning_strength = 1.0f;
- float cached_global_panning_strength = 1.0f;
+ float cached_global_panning_strength = 0.5f;
protected:
void _validate_property(PropertyInfo &p_property) const;
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index d8524a7392..9cf10dbef1 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -375,7 +375,7 @@ void BoneAttachment3D::on_bone_pose_update(int p_bone_index) {
}
}
#ifdef TOOLS_ENABLED
-void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Ref<BoneMap> p_bone_map) {
+void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map) {
const Skeleton3D *parent = nullptr;
if (use_external_skeleton) {
if (external_skeleton_node_cache.is_valid()) {
@@ -385,7 +385,7 @@ void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skelet
parent = Object::cast_to<Skeleton3D>(get_parent());
}
if (parent && parent == p_skeleton) {
- StringName bn = p_bone_map->find_profile_bone_name(bone_name);
+ StringName bn = p_rename_map[bone_name];
if (bn) {
set_bone_name(bn);
}
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index 2db6ba6268..81338b30e9 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -72,7 +72,7 @@ protected:
static void _bind_methods();
#ifdef TOOLS_ENABLED
- virtual void _notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Ref<BoneMap> p_bone_map);
+ virtual void _notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map);
#endif // TOOLS_ENABLED
public:
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 7de685b469..5ac8535bb6 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -867,7 +867,7 @@ void CPUParticles3D::_particles_process(double p_delta) {
real_t ring_random_angle = Math::randf() * Math_TAU;
real_t ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;
Vector3 axis = emission_ring_axis.normalized();
- Vector3 ortho_axis = Vector3();
+ Vector3 ortho_axis;
if (axis == Vector3(1.0, 0.0, 0.0)) {
ortho_axis = Vector3(0.0, 1.0, 0.0).cross(axis);
} else {
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 9d04202c2d..17dfe2610e 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -272,10 +272,6 @@ bool GPUParticles3D::get_interpolate() const {
PackedStringArray GPUParticles3D::get_configuration_warnings() const {
PackedStringArray warnings = GeometryInstance3D::get_configuration_warnings();
- if (RenderingServer::get_singleton()->is_low_end()) {
- warnings.push_back(RTR("GPU-based particles are not supported by the OpenGL video driver.\nUse the CPUParticles3D node instead. You can use the \"Convert to CPUParticles3D\" option for this purpose."));
- }
-
bool meshes_found = false;
bool anim_material_found = false;
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index 835d71862a..d1768436e5 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -82,7 +82,7 @@ private:
Ref<Material> process_material;
- DrawOrder draw_order;
+ DrawOrder draw_order = DRAW_ORDER_INDEX;
Vector<Ref<Mesh>> draw_passes;
Ref<Skin> skin;
diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h
index 1fc03546fa..46bc6318b8 100644
--- a/scene/3d/navigation_link_3d.h
+++ b/scene/3d/navigation_link_3d.h
@@ -37,11 +37,11 @@ class NavigationLink3D : public Node3D {
GDCLASS(NavigationLink3D, Node3D);
bool enabled = true;
- RID link = RID();
+ RID link;
bool bidirectional = true;
uint32_t navigation_layers = 1;
- Vector3 end_location = Vector3();
- Vector3 start_location = Vector3();
+ Vector3 end_location;
+ Vector3 start_location;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index ab4cba86fb..02ab297d8e 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -182,125 +182,31 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
if (bl == 0.0) {
return;
}
- real_t bi = c->get_bake_interval();
- real_t o_next = progress + bi;
- real_t o_prev = progress - bi;
-
- if (loop) {
- o_next = Math::fposmod(o_next, bl);
- o_prev = Math::fposmod(o_prev, bl);
- } else if (rotation_mode == ROTATION_ORIENTED) {
- if (o_next >= bl) {
- o_next = bl;
- }
- if (o_prev <= 0) {
- o_prev = 0;
- }
- }
-
- Vector3 pos = c->sample_baked(progress, cubic);
- Transform3D t = get_transform();
- // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
- // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
-
- if (rotation_mode == ROTATION_ORIENTED) {
- Vector3 forward = c->sample_baked(o_next, cubic) - pos;
-
- // Try with the previous position
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = pos - c->sample_baked(o_prev, cubic);
- }
-
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = Vector3(0, 0, 1);
- } else {
- forward.normalize();
- }
-
- Vector3 up = c->sample_baked_up_vector(progress, true);
- if (o_next < progress) {
- Vector3 up1 = c->sample_baked_up_vector(o_next, true);
- Vector3 axis = up.cross(up1);
-
- if (axis.length_squared() < CMP_EPSILON2) {
- axis = forward;
- } else {
- axis.normalize();
- }
-
- up.rotate(axis, up.angle_to(up1) * 0.5f);
- }
-
- Vector3 scale = t.basis.get_scale();
- Vector3 sideways = up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
-
- t.basis.set_columns(sideways, up, forward);
- t.basis.scale_local(scale);
-
- t.origin = pos + sideways * h_offset + up * v_offset;
- } else if (rotation_mode != ROTATION_NONE) {
- // perform parallel transport
- //
- // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
- // for a discussion about why not Frenet frame.
+ Transform3D t;
+ if (rotation_mode == ROTATION_NONE) {
+ Vector3 pos = c->sample_baked(progress, cubic);
t.origin = pos;
- if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
- real_t sample_distance = bi * 0.01;
- Vector3 t_prev_pos_a = c->sample_baked(prev_offset - sample_distance, cubic);
- Vector3 t_prev_pos_b = c->sample_baked(prev_offset + sample_distance, cubic);
- Vector3 t_cur_pos_a = c->sample_baked(progress - sample_distance, cubic);
- Vector3 t_cur_pos_b = c->sample_baked(progress + sample_distance, cubic);
- Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized();
- Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized();
-
- Vector3 axis = t_prev.cross(t_cur);
- real_t dot = t_prev.dot(t_cur);
- real_t angle = Math::acos(CLAMP(dot, -1, 1));
-
- if (likely(!Math::is_zero_approx(angle))) {
- if (rotation_mode == ROTATION_Y) {
- // assuming we're referring to global Y-axis. is this correct?
- axis.x = 0;
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
+ } else {
+ t = c->sample_baked_with_rotation(progress, cubic, false);
+ Vector3 forward = t.basis.get_column(2); // Retain tangent for applying tilt
+ t = PathFollow3D::correct_posture(t, rotation_mode);
- if (likely(!Math::is_zero_approx(axis.length()))) {
- t.rotate_basis(axis.normalized(), angle);
- }
- }
+ // Apply tilt *after* correct_posture
+ if (tilt_enabled) {
+ const real_t tilt = c->sample_baked_tilt(progress);
- // do the additional tilting
- real_t tilt_angle = c->sample_baked_tilt(progress);
- Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
-
- if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
- if (rotation_mode == ROTATION_Y) {
- tilt_axis.x = 0;
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
-
- if (likely(!Math::is_zero_approx(tilt_axis.length()))) {
- t.rotate_basis(tilt_axis.normalized(), tilt_angle);
- }
- }
+ const Basis twist(forward, tilt);
+ t.basis = twist * t.basis;
}
-
- t.translate_local(Vector3(h_offset, v_offset, 0));
- } else {
- t.origin = pos + Vector3(h_offset, v_offset, 0);
}
+ Vector3 scale = get_transform().basis.get_scale();
+
+ t.translate_local(Vector3(h_offset, v_offset, 0));
+ t.basis.scale_local(scale);
+
set_transform(t);
}
@@ -358,6 +264,38 @@ PackedStringArray PathFollow3D::get_configuration_warnings() const {
return warnings;
}
+Transform3D PathFollow3D::correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode) {
+ Transform3D t = p_transform;
+
+ // Modify frame according to rotation mode.
+ if (p_rotation_mode == PathFollow3D::ROTATION_NONE) {
+ // Clear rotation.
+ t.basis = Basis();
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_ORIENTED) {
+ // Y-axis always straight up.
+ Vector3 up(0.0, 1.0, 0.0);
+ Vector3 forward = t.basis.get_column(2);
+
+ t.basis = Basis::looking_at(-forward, up);
+ } else {
+ // Lock some euler axes.
+ Vector3 euler = t.basis.get_euler_normalized(EulerOrder::YXZ);
+ if (p_rotation_mode == PathFollow3D::ROTATION_Y) {
+ // Only Y-axis allowed.
+ euler[0] = 0;
+ euler[2] = 0;
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_XY) {
+ // XY allowed.
+ euler[2] = 0;
+ }
+
+ Basis locked = Basis::from_euler(euler, EulerOrder::YXZ);
+ t.basis = locked;
+ }
+
+ return t;
+}
+
void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow3D::set_progress);
ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow3D::get_progress);
@@ -380,6 +318,11 @@ void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop);
+ ClassDB::bind_method(D_METHOD("set_tilt_enabled", "enabled"), &PathFollow3D::set_tilt_enabled);
+ ClassDB::bind_method(D_METHOD("is_tilt_enabled"), &PathFollow3D::is_tilt_enabled);
+
+ ClassDB::bind_static_method("PathFollow3D", D_METHOD("correct_posture", "transform", "rotation_mode"), &PathFollow3D::correct_posture);
+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_less,or_greater,suffix:m"), "set_progress", "get_progress");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_less,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
@@ -387,6 +330,7 @@ void PathFollow3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tilt_enabled"), "set_tilt_enabled", "is_tilt_enabled");
BIND_ENUM_CONSTANT(ROTATION_NONE);
BIND_ENUM_CONSTANT(ROTATION_Y);
@@ -397,7 +341,6 @@ void PathFollow3D::_bind_methods() {
void PathFollow3D::set_progress(real_t p_progress) {
ERR_FAIL_COND(!isfinite(p_progress));
- prev_offset = progress;
progress = p_progress;
if (path) {
@@ -409,8 +352,6 @@ void PathFollow3D::set_progress(real_t p_progress) {
if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) {
progress = path_length;
}
- } else {
- progress = CLAMP(progress, 0, path_length);
}
}
@@ -476,3 +417,11 @@ void PathFollow3D::set_loop(bool p_loop) {
bool PathFollow3D::has_loop() const {
return loop;
}
+
+void PathFollow3D::set_tilt_enabled(bool p_enable) {
+ tilt_enabled = p_enable;
+}
+
+bool PathFollow3D::is_tilt_enabled() const {
+ return tilt_enabled;
+}
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index b161b12185..9d5f694247 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -72,14 +72,16 @@ public:
ROTATION_ORIENTED
};
+ static Transform3D correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode);
+
private:
Path3D *path = nullptr;
- real_t prev_offset = 0.0; // Offset during the last _update_transform.
real_t progress = 0.0;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
bool cubic = true;
bool loop = true;
+ bool tilt_enabled = true;
RotationMode rotation_mode = ROTATION_XYZ;
void _update_transform(bool p_update_xyz_rot = true);
@@ -106,6 +108,9 @@ public:
void set_loop(bool p_loop);
bool has_loop() const;
+ void set_tilt_enabled(bool p_enable);
+ bool is_tilt_enabled() const;
+
void set_rotation_mode(RotationMode p_rotation_mode);
RotationMode get_rotation_mode() const;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index d9fa37ce74..d29f337fc8 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -34,8 +34,8 @@
#include "scene/scene_string_names.h"
void PhysicsBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicsBody3D::set_axis_lock);
ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicsBody3D::get_axis_lock);
@@ -80,19 +80,19 @@ TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
void PhysicsBody3D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid());
}
void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
}
-Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_distance, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
+Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
parameters.max_collisions = p_max_collisions;
parameters.recovery_as_collision = p_recovery_as_collision;
@@ -169,7 +169,7 @@ bool PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters &p_
return colliding;
}
-bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer3D::MotionResult *r = nullptr;
@@ -181,7 +181,7 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distan
r = &temp_result;
}
- PhysicsServer3D::MotionParameters parameters(p_from, p_distance, p_margin);
+ PhysicsServer3D::MotionParameters parameters(p_from, p_motion, p_margin);
parameters.recovery_as_collision = p_recovery_as_collision;
return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 4b874b91d9..36b7ce774c 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -50,11 +50,11 @@ protected:
uint16_t locked_axis = 0;
- Ref<KinematicCollision3D> _move(const Vector3 &p_distance, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+ Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
public:
bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
- bool test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+ bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index a1f962c690..b205c2cde0 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -541,7 +541,7 @@ void Skeleton3D::set_bone_name(int p_bone, const String &p_name) {
for (int i = 0; i < bone_size; i++) {
if (i != p_bone) {
- ERR_FAIL_COND(bones[i].name == p_name);
+ ERR_FAIL_COND_MSG(bones[i].name == p_name, "Skeleton3D: '" + get_name() + "', bone name: '" + p_name + "' is already exist.");
}
}
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 83e3369423..1814baa9e9 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -607,14 +607,14 @@ TypedArray<PhysicsBody3D> SoftBody3D::get_collision_exceptions() {
void SoftBody3D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid());
}
void SoftBody3D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid());
}
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 59930a3fbb..85bc4e9814 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -1442,11 +1442,11 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) {
}
void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) {
- Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), CONNECT_REFERENCE_COUNTED);
+ Ref<Animation>(p_anim)->connect("changed", callable_mp(this, &AnimationPlayer::_animation_changed), CONNECT_REFERENCE_COUNTED);
}
void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) {
- Ref<Animation>(p_anim)->disconnect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed));
+ Ref<Animation>(p_anim)->disconnect("changed", callable_mp(this, &AnimationPlayer::_animation_changed));
}
void AnimationPlayer::rename_animation_library(const StringName &p_name, const StringName &p_new_name) {
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index b4bdda9ecb..599a759b08 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -39,87 +39,10 @@
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
-Array SceneDebugger::RPCProfilerFrame::serialize() {
- Array arr;
- arr.push_back(infos.size() * 4);
- for (int i = 0; i < infos.size(); ++i) {
- arr.push_back(uint64_t(infos[i].node));
- arr.push_back(infos[i].node_path);
- arr.push_back(infos[i].incoming_rpc);
- arr.push_back(infos[i].outgoing_rpc);
- }
- return arr;
-}
-
-bool SceneDebugger::RPCProfilerFrame::deserialize(const Array &p_arr) {
- ERR_FAIL_COND_V(p_arr.size() < 1, false);
- uint32_t size = p_arr[0];
- ERR_FAIL_COND_V(size % 4, false);
- ERR_FAIL_COND_V((uint32_t)p_arr.size() != size + 1, false);
- infos.resize(size / 4);
- int idx = 1;
- for (uint32_t i = 0; i < size / 4; ++i) {
- infos.write[i].node = uint64_t(p_arr[idx]);
- infos.write[i].node_path = p_arr[idx + 1];
- infos.write[i].incoming_rpc = p_arr[idx + 2];
- infos.write[i].outgoing_rpc = p_arr[idx + 3];
- }
- return true;
-}
-
-class SceneDebugger::RPCProfiler : public EngineProfiler {
- HashMap<ObjectID, RPCNodeInfo> rpc_node_data;
- uint64_t last_profile_time = 0;
-
- void init_node(const ObjectID p_node) {
- if (rpc_node_data.has(p_node)) {
- return;
- }
- rpc_node_data.insert(p_node, RPCNodeInfo());
- rpc_node_data[p_node].node = p_node;
- rpc_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path();
- rpc_node_data[p_node].incoming_rpc = 0;
- rpc_node_data[p_node].outgoing_rpc = 0;
- }
-
-public:
- void toggle(bool p_enable, const Array &p_opts) {
- rpc_node_data.clear();
- }
-
- void add(const Array &p_data) {
- ERR_FAIL_COND(p_data.size() < 2);
- const ObjectID id = p_data[0];
- const String what = p_data[1];
- init_node(id);
- RPCNodeInfo &info = rpc_node_data[id];
- if (what == "rpc_in") {
- info.incoming_rpc++;
- } else if (what == "rpc_out") {
- info.outgoing_rpc++;
- }
- }
-
- void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
- uint64_t pt = OS::get_singleton()->get_ticks_msec();
- if (pt - last_profile_time > 100) {
- last_profile_time = pt;
- RPCProfilerFrame frame;
- for (const KeyValue<ObjectID, RPCNodeInfo> &E : rpc_node_data) {
- frame.infos.push_back(E.value);
- }
- rpc_node_data.clear();
- EngineDebugger::get_singleton()->send_message("multiplayer:rpc", frame.serialize());
- }
- }
-};
-
SceneDebugger *SceneDebugger::singleton = nullptr;
SceneDebugger::SceneDebugger() {
singleton = this;
- rpc_profiler.instantiate();
- rpc_profiler->bind("rpc");
#ifdef DEBUG_ENABLED
LiveEditor::singleton = memnew(LiveEditor);
EngineDebugger::register_message_capture("scene", EngineDebugger::Capture(nullptr, SceneDebugger::parse_message));
@@ -264,7 +187,7 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
live_editor->_create_node_func(p_args[0], p_args[1], p_args[2]);
- } else if (p_msg == "live_instance_node") {
+ } else if (p_msg == "live_instantiate_node") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
live_editor->_instance_node_func(p_args[0], p_args[1], p_args[2]);
diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h
index fe35446aae..0428bfcc2e 100644
--- a/scene/debugger/scene_debugger.h
+++ b/scene/debugger/scene_debugger.h
@@ -42,28 +42,9 @@ class Node;
class SceneDebugger {
public:
- // RPC profiler
- struct RPCNodeInfo {
- ObjectID node;
- String node_path;
- int incoming_rpc = 0;
- int outgoing_rpc = 0;
- };
-
- struct RPCProfilerFrame {
- Vector<RPCNodeInfo> infos;
-
- Array serialize();
- bool deserialize(const Array &p_arr);
- };
-
private:
- class RPCProfiler;
-
static SceneDebugger *singleton;
- Ref<RPCProfiler> rpc_profiler;
-
SceneDebugger();
public:
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index c2b82e01d1..0e7bc5c306 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -231,7 +231,7 @@ void Button::_notification(int p_what) {
_icon = icon;
}
- Rect2 icon_region = Rect2();
+ Rect2 icon_region;
HorizontalAlignment icon_align_rtl_checked = icon_alignment;
HorizontalAlignment align_rtl_checked = alignment;
// Swap icon and text alignment sides if right-to-left layout is set.
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index ea310f5a12..9e0dc049e5 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -1425,7 +1425,10 @@ bool CodeEdit::is_line_numbers_zero_padded() const {
}
void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) {
- String fc = TS->format_number(String::num(p_line + 1).lpad(line_number_digits, line_number_padding));
+ String fc = String::num(p_line + 1).lpad(line_number_digits, line_number_padding);
+ if (is_localizing_numeral_system()) {
+ fc = TS->format_number(fc);
+ }
Ref<TextLine> tl;
tl.instantiate();
tl->add_string(fc, font, font_size);
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 724e5bcaf6..66c790b0d9 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -959,7 +959,7 @@ void ColorPicker::_sample_draw() {
// Draw both old and new colors for easier comparison (only if spawned from a ColorPickerButton).
const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
- if (display_old_color && old_color.a < 1.0) {
+ if (old_color.a < 1.0) {
sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_old, true);
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index c5cb7157e8..4e76f72921 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2773,6 +2773,20 @@ bool Control::is_layout_rtl() const {
return data.is_rtl;
}
+void Control::set_localize_numeral_system(bool p_enable) {
+ if (p_enable == data.localize_numeral_system) {
+ return;
+ }
+
+ data.localize_numeral_system = p_enable;
+
+ notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
+}
+
+bool Control::is_localizing_numeral_system() const {
+ return data.localize_numeral_system;
+}
+
void Control::set_auto_translate(bool p_enable) {
if (p_enable == data.auto_translate) {
return;
@@ -3154,6 +3168,9 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_translate", "enable"), &Control::set_auto_translate);
ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating);
+ ClassDB::bind_method(D_METHOD("set_localize_numeral_system", "enable"), &Control::set_localize_numeral_system);
+ ClassDB::bind_method(D_METHOD("is_localizing_numeral_system"), &Control::is_localizing_numeral_system);
+
ADD_GROUP("Layout", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "custom_minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size");
@@ -3198,8 +3215,9 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_v_size_flags", "get_v_size_flags");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio");
- ADD_GROUP("Auto Translate", "");
+ ADD_GROUP("Localization", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "localize_numeral_system"), "set_localize_numeral_system", "is_localizing_numeral_system");
ADD_GROUP("Tooltip", "tooltip_");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip_text", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip_text", "get_tooltip_text");
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 72e870930d..3e9bb48a4a 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -249,6 +249,7 @@ private:
bool is_rtl = false;
bool auto_translate = true;
+ bool localize_numeral_system = true;
// Extra properties.
@@ -595,6 +596,9 @@ public:
LayoutDirection get_layout_direction() const;
virtual bool is_layout_rtl() const;
+ void set_localize_numeral_system(bool p_enable);
+ bool is_localizing_numeral_system() const;
+
void set_auto_translate(bool p_enable);
bool is_auto_translating() const;
_FORCE_INLINE_ String atr(const String p_string) const {
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index cade65108c..11a3803b35 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -632,8 +632,11 @@ void FileDialog::update_file_list() {
files.pop_front();
}
- if (tree->get_root() && tree->get_root()->get_first_child() && tree->get_selected() == nullptr) {
- tree->get_root()->get_first_child()->select(0);
+ if (mode != FILE_MODE_SAVE_FILE) {
+ // Select the first file from list if nothing is selected.
+ if (tree->get_root() && tree->get_root()->get_first_child() && tree->get_selected() == nullptr) {
+ tree->get_root()->get_first_child()->select(0);
+ }
}
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index fb5ab9f923..8a77c39487 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -960,17 +960,30 @@ void LineEdit::_notification(int p_what) {
if (ime_text.length() == 0) {
// Normal caret.
CaretInfo caret = TS->shaped_text_get_carets(text_rid, caret_column);
-
- if (caret.l_caret == Rect2() && caret.t_caret == Rect2()) {
+ if (using_placeholder || (caret.l_caret == Rect2() && caret.t_caret == Rect2())) {
// No carets, add one at the start.
int h = theme_cache.font->get_height(theme_cache.font_size);
int y = style->get_offset().y + (y_area - h) / 2;
- if (rtl) {
- caret.l_dir = TextServer::DIRECTION_RTL;
- caret.l_caret = Rect2(Vector2(ofs_max, y), Size2(caret_width, h));
- } else {
- caret.l_dir = TextServer::DIRECTION_LTR;
- caret.l_caret = Rect2(Vector2(x_ofs, y), Size2(caret_width, h));
+ caret.l_dir = (rtl) ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR;
+ switch (alignment) {
+ case HORIZONTAL_ALIGNMENT_FILL:
+ case HORIZONTAL_ALIGNMENT_LEFT: {
+ if (rtl) {
+ caret.l_caret = Rect2(Vector2(ofs_max, y), Size2(caret_width, h));
+ } else {
+ caret.l_caret = Rect2(Vector2(style->get_offset().x, y), Size2(caret_width, h));
+ }
+ } break;
+ case HORIZONTAL_ALIGNMENT_CENTER: {
+ caret.l_caret = Rect2(Vector2(size.x / 2, y), Size2(caret_width, h));
+ } break;
+ case HORIZONTAL_ALIGNMENT_RIGHT: {
+ if (rtl) {
+ caret.l_caret = Rect2(Vector2(style->get_offset().x, y), Size2(caret_width, h));
+ } else {
+ caret.l_caret = Rect2(Vector2(ofs_max, y), Size2(caret_width, h));
+ }
+ } break;
}
RenderingServer::get_singleton()->canvas_item_add_rect(ci, caret.l_caret, caret_color);
} else {
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 0940b4c07b..6d0bbdd6af 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -491,9 +491,9 @@ void OptionButton::show_popup() {
return;
}
- Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
- popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
- popup->set_size(Size2(size.width, 0));
+ Size2 button_size = get_global_transform_with_canvas().get_scale() * get_size();
+ popup->set_position(get_screen_position() + Size2(0, button_size.height));
+ popup->set_size(Size2i(button_size.width, 0));
// If not triggered by the mouse, start the popup with the checked item (or the first enabled one) focused.
if (current != NONE_SELECTED && !popup->is_item_disabled(current)) {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 82f56a56c9..ab74979777 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -558,7 +558,7 @@ void PopupMenu::_draw_items() {
check_ofs += theme_cache.h_separation;
}
- Point2 ofs = Point2();
+ Point2 ofs;
// Loop through all items and draw each.
for (int i = 0; i < items.size(); i++) {
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index 8369eaa227..50bcfa6a0c 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -103,7 +103,12 @@ void ProgressBar::_notification(int p_what) {
}
if (show_percentage) {
- String txt = TS->format_number(itos(int(get_as_ratio() * 100))) + TS->percent_sign();
+ String txt = itos(int(get_as_ratio() * 100));
+ if (is_localizing_numeral_system()) {
+ txt = TS->format_number(txt) + TS->percent_sign();
+ } else {
+ txt += String("%");
+ }
TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
Vector2 text_pos = (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 7f487175dc..889610e071 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -752,7 +752,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
prefix = _prefix;
break;
} else if (list_items[i]->list_type == LIST_NUMBERS) {
- segment = TS->format_number(itos(list_index[i]), _find_language(l.from));
+ segment = itos(list_index[i]);
+ if (is_localizing_numeral_system()) {
+ segment = TS->format_number(segment, _find_language(l.from));
+ }
} else if (list_items[i]->list_type == LIST_LETTERS) {
segment = _letters(list_index[i], list_items[i]->capitalize);
} else if (list_items[i]->list_type == LIST_ROMAN) {
@@ -2686,6 +2689,7 @@ bool RichTextLabel::_validate_line_caches() {
int ctrl_height = get_size().height;
// Update fonts.
+ float old_scroll = vscroll->get_value();
if (main->first_invalid_font_line.load() != (int)main->lines.size()) {
for (int i = main->first_invalid_font_line.load(); i < (int)main->lines.size(); i++) {
_update_line_font(main, i, theme_cache.normal_font, theme_cache.normal_font_size);
@@ -2695,6 +2699,7 @@ bool RichTextLabel::_validate_line_caches() {
}
if (main->first_resized_line.load() == (int)main->lines.size()) {
+ vscroll->set_value(old_scroll);
return true;
}
@@ -2733,6 +2738,8 @@ bool RichTextLabel::_validate_line_caches() {
vscroll->set_page(text_rect.size.height);
if (scroll_follow && scroll_following) {
vscroll->set_value(total_height);
+ } else {
+ vscroll->set_value(old_scroll);
}
updating_scroll = false;
@@ -4057,7 +4064,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
Color color = theme_cache.default_color;
Color outline_color = theme_cache.font_outline_color;
int outline_size = theme_cache.outline_size;
- Rect2 dropcap_margins = Rect2();
+ Rect2 dropcap_margins;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
@@ -5716,11 +5723,11 @@ Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_id
}
Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressions) {
- Dictionary d = Dictionary();
+ Dictionary d;
for (int i = 0; i < p_expressions.size(); i++) {
String expression = p_expressions[i];
- Array a = Array();
+ Array a;
Vector<String> parts = expression.split("=", true);
String key = parts[0];
if (parts.size() != 2) {
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index 13ca62d7ff..d62acd52af 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -72,7 +72,7 @@ class ScrollBar : public Range {
NodePath drag_node_path;
bool drag_node_enabled = true;
- Vector2 drag_node_speed = Vector2();
+ Vector2 drag_node_speed;
Vector2 drag_node_accum;
Vector2 drag_node_from;
Vector2 last_drag_node_accum;
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index c4000120c8..e15b3b7bd4 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -40,7 +40,10 @@ Size2 SpinBox::get_minimum_size() const {
}
void SpinBox::_value_changed(double p_value) {
- String value = TS->format_number(String::num(get_value(), Math::range_step_decimals(get_step())));
+ String value = String::num(get_value(), Math::range_step_decimals(get_step()));
+ if (is_localizing_numeral_system()) {
+ value = TS->format_number(value);
+ }
if (!line_edit->has_focus()) {
if (!prefix.is_empty()) {
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 2ca1d6239e..9830b41389 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -71,7 +71,7 @@ void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) {
Vector2i in_parent_pos = get_transform().xform(mm->get_position());
if (!sc->vertical && is_layout_rtl()) {
- sc->split_offset = drag_ofs - ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from);
+ sc->split_offset = drag_ofs - (in_parent_pos.x - drag_from);
} else {
sc->split_offset = drag_ofs + ((sc->vertical ? in_parent_pos.y : in_parent_pos.x) - drag_from);
}
@@ -194,7 +194,6 @@ void SplitContainer::_compute_middle_sep(bool p_clamp) {
// Clamp the split_offset if requested.
if (p_clamp) {
split_offset -= wished_middle_sep - middle_sep;
- p_clamp = false;
}
}
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index cf6681f809..f87829cf71 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -385,9 +385,6 @@ void TabBar::_notification(int p_what) {
if (tabs[i].disabled) {
sb = theme_cache.tab_disabled_style;
col = theme_cache.font_disabled_color;
- } else if (i == current) {
- sb = theme_cache.tab_selected_style;
- col = theme_cache.font_selected_color;
} else {
sb = theme_cache.tab_unselected_style;
col = theme_cache.font_unselected_color;
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index d9ab1c2c55..ccdf56c1d7 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -64,7 +64,7 @@ Size2 TextureButton::get_minimum_size() const {
bool TextureButton::has_point(const Point2 &p_point) const {
if (click_mask.is_valid()) {
Point2 point = p_point;
- Rect2 rect = Rect2();
+ Rect2 rect;
Size2 mask_size = click_mask->get_size();
if (!_position_rect.has_area()) {
@@ -250,11 +250,11 @@ void TextureButton::_notification(int p_what) {
}
void TextureButton::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_normal_texture", "texture"), &TextureButton::set_normal_texture);
- ClassDB::bind_method(D_METHOD("set_pressed_texture", "texture"), &TextureButton::set_pressed_texture);
- ClassDB::bind_method(D_METHOD("set_hover_texture", "texture"), &TextureButton::set_hover_texture);
- ClassDB::bind_method(D_METHOD("set_disabled_texture", "texture"), &TextureButton::set_disabled_texture);
- ClassDB::bind_method(D_METHOD("set_focused_texture", "texture"), &TextureButton::set_focused_texture);
+ ClassDB::bind_method(D_METHOD("set_texture_normal", "texture"), &TextureButton::set_texture_normal);
+ ClassDB::bind_method(D_METHOD("set_texture_pressed", "texture"), &TextureButton::set_texture_pressed);
+ ClassDB::bind_method(D_METHOD("set_texture_hover", "texture"), &TextureButton::set_texture_hover);
+ ClassDB::bind_method(D_METHOD("set_texture_disabled", "texture"), &TextureButton::set_texture_disabled);
+ ClassDB::bind_method(D_METHOD("set_texture_focused", "texture"), &TextureButton::set_texture_focused);
ClassDB::bind_method(D_METHOD("set_click_mask", "mask"), &TextureButton::set_click_mask);
ClassDB::bind_method(D_METHOD("set_ignore_texture_size", "ignore"), &TextureButton::set_ignore_texture_size);
ClassDB::bind_method(D_METHOD("set_stretch_mode", "mode"), &TextureButton::set_stretch_mode);
@@ -263,21 +263,21 @@ void TextureButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flip_v", "enable"), &TextureButton::set_flip_v);
ClassDB::bind_method(D_METHOD("is_flipped_v"), &TextureButton::is_flipped_v);
- ClassDB::bind_method(D_METHOD("get_normal_texture"), &TextureButton::get_normal_texture);
- ClassDB::bind_method(D_METHOD("get_pressed_texture"), &TextureButton::get_pressed_texture);
- ClassDB::bind_method(D_METHOD("get_hover_texture"), &TextureButton::get_hover_texture);
- ClassDB::bind_method(D_METHOD("get_disabled_texture"), &TextureButton::get_disabled_texture);
- ClassDB::bind_method(D_METHOD("get_focused_texture"), &TextureButton::get_focused_texture);
+ ClassDB::bind_method(D_METHOD("get_texture_normal"), &TextureButton::get_texture_normal);
+ ClassDB::bind_method(D_METHOD("get_texture_pressed"), &TextureButton::get_texture_pressed);
+ ClassDB::bind_method(D_METHOD("get_texture_hover"), &TextureButton::get_texture_hover);
+ ClassDB::bind_method(D_METHOD("get_texture_disabled"), &TextureButton::get_texture_disabled);
+ ClassDB::bind_method(D_METHOD("get_texture_focused"), &TextureButton::get_texture_focused);
ClassDB::bind_method(D_METHOD("get_click_mask"), &TextureButton::get_click_mask);
ClassDB::bind_method(D_METHOD("get_ignore_texture_size"), &TextureButton::get_ignore_texture_size);
ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureButton::get_stretch_mode);
ADD_GROUP("Textures", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_normal_texture", "get_normal_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_pressed", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_pressed_texture", "get_pressed_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_hover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_hover_texture", "get_hover_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_disabled", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_disabled_texture", "get_disabled_texture");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_focused_texture", "get_focused_texture");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_normal", "get_texture_normal");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_pressed", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_pressed", "get_texture_pressed");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_hover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_hover", "get_texture_hover");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_disabled", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_disabled", "get_texture_disabled");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture_focused", "get_texture_focused");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_texture_size", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_ignore_texture_size", "get_ignore_texture_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
@@ -293,7 +293,7 @@ void TextureButton::_bind_methods() {
BIND_ENUM_CONSTANT(STRETCH_KEEP_ASPECT_COVERED);
}
-void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
+void TextureButton::set_texture_normal(const Ref<Texture2D> &p_normal) {
if (normal == p_normal) {
return;
}
@@ -303,7 +303,7 @@ void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
update_minimum_size();
}
-void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
+void TextureButton::set_texture_pressed(const Ref<Texture2D> &p_pressed) {
if (pressed == p_pressed) {
return;
}
@@ -313,7 +313,7 @@ void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
update_minimum_size();
}
-void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
+void TextureButton::set_texture_hover(const Ref<Texture2D> &p_hover) {
if (hover == p_hover) {
return;
}
@@ -323,7 +323,7 @@ void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
update_minimum_size();
}
-void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
+void TextureButton::set_texture_disabled(const Ref<Texture2D> &p_disabled) {
if (disabled == p_disabled) {
return;
}
@@ -341,19 +341,19 @@ void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
update_minimum_size();
}
-Ref<Texture2D> TextureButton::get_normal_texture() const {
+Ref<Texture2D> TextureButton::get_texture_normal() const {
return normal;
}
-Ref<Texture2D> TextureButton::get_pressed_texture() const {
+Ref<Texture2D> TextureButton::get_texture_pressed() const {
return pressed;
}
-Ref<Texture2D> TextureButton::get_hover_texture() const {
+Ref<Texture2D> TextureButton::get_texture_hover() const {
return hover;
}
-Ref<Texture2D> TextureButton::get_disabled_texture() const {
+Ref<Texture2D> TextureButton::get_texture_disabled() const {
return disabled;
}
@@ -361,11 +361,11 @@ Ref<BitMap> TextureButton::get_click_mask() const {
return click_mask;
}
-Ref<Texture2D> TextureButton::get_focused_texture() const {
+Ref<Texture2D> TextureButton::get_texture_focused() const {
return focused;
};
-void TextureButton::set_focused_texture(const Ref<Texture2D> &p_focused) {
+void TextureButton::set_texture_focused(const Ref<Texture2D> &p_focused) {
focused = p_focused;
};
diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h
index 9f6f7c1515..4b6d5b5bec 100644
--- a/scene/gui/texture_button.h
+++ b/scene/gui/texture_button.h
@@ -71,18 +71,18 @@ protected:
static void _bind_methods();
public:
- void set_normal_texture(const Ref<Texture2D> &p_normal);
- void set_pressed_texture(const Ref<Texture2D> &p_pressed);
- void set_hover_texture(const Ref<Texture2D> &p_hover);
- void set_disabled_texture(const Ref<Texture2D> &p_disabled);
- void set_focused_texture(const Ref<Texture2D> &p_focused);
+ void set_texture_normal(const Ref<Texture2D> &p_normal);
+ void set_texture_pressed(const Ref<Texture2D> &p_pressed);
+ void set_texture_hover(const Ref<Texture2D> &p_hover);
+ void set_texture_disabled(const Ref<Texture2D> &p_disabled);
+ void set_texture_focused(const Ref<Texture2D> &p_focused);
void set_click_mask(const Ref<BitMap> &p_click_mask);
- Ref<Texture2D> get_normal_texture() const;
- Ref<Texture2D> get_pressed_texture() const;
- Ref<Texture2D> get_hover_texture() const;
- Ref<Texture2D> get_disabled_texture() const;
- Ref<Texture2D> get_focused_texture() const;
+ Ref<Texture2D> get_texture_normal() const;
+ Ref<Texture2D> get_texture_pressed() const;
+ Ref<Texture2D> get_texture_hover() const;
+ Ref<Texture2D> get_texture_disabled() const;
+ Ref<Texture2D> get_texture_focused() const;
Ref<BitMap> get_click_mask() const;
bool get_ignore_texture_size() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 1c96858da7..2da76883b4 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -4338,6 +4338,12 @@ TreeItem *Tree::get_selected() const {
return selected_item;
}
+void Tree::set_selected(TreeItem *p_item, int p_column) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+ ERR_FAIL_COND(!p_item);
+ select_single_item(p_item, get_root(), p_column);
+}
+
int Tree::get_selected_column() const {
return selected_col;
}
@@ -4547,6 +4553,7 @@ void Tree::ensure_cursor_is_visible() {
return; // Nothing under cursor.
}
+ // Note: Code below similar to Tree::scroll_to_item(), in case of bug fix both.
const Size2 area_size = get_size() - theme_cache.panel_style->get_minimum_size();
int y_offset = get_item_offset(selected_item);
@@ -4555,7 +4562,10 @@ void Tree::ensure_cursor_is_visible() {
y_offset -= tbh;
const int cell_h = compute_item_height(selected_item) + theme_cache.vseparation;
- const int screen_h = area_size.height - h_scroll->get_combined_minimum_size().height - tbh;
+ int screen_h = area_size.height - tbh;
+ if (h_scroll->is_visible()) {
+ screen_h -= h_scroll->get_combined_minimum_size().height;
+ }
if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
v_scroll->set_value(y_offset);
@@ -4706,26 +4716,32 @@ Point2 Tree::get_scroll() const {
void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
ERR_FAIL_NULL(p_item);
- if (!is_visible_in_tree() || !p_item->is_visible()) {
- return; // Hack to work around crash in get_item_rect() if Tree is not in tree.
- }
update_scrollbars();
- const real_t tree_height = get_size().y;
- const Rect2 item_rect = get_item_rect(p_item);
- const real_t item_y = item_rect.position.y;
- const real_t item_height = item_rect.size.y + theme_cache.vseparation;
+ // Note: Code below similar to Tree::ensure_cursor_is_visible(), in case of bug fix both.
+ const Size2 area_size = get_size() - theme_cache.panel_style->get_minimum_size();
- if (p_center_on_item) {
- v_scroll->set_value(item_y - (tree_height - item_height) / 2.0f);
- } else {
- if (item_y < v_scroll->get_value()) {
- v_scroll->set_value(item_y);
+ int y_offset = get_item_offset(p_item);
+ if (y_offset != -1) {
+ const int tbh = _get_title_button_height();
+ y_offset -= tbh;
+
+ const int cell_h = compute_item_height(p_item) + theme_cache.vseparation;
+ int screen_h = area_size.height - tbh;
+ if (h_scroll->is_visible()) {
+ screen_h -= h_scroll->get_combined_minimum_size().height;
+ }
+
+ if (p_center_on_item) {
+ v_scroll->set_value(y_offset - (screen_h - cell_h) / 2.0f);
} else {
- const real_t new_position = item_y + item_height - tree_height;
- if (new_position > v_scroll->get_value()) {
- v_scroll->set_value(new_position);
+ if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
+ v_scroll->set_value(y_offset);
+ } else if (y_offset + cell_h > v_scroll->get_value() + screen_h) {
+ v_scroll->set_value(y_offset - screen_h + cell_h);
+ } else if (y_offset < v_scroll->get_value()) {
+ v_scroll->set_value(y_offset);
}
}
}
@@ -5156,6 +5172,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_root_hidden"), &Tree::is_root_hidden);
ClassDB::bind_method(D_METHOD("get_next_selected", "from"), &Tree::get_next_selected);
ClassDB::bind_method(D_METHOD("get_selected"), &Tree::get_selected);
+ ClassDB::bind_method(D_METHOD("set_selected", "item", "column"), &Tree::set_selected);
ClassDB::bind_method(D_METHOD("get_selected_column"), &Tree::get_selected_column);
ClassDB::bind_method(D_METHOD("get_pressed_button"), &Tree::get_pressed_button);
ClassDB::bind_method(D_METHOD("set_select_mode", "mode"), &Tree::set_select_mode);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index f994a5cec1..77a62e1d6a 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -666,6 +666,7 @@ public:
bool is_root_hidden() const;
TreeItem *get_next_selected(TreeItem *p_item);
TreeItem *get_selected() const;
+ void set_selected(TreeItem *p_item, int p_column = 0);
int get_selected_column() const;
int get_pressed_button() const;
void set_select_mode(SelectMode p_mode);
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 2c395ec07d..62f362553f 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -276,10 +276,10 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
}
if (content_encoding == "gzip") {
decompressor.instantiate();
- decompressor->start_decompression(false, get_download_chunk_size() * 2);
+ decompressor->start_decompression(false, get_download_chunk_size());
} else if (content_encoding == "deflate") {
decompressor.instantiate();
- decompressor->start_decompression(true, get_download_chunk_size() * 2);
+ decompressor->start_decompression(true, get_download_chunk_size());
}
return false;
@@ -390,19 +390,38 @@ bool HTTPRequest::_update_connection() {
return false;
}
- PackedByteArray chunk = client->read_response_body_chunk();
- downloaded.add(chunk.size());
-
- // Decompress chunk if needed.
- if (decompressor.is_valid()) {
- Error err = decompressor->put_data(chunk.ptr(), chunk.size());
- if (err == OK) {
- chunk.resize(decompressor->get_available_bytes());
- err = decompressor->get_data(chunk.ptrw(), chunk.size());
- }
- if (err != OK) {
- _defer_done(RESULT_BODY_DECOMPRESS_FAILED, response_code, response_headers, PackedByteArray());
- return true;
+ PackedByteArray chunk;
+ if (decompressor.is_null()) {
+ // Chunk can be read directly.
+ chunk = client->read_response_body_chunk();
+ downloaded.add(chunk.size());
+ } else {
+ // Chunk is the result of decompression.
+ PackedByteArray compressed = client->read_response_body_chunk();
+ downloaded.add(compressed.size());
+
+ int pos = 0;
+ int left = compressed.size();
+ while (left) {
+ int w = 0;
+ Error err = decompressor->put_partial_data(compressed.ptr() + pos, left, w);
+ if (err == OK) {
+ PackedByteArray dc;
+ dc.resize(decompressor->get_available_bytes());
+ err = decompressor->get_data(dc.ptrw(), dc.size());
+ chunk.append_array(dc);
+ }
+ if (err != OK) {
+ _defer_done(RESULT_BODY_DECOMPRESS_FAILED, response_code, response_headers, PackedByteArray());
+ return true;
+ }
+ // We need this check here because a "zip bomb" could result in a chunk of few kilos decompressing into gigabytes of data.
+ if (body_size_limit >= 0 && final_body_size.get() + chunk.size() > body_size_limit) {
+ _defer_done(RESULT_BODY_SIZE_LIMIT_EXCEEDED, response_code, response_headers, PackedByteArray());
+ return true;
+ }
+ pos += w;
+ left -= w;
}
}
final_body_size.add(chunk.size());
diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp
index 946929aa89..8b4b98c172 100644
--- a/scene/main/multiplayer_api.cpp
+++ b/scene/main/multiplayer_api.cpp
@@ -39,7 +39,7 @@
#include "core/os/os.h"
#endif
-StringName MultiplayerAPI::default_interface = StringName();
+StringName MultiplayerAPI::default_interface;
void MultiplayerAPI::set_default_interface(const StringName &p_interface) {
ERR_FAIL_COND_MSG(!ClassDB::is_parent_class(p_interface, MultiplayerAPI::get_class_static()), vformat("Can't make %s the default multiplayer interface since it does not extend MultiplayerAPI.", p_interface));
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 304504a82e..f88fdb3ac1 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1759,11 +1759,11 @@ void Node::add_to_group(const StringName &p_identifier, bool p_persistent) {
}
void Node::remove_from_group(const StringName &p_identifier) {
- ERR_FAIL_COND(!data.grouped.has(p_identifier));
-
HashMap<StringName, GroupData>::Iterator E = data.grouped.find(p_identifier);
- ERR_FAIL_COND(!E);
+ if (!E) {
+ return;
+ }
if (data.tree) {
data.tree->remove_from_group(E->key, this);
@@ -2060,7 +2060,7 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
nip->set_instance_path(ip->get_instance_path());
node = nip;
- } else if ((p_flags & DUPLICATE_USE_INSTANCING) && !get_scene_file_path().is_empty()) {
+ } else if ((p_flags & DUPLICATE_USE_INSTANTIATION) && !get_scene_file_path().is_empty()) {
Ref<PackedScene> res = ResourceLoader::load(get_scene_file_path());
ERR_FAIL_COND_V(res.is_null(), nullptr);
PackedScene::GenEditState ges = PackedScene::GEN_EDIT_STATE_DISABLED;
@@ -2246,7 +2246,7 @@ Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap) con
}
Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const {
- Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANCING | DUPLICATE_FROM_EDITOR, &r_duplimap);
+ Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANTIATION | DUPLICATE_FROM_EDITOR, &r_duplimap);
// This is used by SceneTreeDock's paste functionality. When pasting to foreign scene, resources are duplicated.
if (!p_resource_remap.is_empty()) {
@@ -2581,10 +2581,14 @@ void Node::print_orphan_nodes() {
}
void Node::queue_free() {
+ // There are users which instantiate multiple scene trees for their games.
+ // Use the node's own tree to handle its deletion when relevant.
if (is_inside_tree()) {
get_tree()->queue_delete(this);
} else {
- SceneTree::get_singleton()->queue_delete(this);
+ SceneTree *tree = SceneTree::get_singleton();
+ ERR_FAIL_NULL_MSG(tree, "Can't queue free a node when no SceneTree is available.");
+ tree->queue_delete(this);
}
}
@@ -2652,7 +2656,7 @@ PackedStringArray Node::get_configuration_warnings() const {
String Node::get_configuration_warnings_as_string() const {
PackedStringArray warnings = get_configuration_warnings();
- String all_warnings = String();
+ String all_warnings;
for (int i = 0; i < warnings.size(); i++) {
if (i > 0) {
all_warnings += "\n\n";
@@ -2812,7 +2816,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tree"), &Node::get_tree);
ClassDB::bind_method(D_METHOD("create_tween"), &Node::create_tween);
- ClassDB::bind_method(D_METHOD("duplicate", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANCING | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS));
+ ClassDB::bind_method(D_METHOD("duplicate", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANTIATION | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS));
ClassDB::bind_method(D_METHOD("replace_by", "node", "keep_groups"), &Node::replace_by, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_scene_instance_load_placeholder", "load_placeholder"), &Node::set_scene_instance_load_placeholder);
@@ -2918,7 +2922,7 @@ void Node::_bind_methods() {
BIND_ENUM_CONSTANT(DUPLICATE_SIGNALS);
BIND_ENUM_CONSTANT(DUPLICATE_GROUPS);
BIND_ENUM_CONSTANT(DUPLICATE_SCRIPTS);
- BIND_ENUM_CONSTANT(DUPLICATE_USE_INSTANCING);
+ BIND_ENUM_CONSTANT(DUPLICATE_USE_INSTANTIATION);
BIND_ENUM_CONSTANT(INTERNAL_MODE_DISABLED);
BIND_ENUM_CONSTANT(INTERNAL_MODE_FRONT);
diff --git a/scene/main/node.h b/scene/main/node.h
index 4a3ec253b1..5e51ec6b0e 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -57,7 +57,7 @@ public:
DUPLICATE_SIGNALS = 1,
DUPLICATE_GROUPS = 2,
DUPLICATE_SCRIPTS = 4,
- DUPLICATE_USE_INSTANCING = 8,
+ DUPLICATE_USE_INSTANTIATION = 8,
#ifdef TOOLS_ENABLED
DUPLICATE_FROM_EDITOR = 16,
#endif
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 41eefe0f85..81a4e3073b 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -123,6 +123,9 @@ void SceneTree::tree_changed() {
void SceneTree::node_added(Node *p_node) {
emit_signal(node_added_name, p_node);
+ if (call_lock > 0) {
+ call_skip.erase(p_node->get_instance_id());
+ }
}
void SceneTree::node_removed(Node *p_node) {
@@ -131,7 +134,7 @@ void SceneTree::node_removed(Node *p_node) {
}
emit_signal(node_removed_name, p_node);
if (call_lock > 0) {
- call_skip.insert(p_node);
+ call_skip.insert(p_node->get_instance_id());
}
}
@@ -261,7 +264,7 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro
if (p_call_flags & GROUP_CALL_REVERSE) {
for (int i = gr_node_count - 1; i >= 0; i--) {
- if (call_lock && call_skip.has(gr_nodes[i])) {
+ if (call_lock && call_skip.has(gr_nodes[i]->get_instance_id())) {
continue;
}
@@ -275,7 +278,7 @@ void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_gro
} else {
for (int i = 0; i < gr_node_count; i++) {
- if (call_lock && call_skip.has(gr_nodes[i])) {
+ if (call_lock && call_skip.has(gr_nodes[i]->get_instance_id())) {
continue;
}
@@ -314,7 +317,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr
if (p_call_flags & GROUP_CALL_REVERSE) {
for (int i = gr_node_count - 1; i >= 0; i--) {
- if (call_lock && call_skip.has(gr_nodes[i])) {
+ if (call_lock && call_skip.has(gr_nodes[i]->get_instance_id())) {
continue;
}
@@ -327,7 +330,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr
} else {
for (int i = 0; i < gr_node_count; i++) {
- if (call_lock && call_skip.has(gr_nodes[i])) {
+ if (call_lock && call_skip.has(gr_nodes[i]->get_instance_id())) {
continue;
}
@@ -365,7 +368,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group
if (p_call_flags & GROUP_CALL_REVERSE) {
for (int i = gr_node_count - 1; i >= 0; i--) {
- if (call_lock && call_skip.has(gr_nodes[i])) {
+ if (call_lock && call_skip.has(gr_nodes[i]->get_instance_id())) {
continue;
}
@@ -378,7 +381,7 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group
} else {
for (int i = 0; i < gr_node_count; i++) {
- if (call_lock && call_skip.has(gr_nodes[i])) {
+ if (call_lock && call_skip.has(gr_nodes[i]->get_instance_id())) {
continue;
}
@@ -854,7 +857,7 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio
for (int i = 0; i < gr_node_count; i++) {
Node *n = gr_nodes[i];
- if (call_lock && call_skip.has(n)) {
+ if (call_lock && call_skip.has(n->get_instance_id())) {
continue;
}
@@ -904,7 +907,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal
}
Node *n = gr_nodes[i];
- if (call_lock && call_skip.has(n)) {
+ if (call_lock && call_skip.has(n->get_instance_id())) {
continue;
}
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index a460e40597..d4fcb288ae 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -135,7 +135,7 @@ private:
// Safety for when a node is deleted while a group is being called.
int call_lock = 0;
- HashSet<Node *> call_skip; // Skip erased nodes.
+ HashSet<ObjectID> call_skip; // Skip erased nodes. Store ID instead of pointer to avoid false positives when node is freed and a new node is allocated at the pointed address.
List<ObjectID> delete_queue;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index f4e55c0de3..9e440405af 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1561,44 +1561,15 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
set_input_as_handled();
}
- if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) {
+ if (gui.dragging && mb->get_button_index() == MouseButton::LEFT) {
// Alternate drop use (when using force_drag(), as proposed by #5342).
- gui.drag_successful = false;
- if (gui.mouse_focus) {
- gui.drag_successful = _gui_drop(gui.mouse_focus, pos, false);
- }
-
- gui.drag_data = Variant();
- gui.dragging = false;
-
- Control *drag_preview = _gui_get_drag_preview();
- if (drag_preview) {
- memdelete(drag_preview);
- gui.drag_preview_id = ObjectID();
- }
- _propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
- get_base_window()->update_mouse_cursor_shape();
+ _perform_drop(gui.mouse_focus, pos);
}
_gui_cancel_tooltip();
} else {
- if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) {
- gui.drag_successful = false;
- if (gui.drag_mouse_over) {
- gui.drag_successful = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false);
- }
-
- Control *drag_preview = _gui_get_drag_preview();
- if (drag_preview) {
- memdelete(drag_preview);
- gui.drag_preview_id = ObjectID();
- }
-
- gui.drag_data = Variant();
- gui.dragging = false;
- gui.drag_mouse_over = nullptr;
- _propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
- get_base_window()->update_mouse_cursor_shape();
+ if (gui.dragging && mb->get_button_index() == MouseButton::LEFT) {
+ _perform_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos);
}
gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask.
@@ -1652,7 +1623,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *control = Object::cast_to<Control>(ci);
if (control) {
gui.dragging = true;
- gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos) - gui.drag_accum);
+ gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos - gui.drag_accum));
if (gui.drag_data.get_type() != Variant::NIL) {
gui.mouse_focus = nullptr;
gui.forced_mouse_focus = false;
@@ -1682,7 +1653,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
gui.drag_attempted = true;
- if (gui.drag_data.get_type() != Variant::NIL) {
+ if (gui.dragging) {
_propagate_viewport_notification(this, NOTIFICATION_DRAG_BEGIN);
}
}
@@ -1698,6 +1669,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
_gui_cancel_tooltip();
if (over) {
+ if (!gui.mouse_over) {
+ _drop_physics_mouseover();
+ }
_gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER);
gui.mouse_over = over;
}
@@ -1795,7 +1769,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
- if (gui.drag_data.get_type() != Variant::NIL) {
+ if (gui.dragging) {
// Handle drag & drop.
Control *drag_preview = _gui_get_drag_preview();
@@ -1997,6 +1971,12 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
if (mm.is_null() && mb.is_null() && p_event->is_action_type()) {
+ if (gui.dragging && p_event->is_action_pressed("ui_cancel") && Input::get_singleton()->is_action_just_pressed("ui_cancel")) {
+ _perform_drop();
+ set_input_as_handled();
+ return;
+ }
+
if (gui.key_focus && !gui.key_focus->is_visible_in_tree()) {
gui.key_focus->release_focus();
}
@@ -2078,6 +2058,27 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
+void Viewport::_perform_drop(Control *p_control, Point2 p_pos) {
+ // Without any arguments, simply cancel Drag and Drop.
+ if (p_control) {
+ gui.drag_successful = _gui_drop(p_control, p_pos, false);
+ } else {
+ gui.drag_successful = false;
+ }
+
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ memdelete(drag_preview);
+ gui.drag_preview_id = ObjectID();
+ }
+
+ gui.drag_data = Variant();
+ gui.dragging = false;
+ gui.drag_mouse_over = nullptr;
+ _propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
+ get_base_window()->update_mouse_cursor_shape();
+}
+
void Viewport::_gui_cleanup_internal_state(Ref<InputEvent> p_event) {
ERR_FAIL_COND(p_event.is_null());
@@ -2662,6 +2663,11 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
} else {
gui.subwindow_resize_mode = _sub_window_get_resize_margin(sw.window, mb->get_position());
if (gui.subwindow_resize_mode != SUB_WINDOW_RESIZE_DISABLED) {
+ if (gui.subwindow_focused != sw.window) {
+ // Refocus.
+ _sub_window_grab_focus(sw.window);
+ }
+
gui.subwindow_resize_from_rect = r;
gui.subwindow_drag_from = mb->get_position();
gui.subwindow_drag = SUB_WINDOW_DRAG_RESIZE;
@@ -3041,8 +3047,6 @@ bool Viewport::gui_is_drag_successful() const {
}
void Viewport::set_input_as_handled() {
- _drop_physics_mouseover();
-
if (!handle_input_locally) {
ERR_FAIL_COND(!is_inside_tree());
Viewport *vp = this;
@@ -4161,7 +4165,7 @@ DisplayServer::WindowID SubViewport::get_window_id() const {
}
Transform2D SubViewport::_stretch_transform() {
- Transform2D transform = Transform2D();
+ Transform2D transform;
Size2i view_size_2d_override = _get_size_2d_override();
if (size_2d_override_stretch && view_size_2d_override.width > 0 && view_size_2d_override.height > 0) {
Size2 scale = Size2(_get_size()) / Size2(view_size_2d_override);
@@ -4172,7 +4176,7 @@ Transform2D SubViewport::_stretch_transform() {
}
Transform2D SubViewport::get_screen_transform() const {
- Transform2D container_transform = Transform2D();
+ Transform2D container_transform;
SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent());
if (c) {
if (c->is_stretch_enabled()) {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 8911aea335..dc69ec24d8 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -405,6 +405,7 @@ private:
Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform);
void _gui_input_event(Ref<InputEvent> p_event);
+ void _perform_drop(Control *p_control = nullptr, Point2 p_pos = Point2());
void _gui_cleanup_internal_state(Ref<InputEvent> p_event);
_FORCE_INLINE_ Transform2D _get_input_pre_xform() const;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index ebb11ecee8..aff2c594d9 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -1633,7 +1633,7 @@ void Window::_validate_property(PropertyInfo &p_property) const {
}
Transform2D Window::get_screen_transform() const {
- Transform2D embedder_transform = Transform2D();
+ Transform2D embedder_transform;
if (_get_embedder()) {
embedder_transform.translate_local(get_position());
embedder_transform = _get_embedder()->get_screen_transform() * embedder_transform;
diff --git a/scene/property_utils.h b/scene/property_utils.h
index 5ada35fdd7..5b0200b491 100644
--- a/scene/property_utils.h
+++ b/scene/property_utils.h
@@ -42,7 +42,7 @@ public:
// Gets the instance/inheritance states of this node, in order of precedence,
// that is, from the topmost (the most able to override values) to the lowermost
- // (Note that in nested instancing the one with the greatest precedence is the furthest
+ // (Note that in nested instantiation, the one with the greatest precedence is the furthest
// in the tree, since every owner found while traversing towards the root gets a chance
// to override property values.)
static Vector<SceneState::PackState> get_node_states_stack(const Node *p_node, const Node *p_owner = nullptr, bool *r_instantiated_by_owner = nullptr);
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 0f55c7b3b8..ee45a8ea6f 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -960,6 +960,7 @@ void register_scene_types() {
ClassDB::add_compatibility_class("Navigation3D", "Node3D");
ClassDB::add_compatibility_class("Navigation2D", "Node2D");
ClassDB::add_compatibility_class("OpenSimplexNoise", "FastNoiseLite");
+ ClassDB::add_compatibility_class("ProximityGroup", "Node3D");
ClassDB::add_compatibility_class("ToolButton", "Button");
ClassDB::add_compatibility_class("YSort", "Node2D");
// Portal and room occlusion was replaced by raster occlusion (OccluderInstance3D node).
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 1eb78f0160..da73a479ce 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -888,7 +888,6 @@ int Animation::add_track(TrackType p_type, int p_at_pos) {
}
}
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
return p_at_pos;
}
@@ -951,7 +950,6 @@ void Animation::remove_track(int p_track) {
memdelete(t);
tracks.remove_at(p_track);
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
int Animation::get_track_count() const {
@@ -967,7 +965,6 @@ void Animation::track_set_path(int p_track, const NodePath &p_path) {
ERR_FAIL_INDEX(p_track, tracks.size());
tracks[p_track]->path = p_path;
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
NodePath Animation::track_get_path(int p_track) const {
@@ -2467,7 +2464,6 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
ERR_FAIL_COND_V(idx == -2, T());
- bool result = true;
int next = 0;
real_t c = 0.0;
// prepare for all cases of interpolation
@@ -2599,10 +2595,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
}
if (p_ok) {
- *p_ok = result;
- }
- if (!result) {
- return T();
+ *p_ok = true;
}
real_t tr = p_keys[idx].transition;
@@ -3834,7 +3827,6 @@ void Animation::track_move_up(int p_track) {
}
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::track_move_down(int p_track) {
@@ -3843,7 +3835,6 @@ void Animation::track_move_down(int p_track) {
}
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::track_move_to(int p_track, int p_to_index) {
@@ -3859,7 +3850,6 @@ void Animation::track_move_to(int p_track, int p_to_index) {
tracks.insert(p_to_index > p_track ? p_to_index - 1 : p_to_index, track);
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::track_swap(int p_track, int p_with_track) {
@@ -3871,7 +3861,6 @@ void Animation::track_swap(int p_track, int p_with_track) {
SWAP(tracks.write[p_track], tracks.write[p_with_track]);
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
void Animation::set_step(real_t p_step) {
@@ -4001,8 +3990,6 @@ void Animation::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Ping-Pong"), "set_loop_mode", "get_loop_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001,suffix:s"), "set_step", "get_step");
- ADD_SIGNAL(MethodInfo("tracks_changed"));
-
BIND_ENUM_CONSTANT(TYPE_VALUE);
BIND_ENUM_CONSTANT(TYPE_POSITION_3D);
BIND_ENUM_CONSTANT(TYPE_ROTATION_3D);
@@ -4041,7 +4028,6 @@ void Animation::clear() {
compression.pages.clear();
compression.fps = 120;
emit_changed();
- emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) {
@@ -4964,7 +4950,7 @@ void Animation::compress(uint32_t p_page_size, uint32_t p_fps, float p_split_tol
if (rollback || best_frame == FRAME_MAX) {
// Commit the page if had to rollback or if no track was found
- print_animc("\tCommiting page..");
+ print_animc("\tCommiting page...");
// The end frame for the page depends entirely on whether its valid or
// no more keys were found.
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index 1b06e09bb8..4afc82576d 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -169,7 +169,15 @@ Dictionary BitMap::_get_data() const {
return d;
}
-Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_start) const {
+struct CrossStackEntry {
+ Point2i cross;
+ Vector<int> ranges;
+
+ _FORCE_INLINE_ bool operator==(const CrossStackEntry &p_other) const { return cross == p_other.cross; }
+ _FORCE_INLINE_ bool operator!=(const CrossStackEntry &p_other) const { return cross != p_other.cross; }
+};
+
+Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_start) const {
int stepx = 0;
int stepy = 0;
int prevx = 0;
@@ -179,9 +187,20 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_sta
int curx = startx;
int cury = starty;
unsigned int count = 0;
- HashSet<Point2i> case9s;
- HashSet<Point2i> case6s;
- Vector<Vector2> _points;
+
+ Vector<CrossStackEntry> cross_stack;
+ int cross_stack_size = 0;
+
+ // Add starting point to stack as the default entry.
+ cross_stack.push_back({ Point2i(-1, -1), Vector<int>({ 0 }) });
+ cross_stack_size++;
+
+ Vector<Point2i> _points;
+ Vector<Vector<Vector2>> ret;
+
+ // Add starting entry at start of return.
+ ret.resize(1);
+
do {
int sv = 0;
{ // Square value
@@ -202,7 +221,7 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_sta
sv += (p_rect.has_point(bl) && get_bitv(bl)) ? 4 : 0;
Point2i br = Point2i(curx, cury);
sv += (p_rect.has_point(br) && get_bitv(br)) ? 8 : 0;
- ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector2>());
+ ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector<Vector2>>());
}
switch (sv) {
@@ -266,70 +285,139 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_sta
stepy = 0;
break;
case 9:
- /*
+ /* Going DOWN if coming from the LEFT, otherwise go UP.
+ 9
+---+---+
| 1 | |
+---+---+
| | 8 |
+---+---+
- this should normally go UP, but if we already been here, we go down
*/
- if (case9s.has(Point2i(curx, cury))) {
- //found, so we go down, and delete from case9s;
+
+ if (prevx == 1) {
stepx = 0;
stepy = 1;
- case9s.erase(Point2i(curx, cury));
} else {
- //not found, we go up, and add to case9s;
stepx = 0;
stepy = -1;
- case9s.insert(Point2i(curx, cury));
}
break;
case 6:
- /*
+ /* Going RIGHT if coming from BELOW, otherwise go LEFT.
6
+---+---+
| | 2 |
+---+---+
| 4 | |
+---+---+
- this normally go RIGHT, but if it's coming from RIGHT, it should go LEFT
*/
- if (case6s.has(Point2i(curx, cury))) {
- //found, so we go left, and delete from case6s;
- stepx = -1;
+
+ if (prevy == -1) {
+ stepx = 1;
stepy = 0;
- case6s.erase(Point2i(curx, cury));
} else {
- //not found, we go right, and add to case6s;
- stepx = 1;
+ stepx = -1;
stepy = 0;
- case6s.insert(Point2i(curx, cury));
}
break;
default:
ERR_PRINT("this shouldn't happen.");
}
+
+ // Handle crossing points.
+ if (sv == 6 || sv == 9) {
+ const int new_index = _points.size() - 1;
+
+ // Add previous point to last stack entry.
+ cross_stack.write[cross_stack_size - 1].ranges.push_back(new_index);
+
+ // Create temporary entry to maybe insert, for searching.
+ const CrossStackEntry new_entry = { _points[new_index], Vector<int>({ new_index }) };
+
+ // Attempt to find matching entry.
+ const int found = cross_stack.rfind(new_entry, cross_stack_size - 1);
+
+ if (found != -1) {
+ Vector<Vector2> tmp;
+
+ // Iterate over entries between end of stack and found, adding ranges to result.
+ for (int i = found; i < cross_stack_size; i++) {
+ const Vector<int> &ranges = cross_stack[i].ranges;
+
+ for (int j = 0; j < ranges.size() / 2; j++) {
+ int first = ranges[2 * j];
+ const int last = ranges[2 * j + 1];
+
+ int new_pos = tmp.size();
+
+ tmp.resize(tmp.size() + (last - first));
+
+ Vector2 *tmp_ptrw = tmp.ptrw();
+
+ for (; first < last; first++, new_pos++) {
+ tmp_ptrw[new_pos].x = (float)(_points[first].x - p_rect.position.x);
+ tmp_ptrw[new_pos].y = (float)(_points[first].y - p_rect.position.y);
+ }
+ }
+ }
+
+ ret.push_back(tmp);
+
+ // Shrink stack.
+ cross_stack_size = found;
+
+ // Add previous point to last stack entry.
+ cross_stack.write[cross_stack_size - 1].ranges.push_back(new_index);
+ } else {
+ cross_stack.resize(MAX(cross_stack_size + 1, cross_stack.size()));
+ cross_stack.set(cross_stack_size, new_entry);
+ cross_stack_size++;
+ }
+ }
+
// Small optimization:
// If the previous direction is same as the current direction,
// then we should modify the last vector to current.
curx += stepx;
cury += stepy;
if (stepx == prevx && stepy == prevy) {
- _points.write[_points.size() - 1].x = (float)(curx - p_rect.position.x);
- _points.write[_points.size() - 1].y = (float)(cury + p_rect.position.y);
+ _points.write[_points.size() - 1].x = curx;
+ _points.write[_points.size() - 1].y = cury;
} else {
- _points.push_back(Vector2((float)(curx - p_rect.position.x), (float)(cury + p_rect.position.y)));
+ _points.push_back(Point2i(curx, cury));
}
count++;
prevx = stepx;
prevy = stepy;
- ERR_FAIL_COND_V((int)count > width * height, _points);
+ ERR_FAIL_COND_V((int)count > width * height, Vector<Vector<Vector2>>());
} while (curx != startx || cury != starty);
- return _points;
+
+ // Add last position to last stack entry.
+ cross_stack.write[cross_stack_size - 1].ranges.push_back(_points.size());
+
+ for (int i = 0; i < cross_stack_size; i++) {
+ const Vector<int> &ranges = cross_stack[i].ranges;
+
+ for (int j = 0; j < ranges.size() / 2; j++) {
+ int first = ranges[2 * j];
+ const int last = ranges[2 * j + 1];
+
+ int new_pos = ret[0].size();
+
+ ret.write[0].resize(ret[0].size() + (last - first));
+
+ Vector2 *tmp_ptrw = ret.write[0].ptrw();
+
+ for (; first < last; first++, new_pos++) {
+ tmp_ptrw[new_pos].x = (float)(_points[first].x - p_rect.position.x);
+ tmp_ptrw[new_pos].y = (float)(_points[first].y - p_rect.position.y);
+ }
+ }
+ }
+
+ return ret;
}
static float perpendicular_distance(const Vector2 &i, const Vector2 &start, const Vector2 &end) {
@@ -442,7 +530,7 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
for (int j = next_j; j <= pos.y + 1; j++) {
if (popped) {
// The next loop over j must start normally.
- next_j = pos.y;
+ next_j = pos.y - 1;
popped = false;
// Skip because an iteration was already executed with current counter values.
continue;
@@ -486,13 +574,10 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
}
}
} while (reenter || popped);
-
- print_verbose("BitMap: Max stack size: " + itos(stack.size()));
}
Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2i &p_rect, float p_epsilon) const {
Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect);
- print_verbose("BitMap: Rect: " + r);
Point2i from;
Ref<BitMap> fill;
@@ -505,17 +590,16 @@ Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2i &p_rect, fl
if (!fill->get_bit(j, i) && get_bit(j, i)) {
fill_bits(this, fill, Point2i(j, i), r);
- Vector<Vector2> polygon = _march_square(r, Point2i(j, i));
- print_verbose("BitMap: Pre reduce: " + itos(polygon.size()));
- polygon = reduce(polygon, r, p_epsilon);
- print_verbose("BitMap: Post reduce: " + itos(polygon.size()));
+ for (Vector<Vector2> polygon : _march_square(r, Point2i(j, i))) {
+ polygon = reduce(polygon, r, p_epsilon);
- if (polygon.size() < 3) {
- print_verbose("Invalid polygon, skipped");
- continue;
- }
+ if (polygon.size() < 3) {
+ print_verbose("Invalid polygon, skipped");
+ continue;
+ }
- polygons.push_back(polygon);
+ polygons.push_back(polygon);
+ }
}
}
}
diff --git a/scene/resources/bit_map.h b/scene/resources/bit_map.h
index 291ed8c4d0..0ec5772fd1 100644
--- a/scene/resources/bit_map.h
+++ b/scene/resources/bit_map.h
@@ -46,7 +46,7 @@ class BitMap : public Resource {
int width = 0;
int height = 0;
- Vector<Vector2> _march_square(const Rect2i &p_rect, const Point2i &p_start) const;
+ Vector<Vector<Vector2>> _march_square(const Rect2i &p_rect, const Point2i &p_start) const;
TypedArray<PackedVector2Array> _opaque_to_polygons_bind(const Rect2i &p_rect, float p_epsilon) const;
diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp
index dfaf82f36a..5698e61004 100644
--- a/scene/resources/bone_map.cpp
+++ b/scene/resources/bone_map.cpp
@@ -93,7 +93,7 @@ void BoneMap::set_skeleton_bone_name(StringName p_profile_bone_name, const Strin
}
StringName BoneMap::find_profile_bone_name(StringName p_skeleton_bone_name) const {
- StringName profile_bone_name = StringName();
+ StringName profile_bone_name;
HashMap<StringName, StringName>::ConstIterator E = bone_map.begin();
while (E) {
if (E->value == p_skeleton_bone_name) {
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index eda9af9dde..0c36abc148 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -31,6 +31,7 @@
#include "curve.h"
#include "core/core_string_names.h"
+#include "core/math/math_funcs.h"
const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed";
@@ -1413,8 +1414,9 @@ void Curve3D::_bake() const {
if (points.size() == 0) {
baked_point_cache.clear();
baked_tilt_cache.clear();
- baked_up_vector_cache.clear();
baked_dist_cache.clear();
+
+ baked_up_vector_cache.clear();
return;
}
@@ -1438,15 +1440,16 @@ void Curve3D::_bake() const {
Vector3 position = points[0].position;
real_t dist = 0.0;
- List<Plane> pointlist;
+ List<Plane> pointlist; // Abuse Plane for (position, dist)
List<real_t> distlist;
// Start always from origin.
pointlist.push_back(Plane(position, points[0].tilt));
distlist.push_back(0.0);
+ // Step 1: Sample points
+ const real_t step = 0.1; // At least 10 substeps ought to be enough?
for (int i = 0; i < points.size() - 1; i++) {
- real_t step = 0.1; // at least 10 substeps ought to be enough?
real_t p = 0.0;
while (p < 1.0) {
@@ -1461,7 +1464,7 @@ void Curve3D::_bake() const {
if (d > bake_interval) {
// OK! between P and NP there _has_ to be Something, let's go searching!
- int iterations = 10; //lots of detail!
+ const int iterations = 10; // Lots of detail!
real_t low = p;
real_t hi = np;
@@ -1496,76 +1499,135 @@ void Curve3D::_bake() const {
Vector3 npp = points[i + 1].position;
real_t d = position.distance_to(npp);
- position = npp;
- Plane post;
- post.normal = position;
- post.d = points[i + 1].tilt;
+ if (d > CMP_EPSILON) { // Avoid the degenerate case of two very close points.
+ position = npp;
+ Plane post;
+ post.normal = position;
+ post.d = points[i + 1].tilt;
- dist += d;
+ dist += d;
- pointlist.push_back(post);
- distlist.push_back(dist);
+ pointlist.push_back(post);
+ distlist.push_back(dist);
+ }
}
baked_max_ofs = dist;
- baked_point_cache.resize(pointlist.size());
- Vector3 *w = baked_point_cache.ptrw();
- int idx = 0;
+ const int point_count = pointlist.size();
+ {
+ baked_point_cache.resize(point_count);
+ Vector3 *w = baked_point_cache.ptrw();
- baked_tilt_cache.resize(pointlist.size());
- real_t *wt = baked_tilt_cache.ptrw();
+ baked_tilt_cache.resize(point_count);
+ real_t *wt = baked_tilt_cache.ptrw();
- baked_up_vector_cache.resize(up_vector_enabled ? pointlist.size() : 0);
- Vector3 *up_write = baked_up_vector_cache.ptrw();
+ baked_dist_cache.resize(point_count);
+ real_t *wd = baked_dist_cache.ptrw();
- baked_dist_cache.resize(pointlist.size());
- real_t *wd = baked_dist_cache.ptrw();
+ int idx = 0;
+ for (const Plane &E : pointlist) {
+ w[idx] = E.normal;
+ wt[idx] = E.d;
+ wd[idx] = distlist[idx];
- Vector3 sideways;
- Vector3 up;
- Vector3 forward;
+ idx++;
+ }
+ }
+
+ if (!up_vector_enabled) {
+ baked_up_vector_cache.resize(0);
+ return;
+ }
- Vector3 prev_sideways = Vector3(1, 0, 0);
- Vector3 prev_up = Vector3(0, 1, 0);
- Vector3 prev_forward = Vector3(0, 0, 1);
+ // Step 2: Calculate the up vectors and the whole local reference frame
+ //
+ // See Dougan, Carl. "The parallel transport frame." Game Programming Gems 2 (2001): 215-219.
+ // for an example discussing about why not the Frenet frame.
+ {
+ PackedVector3Array forward_vectors;
- for (const Plane &E : pointlist) {
- w[idx] = E.normal;
- wt[idx] = E.d;
- wd[idx] = distlist[idx];
+ baked_up_vector_cache.resize(point_count);
+ forward_vectors.resize(point_count);
- if (!up_vector_enabled) {
- idx++;
- continue;
+ Vector3 *up_write = baked_up_vector_cache.ptrw();
+ Vector3 *forward_write = forward_vectors.ptrw();
+
+ const Vector3 *points_ptr = baked_point_cache.ptr();
+
+ Basis frame; // X-right, Y-up, Z-forward.
+ Basis frame_prev;
+
+ // Set the initial frame based on Y-up rule.
+ {
+ Vector3 up(0, 1, 0);
+ Vector3 forward = (points_ptr[1] - points_ptr[0]).normalized();
+ if (forward.is_equal_approx(Vector3())) {
+ forward = Vector3(1, 0, 0);
+ }
+
+ if (abs(forward.dot(up)) > 1.0 - UNIT_EPSILON) {
+ frame_prev = Basis::looking_at(-forward, up);
+ } else {
+ frame_prev = Basis::looking_at(-forward, Vector3(1, 0, 0));
+ }
+
+ up_write[0] = frame_prev.get_column(1);
+ forward_write[0] = frame_prev.get_column(2);
}
- forward = idx > 0 ? (w[idx] - w[idx - 1]).normalized() : prev_forward;
+ // Calculate the Parallel Transport Frame.
+ for (int idx = 1; idx < point_count; idx++) {
+ Vector3 forward = (points_ptr[idx] - points_ptr[idx - 1]).normalized();
+ if (forward.is_equal_approx(Vector3())) {
+ forward = frame_prev.get_column(2);
+ }
- real_t y_dot = prev_up.dot(forward);
+ Basis rotate;
+ rotate.rotate_to_align(frame_prev.get_column(2), forward);
+ frame = rotate * frame_prev;
+ frame.orthonormalize(); // guard against float error accumulation
- if (y_dot > (1.0f - CMP_EPSILON)) {
- sideways = prev_sideways;
- up = -prev_forward;
- } else if (y_dot < -(1.0f - CMP_EPSILON)) {
- sideways = prev_sideways;
- up = prev_forward;
- } else {
- sideways = prev_up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
+ up_write[idx] = frame.get_column(1);
+ forward_write[idx] = frame.get_column(2);
+
+ frame_prev = frame;
}
- if (idx == 1) {
- up_write[0] = up;
+ bool is_loop = true;
+ // Loop smoothing only applies when the curve is a loop, which means two ends meet, and share forward directions.
+ {
+ if (!points_ptr[0].is_equal_approx(points_ptr[point_count - 1])) {
+ is_loop = false;
+ }
+
+ real_t dot = forward_write[0].dot(forward_write[point_count - 1]);
+ if (dot < 1.0 - 0.01) { // Alignment should not be too tight, or it dosen't work for coarse bake interval
+ is_loop = false;
+ }
}
- up_write[idx] = up;
+ // Twist up vectors, so that they align at two ends of the curve.
+ if (is_loop) {
+ const Vector3 up_start = up_write[0];
+ const Vector3 up_end = up_write[point_count - 1];
+
+ real_t sign = SIGN(up_end.cross(up_start).dot(forward_write[0]));
+ real_t full_angle = Quaternion(up_end, up_start).get_angle();
- prev_sideways = sideways;
- prev_up = up;
- prev_forward = forward;
+ if (abs(full_angle) < UNIT_EPSILON) {
+ return;
+ } else {
+ const real_t *dists = baked_dist_cache.ptr();
+ for (int idx = 1; idx < point_count; idx++) {
+ const real_t frac = dists[idx] / baked_max_ofs;
+ const real_t angle = Math::lerp((real_t)0.0, full_angle, frac);
+ Basis twist(forward_write[idx] * sign, angle);
- idx++;
+ up_write[idx] = twist.xform(up_write[idx]);
+ }
+ }
+ }
}
}
@@ -1577,27 +1639,15 @@ real_t Curve3D::get_baked_length() const {
return baked_max_ofs;
}
-Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
- if (baked_cache_dirty) {
- _bake();
- }
+Curve3D::Interval Curve3D::_find_interval(real_t p_offset) const {
+ Interval interval = {
+ -1,
+ 0.0
+ };
+ ERR_FAIL_COND_V_MSG(baked_cache_dirty, interval, "Backed cache is dirty");
- // Validate: Curve may not have baked points.
int pc = baked_point_cache.size();
- ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D.");
-
- if (pc == 1) {
- return baked_point_cache.get(0);
- }
-
- const Vector3 *r = baked_point_cache.ptr();
-
- if (p_offset < 0) {
- return r[0];
- }
- if (p_offset >= baked_max_ofs) {
- return r[pc - 1];
- }
+ ERR_FAIL_COND_V_MSG(pc < 2, interval, "Less than two points in cache");
int start = 0;
int end = pc;
@@ -1617,9 +1667,27 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(), "Couldn't find baked segment.");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, interval, "Offset out of range.");
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ interval.idx = idx;
+ if (idx_interval < FLT_EPSILON) {
+ interval.frac = 0.5; // For a very short interval, 0.5 is a reasonable choice.
+ ERR_FAIL_V_MSG(interval, "Zero length interval.");
+ }
+
+ interval.frac = (p_offset - offset_begin) / idx_interval;
+ return interval;
+}
+
+Vector3 Curve3D::_sample_baked(Interval p_interval, bool p_cubic) const {
+ // Assuming p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Vector3(), "Invalid interval");
+
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
+
+ const Vector3 *r = baked_point_cache.ptr();
+ int pc = baked_point_cache.size();
if (p_cubic) {
Vector3 pre = idx > 0 ? r[idx - 1] : r[idx];
@@ -1630,114 +1698,150 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
}
}
-real_t Curve3D::sample_baked_tilt(real_t p_offset) const {
- if (baked_cache_dirty) {
- _bake();
- }
-
- // Validate: Curve may not have baked tilts.
- int pc = baked_tilt_cache.size();
- ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D.");
+real_t Curve3D::_sample_baked_tilt(Interval p_interval) const {
+ // Assuming that p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_tilt_cache.size(), 0.0, "Invalid interval");
- if (pc == 1) {
- return baked_tilt_cache.get(0);
- }
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
const real_t *r = baked_tilt_cache.ptr();
- if (p_offset < 0) {
- return r[0];
+ return Math::lerp(r[idx], r[idx + 1], frac);
+}
+
+Basis Curve3D::_sample_posture(Interval p_interval, bool p_apply_tilt) const {
+ // Assuming that p_interval is valid.
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_point_cache.size(), Basis(), "Invalid interval");
+ if (up_vector_enabled) {
+ ERR_FAIL_INDEX_V_MSG(p_interval.idx, baked_up_vector_cache.size(), Basis(), "Invalid interval");
}
- if (p_offset >= baked_max_ofs) {
- return r[pc - 1];
+
+ int idx = p_interval.idx;
+ real_t frac = p_interval.frac;
+
+ Vector3 forward_begin;
+ Vector3 forward_end;
+ if (idx == 0) {
+ forward_begin = (baked_point_cache[1] - baked_point_cache[0]).normalized();
+ forward_end = (baked_point_cache[1] - baked_point_cache[0]).normalized();
+ } else {
+ forward_begin = (baked_point_cache[idx] - baked_point_cache[idx - 1]).normalized();
+ forward_end = (baked_point_cache[idx + 1] - baked_point_cache[idx]).normalized();
}
- int start = 0;
- int end = pc;
- int idx = (end + start) / 2;
- // Binary search to find baked points.
- while (start < idx) {
- real_t offset = baked_dist_cache[idx];
- if (p_offset <= offset) {
- end = idx;
- } else {
- start = idx;
- }
- idx = (end + start) / 2;
+ Vector3 up_begin;
+ Vector3 up_end;
+ if (up_vector_enabled) {
+ const Vector3 *up_ptr = baked_up_vector_cache.ptr();
+ up_begin = up_ptr[idx];
+ up_end = up_ptr[idx + 1];
+ } else {
+ up_begin = Vector3(0.0, 1.0, 0.0);
+ up_end = Vector3(0.0, 1.0, 0.0);
}
- real_t offset_begin = baked_dist_cache[idx];
- real_t offset_end = baked_dist_cache[idx + 1];
+ // Build frames at both ends of the interval, then interpolate.
+ const Basis frame_begin = Basis::looking_at(-forward_begin, up_begin);
+ const Basis frame_end = Basis::looking_at(-forward_end, up_end);
+ const Basis frame = frame_begin.slerp(frame_end, frac).orthonormalized();
- real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, 0, "Couldn't find baked segment.");
+ if (!p_apply_tilt) {
+ return frame;
+ }
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ // Applying tilt.
+ const real_t tilt = _sample_baked_tilt(p_interval);
+ Vector3 forward = frame.get_column(2);
- return Math::lerp(r[idx], r[idx + 1], (real_t)frac);
+ const Basis twist(forward, tilt);
+ return twist * frame;
}
-Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
+Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
if (baked_cache_dirty) {
_bake();
}
- // Validate: Curve may not have baked up vectors.
- int count = baked_up_vector_cache.size();
- ERR_FAIL_COND_V_MSG(count == 0, Vector3(0, 1, 0), "No up vectors in Curve3D.");
+ // Validate: Curve may not have baked points.
+ int pc = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D.");
- if (count == 1) {
- return baked_up_vector_cache.get(0);
+ if (pc == 1) {
+ return baked_point_cache[0];
}
- const Vector3 *r = baked_up_vector_cache.ptr();
- const Vector3 *rp = baked_point_cache.ptr();
- const real_t *rt = baked_tilt_cache.ptr();
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
- int start = 0;
- int end = count;
- int idx = (end + start) / 2;
- // Binary search to find baked points.
- while (start < idx) {
- real_t offset = baked_dist_cache[idx];
- if (p_offset <= offset) {
- end = idx;
- } else {
- start = idx;
- }
- idx = (end + start) / 2;
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_baked(interval, p_cubic);
+}
+
+Transform3D Curve3D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, bool p_apply_tilt) const {
+ if (baked_cache_dirty) {
+ _bake();
}
- if (idx == count - 1) {
- return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx];
+ // Validate: Curve may not have baked points.
+ const int point_count = baked_point_cache.size();
+ ERR_FAIL_COND_V_MSG(point_count == 0, Transform3D(), "No points in Curve3D.");
+
+ if (point_count == 1) {
+ Transform3D t;
+ t.origin = baked_point_cache.get(0);
+ ERR_FAIL_V_MSG(t, "Only 1 point in Curve3D.");
}
- real_t offset_begin = baked_dist_cache[idx];
- real_t offset_end = baked_dist_cache[idx + 1];
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
- real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(0, 1, 0), "Couldn't find baked segment.");
+ // 0. Find interval for all sampling steps.
+ Curve3D::Interval interval = _find_interval(p_offset);
- real_t frac = (p_offset - offset_begin) / idx_interval;
+ // 1. Sample position.
+ Vector3 pos = _sample_baked(interval, p_cubic);
+
+ // 2. Sample rotation frame.
+ Basis frame = _sample_posture(interval, p_apply_tilt);
+
+ return Transform3D(frame, pos);
+}
+
+real_t Curve3D::sample_baked_tilt(real_t p_offset) const {
+ if (baked_cache_dirty) {
+ _bake();
+ }
- Vector3 forward = (rp[idx + 1] - rp[idx]).normalized();
- Vector3 up = r[idx];
- Vector3 up1 = r[idx + 1];
+ // Validate: Curve may not have baked tilts.
+ int pc = baked_tilt_cache.size();
+ ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D.");
- if (p_apply_tilt) {
- up.rotate(forward, rt[idx]);
- up1.rotate(idx + 2 >= count ? forward : (rp[idx + 2] - rp[idx + 1]).normalized(), rt[idx + 1]);
+ if (pc == 1) {
+ return baked_tilt_cache.get(0);
}
- Vector3 axis = up.cross(up1);
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic
- if (axis.length_squared() < CMP_EPSILON2) {
- axis = forward;
- } else {
- axis.normalize();
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_baked_tilt(interval);
+}
+
+Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
+ if (baked_cache_dirty) {
+ _bake();
+ }
+
+ // Validate: Curve may not have baked up vectors.
+ ERR_FAIL_COND_V_MSG(!up_vector_enabled, Vector3(0, 1, 0), "No up vectors in Curve3D.");
+
+ int count = baked_up_vector_cache.size();
+ if (count == 1) {
+ return baked_up_vector_cache.get(0);
}
- return up.rotated(axis, up.angle_to(up1) * frac);
+ p_offset = CLAMP(p_offset, 0.0, get_baked_length()); // PathFollower implement wrapping logic.
+
+ Curve3D::Interval interval = _find_interval(p_offset);
+ return _sample_posture(interval, p_apply_tilt).get_column(1);
}
PackedVector3Array Curve3D::get_baked_points() const {
@@ -2034,6 +2138,7 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve3D::get_baked_length);
ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve3D::sample_baked, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked_with_rotation", "offset", "cubic", "apply_tilt"), &Curve3D::sample_baked_with_rotation, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("sample_baked_up_vector", "offset", "apply_tilt"), &Curve3D::sample_baked_up_vector, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index fa1d35aab1..d0c813f262 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -238,11 +238,6 @@ class Curve3D : public Resource {
Vector<Point> points;
- struct BakedPoint {
- real_t ofs = 0.0;
- Vector3 point;
- };
-
mutable bool baked_cache_dirty = false;
mutable PackedVector3Array baked_point_cache;
mutable Vector<real_t> baked_tilt_cache;
@@ -254,6 +249,15 @@ class Curve3D : public Resource {
void _bake() const;
+ struct Interval {
+ int idx;
+ real_t frac;
+ };
+ Interval _find_interval(real_t p_offset) const;
+ Vector3 _sample_baked(Interval p_interval, bool p_cubic) const;
+ real_t _sample_baked_tilt(Interval p_interval) const;
+ Basis _sample_posture(Interval p_interval, bool p_apply_tilt = false) const;
+
real_t bake_interval = 0.2;
bool up_vector_enabled = true;
@@ -296,9 +300,10 @@ public:
real_t get_baked_length() const;
Vector3 sample_baked(real_t p_offset, bool p_cubic = false) const;
+ Transform3D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false, bool p_apply_tilt = false) const;
real_t sample_baked_tilt(real_t p_offset) const;
Vector3 sample_baked_up_vector(real_t p_offset, bool p_apply_tilt = false) const;
- PackedVector3Array get_baked_points() const; //useful for going through
+ PackedVector3Array get_baked_points() const; // Useful for going through.
Vector<real_t> get_baked_tilts() const; //useful for going through
PackedVector3Array get_baked_up_vectors() const;
Vector3 get_closest_point(const Vector3 &p_to_point) const;
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 185b6f4bdc..84814d939b 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -1396,6 +1396,9 @@ Error FontFile::load_bitmap_font(const String &p_path) {
case 1: /* info */ {
ERR_FAIL_COND_V_MSG(block_size < 15, ERR_CANT_CREATE, RTR("Invalid BMFont info block size."));
base_size = f->get_16();
+ if (base_size <= 0) {
+ base_size = 16;
+ }
uint8_t flags = f->get_8();
if (flags & (1 << 3)) {
st_flags.set_flag(TextServer::FONT_BOLD);
@@ -1681,7 +1684,6 @@ Error FontFile::load_bitmap_font(const String &p_path) {
if (type == "info") {
if (keys.has("size")) {
base_size = keys["size"].to_int();
- set_fixed_size(base_size);
}
if (keys.has("outline")) {
outline = keys["outline"].to_int();
@@ -1730,6 +1732,7 @@ Error FontFile::load_bitmap_font(const String &p_path) {
encoding = 2;
}
}
+ set_fixed_size(base_size);
} else if (type == "common") {
if (keys.has("lineHeight")) {
height = keys["lineHeight"].to_int();
@@ -1788,7 +1791,10 @@ Error FontFile::load_bitmap_font(const String &p_path) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, RTR("Unsupported BMFont texture format."));
}
} else {
- if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline
+ if ((ch[3] == 0) && (ch[0] == 4) && (ch[1] == 4) && (ch[2] == 4) && img->get_format() == Image::FORMAT_RGBA8) { // might be RGBA8 color, no outline (color part of the image should be sold white, but some apps designed for Godot 3 generate color fonts with this config)
+ outline = 0;
+ set_texture_image(0, Vector2i(base_size, 0), page, img);
+ } else if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline
outline = 0;
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, RTR("Unsupported BMFont texture format."));
set_texture_image(0, Vector2i(base_size, 0), page, img);
diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp
index b728c24e0d..cec5569345 100644
--- a/scene/resources/importer_mesh.cpp
+++ b/scene/resources/importer_mesh.cpp
@@ -255,7 +255,7 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma
}
#define VERTEX_SKIN_FUNC(bone_count, vert_idx, read_array, write_array, transform_array, bone_array, weight_array) \
- Vector3 transformed_vert = Vector3(); \
+ Vector3 transformed_vert; \
for (unsigned int weight_idx = 0; weight_idx < bone_count; weight_idx++) { \
int bone_idx = bone_array[vert_idx * bone_count + weight_idx]; \
float w = weight_array[vert_idx * bone_count + weight_idx]; \
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 1c99fa5554..f46faa1013 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -71,7 +71,7 @@ static Array _sanitize_node_pinned_properties(Node *p_node) {
}
Node *SceneState::instantiate(GenEditState p_edit_state) const {
- // nodes where instancing failed (because something is missing)
+ // Nodes where instantiation failed (because something is missing.)
List<Node *> stray_instances;
#define NODE_FROM_ID(p_name, p_id) \
@@ -122,7 +122,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
NODE_FROM_ID(nparent, n.parent);
#ifdef DEBUG_ENABLED
if (!nparent && (n.parent & FLAG_ID_IS_PATH)) {
- WARN_PRINT(String("Parent path '" + String(node_paths[n.parent & FLAG_MASK]) + "' for node '" + String(snames[n.name]) + "' has vanished when instancing: '" + get_path() + "'.").ascii().get_data());
+ WARN_PRINT(String("Parent path '" + String(node_paths[n.parent & FLAG_MASK]) + "' for node '" + String(snames[n.name]) + "' has vanished when instantiating: '" + get_path() + "'.").ascii().get_data());
old_parent_path = String(node_paths[n.parent & FLAG_MASK]).trim_prefix("./").replace("/", "@");
nparent = ret_nodes[0];
}
@@ -131,7 +131,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
} else {
// i == 0 is root node.
ERR_FAIL_COND_V_MSG(n.parent != -1, nullptr, vformat("Invalid scene: root node %s cannot specify a parent node.", snames[n.name]));
- ERR_FAIL_COND_V_MSG(n.type == TYPE_INSTANCED && base_scene_idx < 0, nullptr, vformat("Invalid scene: root node %s in an instance, but there's no base scene.", snames[n.name]));
+ ERR_FAIL_COND_V_MSG(n.type == TYPE_INSTANTIATED && base_scene_idx < 0, nullptr, vformat("Invalid scene: root node %s in an instance, but there's no base scene.", snames[n.name]));
}
Node *node = nullptr;
@@ -169,7 +169,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
ERR_FAIL_COND_V(!node, nullptr);
}
- } else if (n.type == TYPE_INSTANCED) {
+ } else if (n.type == TYPE_INSTANTIATED) {
//get the node from somewhere, it likely already exists from another instance
if (parent) {
node = parent->_get_child_by_name(snames[n.name]);
@@ -345,7 +345,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
node->add_to_group(snames[n.groups[j]], true);
}
- if (n.instance >= 0 || n.type != TYPE_INSTANCED || i == 0) {
+ if (n.instance >= 0 || n.type != TYPE_INSTANTIATED || i == 0) {
//if node was not part of instance, must set its name, parenthood and ownership
if (i > 0) {
if (parent) {
@@ -382,7 +382,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
}
}
- // we only want to deal with pinned flag if instancing as pure main (no instance, no inheriting)
+ // We only want to deal with pinned flag if instantiating as pure main (no instance, no inheriting.)
if (p_edit_state == GEN_EDIT_STATE_MAIN) {
_sanitize_node_pinned_properties(node);
} else {
@@ -665,7 +665,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
// Save the right type. If this node was created by an instance
// then flag that the node should not be created but reused
if (states_stack.is_empty() && !is_editable_instance) {
- //this node is not part of an instancing process, so save the type
+ //This node is not part of an instantiation process, so save the type.
if (missing_node != nullptr) {
// It's a missing node (type non existent on load).
nd.type = _nm_get_string(missing_node->get_original_class(), name_map);
@@ -675,7 +675,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
} else {
// this node is part of an instantiated process, so do not save the type.
// instead, save that it was instantiated
- nd.type = TYPE_INSTANCED;
+ nd.type = TYPE_INSTANTIATED;
}
// determine whether to save this node or not
@@ -1351,7 +1351,7 @@ int SceneState::get_node_count() const {
StringName SceneState::get_node_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, nodes.size(), StringName());
- if (nodes[p_idx].type == TYPE_INSTANCED) {
+ if (nodes[p_idx].type == TYPE_INSTANTIATED) {
return StringName();
}
return names[nodes[p_idx].type];
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index c6f82ddd5e..a30ec54d85 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -108,7 +108,7 @@ protected:
public:
enum {
FLAG_ID_IS_PATH = (1 << 30),
- TYPE_INSTANCED = 0x7FFFFFFF,
+ TYPE_INSTANTIATED = 0x7FFFFFFF,
FLAG_INSTANCE_IS_PLACEHOLDER = (1 << 30),
FLAG_PATH_PROPERTY_IS_NODE = (1 << 30),
FLAG_PROP_NAME_MASK = FLAG_PATH_PROPERTY_IS_NODE - 1,
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index eb83a37c7b..4c6d533c72 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -30,6 +30,7 @@
#include "primitive_meshes.h"
+#include "core/config/project_settings.h"
#include "core/core_string_names.h"
#include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
@@ -37,6 +38,8 @@
#include "thirdparty/misc/clipper.hpp"
#include "thirdparty/misc/polypartition.h"
+#define PADDING_REF_SIZE 1024.0
+
/**
PrimitiveMesh
*/
@@ -94,6 +97,26 @@ void PrimitiveMesh::_update() const {
}
}
+ if (add_uv2) {
+ // _create_mesh_array should populate our UV2, this is a fallback in case it doesn't.
+ // As we don't know anything about the geometry we only pad the right and bottom edge
+ // of our texture.
+ Vector<Vector2> uv = arr[RS::ARRAY_TEX_UV];
+ Vector<Vector2> uv2 = arr[RS::ARRAY_TEX_UV2];
+
+ if (uv.size() > 0 && uv2.size() == 0) {
+ Vector2 uv2_scale = get_uv2_scale();
+ uv2.resize(uv.size());
+
+ Vector2 *uv2w = uv2.ptrw();
+ for (int i = 0; i < uv.size(); i++) {
+ uv2w[i] = uv[i] * uv2_scale;
+ }
+ }
+
+ arr[RS::ARRAY_TEX_UV2] = uv2;
+ }
+
array_len = pc;
index_array_len = indices.size();
// in with the new
@@ -160,7 +183,12 @@ TypedArray<Array> PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) c
uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, 0);
- return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
+ uint32_t mesh_format = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
+ if (add_uv2) {
+ mesh_format |= RS::ARRAY_FORMAT_TEX_UV2;
+ }
+
+ return mesh_format;
}
Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
@@ -219,9 +247,17 @@ void PrimitiveMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
+ ClassDB::bind_method(D_METHOD("set_add_uv2", "add_uv2"), &PrimitiveMesh::set_add_uv2);
+ ClassDB::bind_method(D_METHOD("get_add_uv2"), &PrimitiveMesh::get_add_uv2);
+
+ ClassDB::bind_method(D_METHOD("set_uv2_padding", "uv2_padding"), &PrimitiveMesh::set_uv2_padding);
+ ClassDB::bind_method(D_METHOD("get_uv2_padding"), &PrimitiveMesh::get_uv2_padding);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "add_uv2"), "set_add_uv2", "get_add_uv2");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv2_padding"), "set_uv2_padding", "get_uv2_padding");
GDVIRTUAL_BIND(_create_mesh_array);
}
@@ -233,7 +269,7 @@ void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
notify_property_list_changed();
emit_changed();
- };
+ }
}
Ref<Material> PrimitiveMesh::get_material() const {
@@ -263,6 +299,42 @@ bool PrimitiveMesh::get_flip_faces() const {
return flip_faces;
}
+void PrimitiveMesh::set_add_uv2(bool p_enable) {
+ add_uv2 = p_enable;
+ _update_lightmap_size();
+ _request_update();
+}
+
+void PrimitiveMesh::set_uv2_padding(float p_padding) {
+ uv2_padding = p_padding;
+ _update_lightmap_size();
+ _request_update();
+}
+
+Vector2 PrimitiveMesh::get_uv2_scale(Vector2 p_margin_scale) const {
+ Vector2 uv2_scale;
+ Vector2 lightmap_size = get_lightmap_size_hint();
+
+ // Calculate it as a margin, if no lightmap size hint is given we assume "PADDING_REF_SIZE" as our texture size.
+ uv2_scale.x = p_margin_scale.x * uv2_padding / (lightmap_size.x == 0.0 ? PADDING_REF_SIZE : lightmap_size.x);
+ uv2_scale.y = p_margin_scale.y * uv2_padding / (lightmap_size.y == 0.0 ? PADDING_REF_SIZE : lightmap_size.y);
+
+ // Inverse it to turn our margin into a scale
+ uv2_scale = Vector2(1.0, 1.0) - uv2_scale;
+
+ return uv2_scale;
+}
+
+float PrimitiveMesh::get_lightmap_texel_size() const {
+ float texel_size = GLOBAL_GET("rendering/lightmapping/primitive_meshes/texel_size");
+
+ if (texel_size <= 0.0) {
+ texel_size = 0.2;
+ }
+
+ return texel_size;
+}
+
PrimitiveMesh::PrimitiveMesh() {
mesh = RenderingServer::get_singleton()->mesh_create();
}
@@ -275,22 +347,52 @@ PrimitiveMesh::~PrimitiveMesh() {
CapsuleMesh
*/
+void CapsuleMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
+ float vertical_length = radial_length * 2 + (height - 2.0 * radius); // total vertical length
+
+ _lightmap_size_hint.x = MAX(1.0, 4.0 * radial_length / texel_size) + padding;
+ _lightmap_size_hint.y = MAX(1.0, vertical_length / texel_size) + padding;
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
- create_mesh_array(p_arr, radius, height, radial_segments, rings);
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ create_mesh_array(p_arr, radius, height, radial_segments, rings, _add_uv2, _uv2_padding);
}
-void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings) {
+void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
float x, y, z, u, v, w;
float onethird = 1.0 / 3.0;
float twothirds = 2.0 / 3.0;
+ // Only used if we calculate UV2
+ float radial_width = 2.0 * radius * Math_PI;
+ float radial_h = radial_width / (radial_width + p_uv2_padding);
+ float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
+ float vertical_length = radial_length * 2 + (height - 2.0 * radius) + p_uv2_padding; // total vertical length
+ float radial_v = radial_length / vertical_length; // v size of top and bottom section
+ float height_v = (height - 2.0 * radius) / vertical_length; // v size of height section
+
// note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
Vector<Vector3> points;
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -322,6 +424,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
normals.push_back(p.normalized());
ADD_TANGENT(-z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v * onethird));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u * radial_h, v * radial_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -332,12 +437,12 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
/* cylinder */
thisrow = point;
@@ -361,6 +466,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
normals.push_back(Vector3(x, 0.0, -z));
ADD_TANGENT(-z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, onethird + (v * onethird)));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u * radial_h, radial_v + (v * height_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -371,12 +479,12 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
/* bottom hemisphere */
thisrow = point;
@@ -390,17 +498,20 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
y = radius * cos(0.5 * Math_PI * v);
for (i = 0; i <= radial_segments; i++) {
- float u2 = i;
- u2 /= radial_segments;
+ u = i;
+ u /= radial_segments;
- x = -sin(u2 * Math_TAU);
- z = cos(u2 * Math_TAU);
+ x = -sin(u * Math_TAU);
+ z = cos(u * Math_TAU);
Vector3 p = Vector3(x * radius * w, y, -z * radius * w);
points.push_back(p + Vector3(0.0, -0.5 * height + radius, 0.0));
normals.push_back(p.normalized());
ADD_TANGENT(-z, 0.0, -x, 1.0)
- uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird)));
+ uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u * radial_h, radial_v + height_v + ((v - 1.0) * radial_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -411,17 +522,20 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
p_arr[RS::ARRAY_TANGENT] = tangents;
p_arr[RS::ARRAY_TEX_UV] = uvs;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -450,6 +564,7 @@ void CapsuleMesh::set_radius(const float p_radius) {
if (radius > height * 0.5) {
height = radius * 2.0;
}
+ _update_lightmap_size();
_request_update();
}
@@ -462,6 +577,7 @@ void CapsuleMesh::set_height(const float p_height) {
if (radius > height * 0.5) {
radius = height * 0.5;
}
+ _update_lightmap_size();
_request_update();
}
@@ -493,16 +609,53 @@ CapsuleMesh::CapsuleMesh() {}
BoxMesh
*/
+void BoxMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float width = (size.x + size.z) / texel_size;
+ float length = (size.y + size.y + MAX(size.x, size.z)) / texel_size;
+
+ _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
+ _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void BoxMesh::_create_mesh_array(Array &p_arr) const {
- BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d);
+ // Note about padding, with our box each face of the box faces a different direction so we want a seam
+ // around every face. We thus add our padding to the right and bottom of each face.
+ // With 3 faces along the width and 2 along the height of the texture we need to adjust our scale
+ // accordingly.
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d, _add_uv2, _uv2_padding);
}
-void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d) {
+void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
float x, y, z;
float onethird = 1.0 / 3.0;
float twothirds = 2.0 / 3.0;
+ // Only used if we calculate UV2
+ // TODO this could be improved by changing the order depending on which side is the longest (basically the below works best if size.y is the longest)
+ float total_h = (size.x + size.z + (2.0 * p_uv2_padding));
+ float padding_h = p_uv2_padding / total_h;
+ float width_h = size.x / total_h;
+ float depth_h = size.z / total_h;
+ float total_v = (size.y + size.y + MAX(size.x, size.z) + (3.0 * p_uv2_padding));
+ float padding_v = p_uv2_padding / total_v;
+ float width_v = size.x / total_v;
+ float height_v = size.y / total_v;
+ float depth_v = size.z / total_v;
+
Vector3 start_pos = size * -0.5;
// set our bounding box
@@ -511,6 +664,7 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -525,18 +679,24 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
thisrow = point;
prevrow = 0;
for (j = 0; j <= subdivide_h + 1; j++) {
+ float v = j;
+ float v2 = v / (subdivide_w + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
x = start_pos.x;
for (i = 0; i <= subdivide_w + 1; i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
// front
points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, v2 * height_v));
+ }
point++;
// back
@@ -544,6 +704,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
normals.push_back(Vector3(0.0, 0.0, -1.0));
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, height_v + padding_v + (v2 * height_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -564,33 +727,39 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
// left + right
y = start_pos.y;
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_h + 1); j++) {
+ float v = j;
+ float v2 = v / (subdivide_h + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
z = start_pos.z;
for (i = 0; i <= (subdivide_d + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_d + 1.0);
u /= (3.0 * (subdivide_d + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
// right
points.push_back(Vector3(-start_pos.x, -y, -z));
normals.push_back(Vector3(1.0, 0.0, 0.0));
ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
uvs.push_back(Vector2(onethird + u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), v2 * height_v));
+ }
point++;
// left
@@ -598,6 +767,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
normals.push_back(Vector3(-1.0, 0.0, 0.0));
ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
uvs.push_back(Vector2(u, 0.5 + v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), height_v + padding_v + (v2 * height_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -618,33 +790,39 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
z += size.z / (subdivide_d + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
// top + bottom
z = start_pos.z;
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_d + 1); j++) {
+ float v = j;
+ float v2 = v / (subdivide_d + 1.0);
+ v /= (2.0 * (subdivide_d + 1.0));
+
x = start_pos.x;
for (i = 0; i <= (subdivide_w + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_d + 1.0));
// top
points.push_back(Vector3(-x, -start_pos.y, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(onethird + u, 0.5 + v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, ((height_v + padding_v) * 2.0) + (v2 * depth_v)));
+ }
point++;
// bottom
@@ -652,6 +830,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), ((height_v + padding_v) * 2.0) + (v2 * width_v)));
+ }
point++;
if (i > 0 && j > 0) {
@@ -672,20 +853,23 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
z += size.z / (subdivide_d + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
p_arr[RS::ARRAY_TANGENT] = tangents;
p_arr[RS::ARRAY_TEX_UV] = uvs;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -708,6 +892,7 @@ void BoxMesh::_bind_methods() {
void BoxMesh::set_size(const Vector3 &p_size) {
size = p_size;
+ _update_lightmap_size();
_request_update();
}
@@ -748,18 +933,58 @@ BoxMesh::BoxMesh() {}
CylinderMesh
*/
+void CylinderMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float top_circumference = top_radius * Math_PI * 2.0;
+ float bottom_circumference = bottom_radius * Math_PI * 2.0;
+
+ float _width = MAX(top_circumference, bottom_circumference) / texel_size + padding;
+ _width = MAX(_width, (((top_radius + bottom_radius) / texel_size) + padding) * 2.0); // this is extremely unlikely to be larger, will only happen if padding is larger then our diameter.
+ _lightmap_size_hint.x = MAX(1.0, _width);
+
+ float _height = ((height + (MAX(top_radius, bottom_radius) * 2.0)) / texel_size) + (2.0 * padding);
+
+ _lightmap_size_hint.y = MAX(1.0, _height);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void CylinderMesh::_create_mesh_array(Array &p_arr) const {
- create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom);
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom, _add_uv2, _uv2_padding);
}
-void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom) {
+void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
- float x, y, z, u, v, radius;
+ float x, y, z, u, v, radius, radius_h;
+
+ // Only used if we calculate UV2
+ float top_circumference = top_radius * Math_PI * 2.0;
+ float bottom_circumference = bottom_radius * Math_PI * 2.0;
+ float vertical_length = height + MAX(2.0 * top_radius, 2.0 * bottom_radius) + (2.0 * p_uv2_padding);
+ float height_v = height / vertical_length;
+ float padding_v = p_uv2_padding / vertical_length;
+
+ float horizonal_length = MAX(MAX(2.0 * (top_radius + bottom_radius + p_uv2_padding), top_circumference + p_uv2_padding), bottom_circumference + p_uv2_padding);
+ float center_h = 0.5 * (horizonal_length - p_uv2_padding) / horizonal_length;
+ float top_h = top_circumference / horizonal_length;
+ float bottom_h = bottom_circumference / horizonal_length;
+ float padding_h = p_uv2_padding / horizonal_length;
Vector<Vector3> points;
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -777,6 +1002,7 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
v /= (rings + 1);
radius = top_radius + ((bottom_radius - top_radius) * v);
+ radius_h = top_h + ((bottom_h - top_h) * v);
y = height * v;
y = (height * 0.5) - y;
@@ -793,6 +1019,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(x, side_normal_y, z).normalized());
ADD_TANGENT(z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v * 0.5));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(center_h + (u - 0.5) * radius_h, v * height_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -803,14 +1032,20 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
- // add top
+ // Adjust for bottom section, only used if we calculate UV2s.
+ top_h = top_radius / horizonal_length;
+ float top_v = top_radius / vertical_length;
+ bottom_h = bottom_radius / horizonal_length;
+ float bottom_v = bottom_radius / vertical_length;
+
+ // Add top.
if (cap_top && top_radius > 0.0) {
y = height * 0.5;
@@ -819,6 +1054,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.25, 0.75));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h, height_v + padding_v + MAX(top_v, bottom_v)));
+ }
point++;
for (i = 0; i <= radial_segments; i++) {
@@ -836,17 +1074,20 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h + (x * top_h), height_v + padding_v + MAX(top_v, bottom_v) + (z * top_v)));
+ }
point++;
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 1);
indices.push_back(point - 2);
- };
- };
- };
+ }
+ }
+ }
- // add bottom
+ // Add bottom.
if (cap_bottom && bottom_radius > 0.0) {
y = height * -0.5;
@@ -855,6 +1096,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.75, 0.75));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h, height_v + padding_v + MAX(top_v, bottom_v)));
+ }
point++;
for (i = 0; i <= radial_segments; i++) {
@@ -872,20 +1116,26 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h + (x * bottom_h), height_v + padding_v + MAX(top_v, bottom_v) - (z * bottom_v)));
+ }
point++;
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 2);
indices.push_back(point - 1);
- };
- };
- };
+ }
+ }
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
p_arr[RS::ARRAY_TANGENT] = tangents;
p_arr[RS::ARRAY_TEX_UV] = uvs;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -919,6 +1169,7 @@ void CylinderMesh::_bind_methods() {
void CylinderMesh::set_top_radius(const float p_radius) {
top_radius = p_radius;
+ _update_lightmap_size();
_request_update();
}
@@ -928,6 +1179,7 @@ float CylinderMesh::get_top_radius() const {
void CylinderMesh::set_bottom_radius(const float p_radius) {
bottom_radius = p_radius;
+ _update_lightmap_size();
_request_update();
}
@@ -937,6 +1189,7 @@ float CylinderMesh::get_bottom_radius() const {
void CylinderMesh::set_height(const float p_height) {
height = p_height;
+ _update_lightmap_size();
_request_update();
}
@@ -986,10 +1239,26 @@ CylinderMesh::CylinderMesh() {}
PlaneMesh
*/
+void PlaneMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ _lightmap_size_hint.x = MAX(1.0, (size.x / texel_size) + padding);
+ _lightmap_size_hint.y = MAX(1.0, (size.y / texel_size) + padding);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void PlaneMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, z;
+ // Plane mesh can use default UV2 calculation as implemented in Primitive Mesh
+
Size2 start_pos = size * -0.5;
Vector3 normal = Vector3(0.0, 1.0, 0.0);
@@ -1043,15 +1312,15 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
z += size.y / (subdivide_d + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
@@ -1088,6 +1357,7 @@ void PlaneMesh::_bind_methods() {
void PlaneMesh::set_size(const Size2 &p_size) {
size = p_size;
+ _update_lightmap_size();
_request_update();
}
@@ -1137,12 +1407,49 @@ PlaneMesh::PlaneMesh() {}
PrismMesh
*/
+void PrismMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ // left_to_right does not effect the surface area of the prism so we ignore that.
+ // TODO we could combine the two triangles and save some space but we need to re-align the uv1 and adjust the tangent.
+
+ float width = (size.x + size.z) / texel_size;
+ float length = (size.y + size.y + size.z) / texel_size;
+
+ _lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
+ _lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void PrismMesh::_create_mesh_array(Array &p_arr) const {
int i, j, prevrow, thisrow, point;
float x, y, z;
float onethird = 1.0 / 3.0;
float twothirds = 2.0 / 3.0;
+ // Only used if we calculate UV2
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ float horizontal_total = size.x + size.z + 2.0 * _uv2_padding;
+ float width_h = size.x / horizontal_total;
+ float depth_h = size.z / horizontal_total;
+ float padding_h = _uv2_padding / horizontal_total;
+
+ float vertical_total = (size.y + size.y + size.z) + (3.0 * _uv2_padding);
+ float height_v = size.y / vertical_total;
+ float depth_v = size.z / vertical_total;
+ float padding_v = _uv2_padding / vertical_total;
+
+ // and start building
+
Vector3 start_pos = size * -0.5;
// set our bounding box
@@ -1151,6 +1458,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -1171,12 +1479,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
float offset_front = (1.0 - scale) * onethird * left_to_right;
float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right);
+ float v = j;
+ float v2 = j / (subdivide_h + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
x = 0.0;
for (i = 0; i <= (subdivide_w + 1); i++) {
float u = i;
- float v = j;
+ float u2 = i / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
u *= scale;
@@ -1185,6 +1496,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
normals.push_back(Vector3(0.0, 0.0, 1.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(offset_front + u, v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(u2 * scale * width_h, v2 * height_v));
+ }
point++;
/* back */
@@ -1192,6 +1506,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
normals.push_back(Vector3(0.0, 0.0, -1.0));
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + offset_back + u, v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(u2 * scale * width_h, height_v + padding_v + v2 * height_v));
+ }
point++;
if (i > 0 && j == 1) {
@@ -1224,15 +1541,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
x += scale * size.x / (subdivide_w + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
/* left + right */
Vector3 normal_left, normal_right;
@@ -1246,6 +1563,10 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_h + 1); j++) {
+ float v = j;
+ float v2 = j / (subdivide_h + 1.0);
+ v /= (2.0 * (subdivide_h + 1.0));
+
float left, right;
float scale = (y - start_pos.y) / size.y;
@@ -1255,15 +1576,17 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
z = start_pos.z;
for (i = 0; i <= (subdivide_d + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_d + 1.0);
u /= (3.0 * (subdivide_d + 1.0));
- v /= (2.0 * (subdivide_h + 1.0));
/* right */
points.push_back(Vector3(right, -y, -z));
normals.push_back(normal_right);
ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
uvs.push_back(Vector2(onethird + u, v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, v2 * height_v));
+ }
point++;
/* left */
@@ -1271,6 +1594,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
normals.push_back(normal_left);
ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
uvs.push_back(Vector2(u, 0.5 + v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, height_v + padding_v + v2 * height_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -1291,33 +1617,39 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i2 + 1);
indices.push_back(thisrow + i2 + 1);
indices.push_back(thisrow + i2 - 1);
- };
+ }
z += size.z / (subdivide_d + 1.0);
- };
+ }
y += size.y / (subdivide_h + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
/* bottom */
z = start_pos.z;
thisrow = point;
prevrow = 0;
for (j = 0; j <= (subdivide_d + 1); j++) {
+ float v = j;
+ float v2 = v / (subdivide_d + 1.0);
+ v /= (2.0 * (subdivide_d + 1.0));
+
x = start_pos.x;
for (i = 0; i <= (subdivide_w + 1); i++) {
float u = i;
- float v = j;
+ float u2 = u / (subdivide_w + 1.0);
u /= (3.0 * (subdivide_w + 1.0));
- v /= (2.0 * (subdivide_d + 1.0));
/* bottom */
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(u2 * width_h, 2.0 * (height_v + padding_v) + v2 * depth_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -1328,20 +1660,23 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
+ }
x += size.x / (subdivide_w + 1.0);
- };
+ }
z += size.z / (subdivide_d + 1.0);
prevrow = thisrow;
thisrow = point;
- };
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
p_arr[RS::ARRAY_TANGENT] = tangents;
p_arr[RS::ARRAY_TEX_UV] = uvs;
+ if (_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -1377,6 +1712,7 @@ float PrismMesh::get_left_to_right() const {
void PrismMesh::set_size(const Vector3 &p_size) {
size = p_size;
+ _update_lightmap_size();
_request_update();
}
@@ -1417,22 +1753,50 @@ PrismMesh::PrismMesh() {}
SphereMesh
*/
+void SphereMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float _width = radius * Math_TAU;
+ _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
+ float _height = (is_hemisphere ? 1.0 : 0.5) * height * Math_PI; // note, with hemisphere height is our radius, while with a full sphere it is the diameter..
+ _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void SphereMesh::_create_mesh_array(Array &p_arr) const {
- create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere);
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere, _add_uv2, _uv2_padding);
}
-void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) {
+void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere, bool p_add_uv2, const float p_uv2_padding) {
int i, j, prevrow, thisrow, point;
float x, y, z;
float scale = height * (is_hemisphere ? 1.0 : 0.5);
+ // Only used if we calculate UV2
+ float circumference = radius * Math_TAU;
+ float horizontal_length = circumference + p_uv2_padding;
+ float center_h = 0.5 * circumference / horizontal_length;
+
+ float height_v = scale * Math_PI / ((scale * Math_PI) + p_uv2_padding);
+
// set our bounding box
Vector<Vector3> points;
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
point = 0;
@@ -1467,9 +1831,13 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int
points.push_back(p);
Vector3 normal = Vector3(x * w * scale, radius * (y / scale), z * w * scale);
normals.push_back(normal.normalized());
- };
+ }
ADD_TANGENT(z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v));
+ if (p_add_uv2) {
+ float w_h = w * 2.0 * center_h;
+ uv2s.push_back(Vector2(center_h + ((u - 0.5) * w_h), v * height_v));
+ }
point++;
if (i > 0 && j > 0) {
@@ -1480,17 +1848,20 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int
indices.push_back(prevrow + i);
indices.push_back(thisrow + i);
indices.push_back(thisrow + i - 1);
- };
- };
+ }
+ }
prevrow = thisrow;
thisrow = point;
- };
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
p_arr[RS::ARRAY_TANGENT] = tangents;
p_arr[RS::ARRAY_TEX_UV] = uvs;
+ if (p_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -1517,6 +1888,7 @@ void SphereMesh::_bind_methods() {
void SphereMesh::set_radius(const float p_radius) {
radius = p_radius;
+ _update_lightmap_size();
_request_update();
}
@@ -1526,6 +1898,7 @@ float SphereMesh::get_radius() const {
void SphereMesh::set_height(const float p_height) {
height = p_height;
+ _update_lightmap_size();
_request_update();
}
@@ -1553,6 +1926,7 @@ int SphereMesh::get_rings() const {
void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
is_hemisphere = p_is_hemisphere;
+ _update_lightmap_size();
_request_update();
}
@@ -1566,6 +1940,31 @@ SphereMesh::SphereMesh() {}
TorusMesh
*/
+void TorusMesh::_update_lightmap_size() {
+ if (get_add_uv2()) {
+ // size must have changed, update lightmap size hint
+ Size2i _lightmap_size_hint;
+ float texel_size = get_lightmap_texel_size();
+ float padding = get_uv2_padding();
+
+ float min_radius = inner_radius;
+ float max_radius = outer_radius;
+
+ if (min_radius > max_radius) {
+ SWAP(min_radius, max_radius);
+ }
+
+ float radius = (max_radius - min_radius) * 0.5;
+
+ float _width = max_radius * Math_TAU;
+ _lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
+ float _height = radius * Math_TAU;
+ _lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
+
+ set_lightmap_size_hint(_lightmap_size_hint);
+ }
+}
+
void TorusMesh::_create_mesh_array(Array &p_arr) const {
// set our bounding box
@@ -1573,6 +1972,7 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
Vector<Vector3> normals;
Vector<float> tangents;
Vector<Vector2> uvs;
+ Vector<Vector2> uv2s;
Vector<int> indices;
#define ADD_TANGENT(m_x, m_y, m_z, m_d) \
@@ -1592,6 +1992,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
float radius = (max_radius - min_radius) * 0.5;
+ // Only used if we calculate UV2
+ bool _add_uv2 = get_add_uv2();
+ float texel_size = get_lightmap_texel_size();
+ float _uv2_padding = get_uv2_padding() * texel_size;
+
+ float horizontal_total = max_radius * Math_TAU + _uv2_padding;
+ float max_h = max_radius * Math_TAU / horizontal_total;
+ float delta_h = (max_radius - min_radius) * Math_TAU / horizontal_total;
+
+ float height_v = radius * Math_TAU / (radius * Math_TAU + _uv2_padding);
+
for (int i = 0; i <= rings; i++) {
int prevrow = (i - 1) * (ring_segments + 1);
int thisrow = i * (ring_segments + 1);
@@ -1607,10 +2018,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj));
Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0);
+ float offset_h = 0.5 * (1.0 - normalj.x) * delta_h;
+ float adj_h = max_h - offset_h;
+ offset_h *= 0.5;
+
points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x));
normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x));
ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0);
uvs.push_back(Vector2(inci, incj));
+ if (_add_uv2) {
+ uv2s.push_back(Vector2(offset_h + inci * adj_h, incj * height_v));
+ }
if (i > 0 && j > 0) {
indices.push_back(thisrow + j - 1);
@@ -1628,6 +2046,9 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
p_arr[RS::ARRAY_NORMAL] = normals;
p_arr[RS::ARRAY_TANGENT] = tangents;
p_arr[RS::ARRAY_TEX_UV] = uvs;
+ if (_add_uv2) {
+ p_arr[RS::ARRAY_TEX_UV2] = uv2s;
+ }
p_arr[RS::ARRAY_INDEX] = indices;
}
@@ -1785,6 +2206,8 @@ Transform3D TubeTrailMesh::get_builtin_bind_pose(int p_index) const {
}
void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
+ // Seeing use case for TubeTrailMesh, no need to do anything more then default UV2 calculation
+
PackedVector3Array points;
PackedVector3Array normals;
PackedFloat32Array tangents;
@@ -1920,9 +2343,9 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(thisrow);
indices.push_back(point - 1);
indices.push_back(point - 2);
- };
- };
- };
+ }
+ }
+ }
float scale_neg = 1.0;
if (curve.is_valid() && curve->get_point_count() > 0) {
@@ -1983,9 +2406,9 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
indices.push_back(thisrow);
indices.push_back(point - 2);
indices.push_back(point - 1);
- };
- };
- };
+ }
+ }
+ }
p_arr[RS::ARRAY_VERTEX] = points;
p_arr[RS::ARRAY_NORMAL] = normals;
@@ -2109,6 +2532,8 @@ Transform3D RibbonTrailMesh::get_builtin_bind_pose(int p_index) const {
}
void RibbonTrailMesh::_create_mesh_array(Array &p_arr) const {
+ // Seeing use case of ribbon trail mesh, no need to implement special UV2 calculation
+
PackedVector3Array points;
PackedVector3Array normals;
PackedFloat32Array tangents;
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index ee61f0ac55..06f9781b84 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -56,6 +56,9 @@ private:
Ref<Material> material;
bool flip_faces = false;
+ bool add_uv2 = false;
+ float uv2_padding = 2.0;
+
// make sure we do an update after we've finished constructing our object
mutable bool pending_request = true;
void _update() const;
@@ -70,6 +73,10 @@ protected:
void _request_update();
GDVIRTUAL0RC(Array, _create_mesh_array)
+ Vector2 get_uv2_scale(Vector2 p_margin_scale = Vector2(1.0, 1.0)) const;
+ float get_lightmap_texel_size() const;
+ virtual void _update_lightmap_size(){};
+
public:
virtual int get_surface_count() const override;
virtual int surface_get_array_len(int p_idx) const override;
@@ -98,6 +105,12 @@ public:
void set_flip_faces(bool p_enable);
bool get_flip_faces() const;
+ void set_add_uv2(bool p_enable);
+ bool get_add_uv2() const { return add_uv2; }
+
+ void set_uv2_padding(float p_padding);
+ float get_uv2_padding() const { return uv2_padding; }
+
PrimitiveMesh();
~PrimitiveMesh();
};
@@ -118,8 +131,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8);
+ static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_radius(const float p_radius);
float get_radius() const;
@@ -152,8 +167,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0);
+ static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_size(const Vector3 &p_size);
Vector3 get_size() const;
@@ -190,8 +207,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true);
+ static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_top_radius(const float p_radius);
float get_top_radius() const;
@@ -241,6 +260,8 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
void set_size(const Size2 &p_size);
Size2 get_size() const;
@@ -292,6 +313,8 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
void set_left_to_right(const float p_left_to_right);
float get_left_to_right() const;
@@ -328,8 +351,10 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
- static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false);
+ static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
void set_radius(const float p_radius);
float get_radius() const;
@@ -365,6 +390,8 @@ protected:
static void _bind_methods();
virtual void _create_mesh_array(Array &p_arr) const override;
+ virtual void _update_lightmap_size() override;
+
public:
void set_inner_radius(const float p_inner_radius);
float get_inner_radius() const;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 85b538b1d9..8b2b7e118c 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -217,7 +217,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars
if (next_tag.fields.has("type")) {
type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
} else {
- type = SceneState::TYPE_INSTANCED; //no type? assume this was instantiated
+ type = SceneState::TYPE_INSTANTIATED; //no type? assume this was instantiated
}
HashSet<StringName> path_properties;
@@ -256,7 +256,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars
if (next_tag.fields.has("owner")) {
owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
} else {
- if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1)) {
+ if (parent != -1 && !(type == SceneState::TYPE_INSTANTIATED && instance == -1)) {
owner = 0; //if no owner, owner is root
}
}
@@ -511,6 +511,7 @@ Error ResourceLoaderText::load() {
if (error) {
_printerr();
+ return error;
}
resource_current++;
@@ -600,9 +601,13 @@ Error ResourceLoaderText::load() {
resource_current++;
int_resources[id] = res; //always assign int resources
- if (do_assign && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
- res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
- res->set_scene_unique_id(id);
+ if (do_assign) {
+ if (cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE) {
+ res->set_path(path);
+ } else {
+ res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
+ res->set_scene_unique_id(id);
+ }
}
Dictionary missing_resource_properties;
@@ -884,6 +889,7 @@ void ResourceLoaderText::get_dependencies(Ref<FileAccess> p_f, List<String> *p_d
error_text = "Unexpected end of file";
_printerr();
error = ERR_FILE_CORRUPT;
+ return;
}
}
}
diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp
index af84144591..413670d23e 100644
--- a/scene/resources/shape_2d.cpp
+++ b/scene/resources/shape_2d.cpp
@@ -124,5 +124,7 @@ Shape2D::Shape2D(const RID &p_rid) {
}
Shape2D::~Shape2D() {
- PhysicsServer2D::get_singleton()->free(shape);
+ if (PhysicsServer2D::get_singleton() != nullptr) {
+ PhysicsServer2D::get_singleton()->free(shape);
+ }
}
diff --git a/scene/resources/shape_3d.cpp b/scene/resources/shape_3d.cpp
index 4423c1d7bb..44f21d2a48 100644
--- a/scene/resources/shape_3d.cpp
+++ b/scene/resources/shape_3d.cpp
@@ -128,5 +128,7 @@ Shape3D::Shape3D(RID p_shape) :
shape(p_shape) {}
Shape3D::~Shape3D() {
- PhysicsServer3D::get_singleton()->free(shape);
+ if (PhysicsServer3D::get_singleton() != nullptr) {
+ PhysicsServer3D::get_singleton()->free(shape);
+ }
}
diff --git a/scene/resources/skeleton_modification_2d_fabrik.h b/scene/resources/skeleton_modification_2d_fabrik.h
index 4a875d039f..0ca6582965 100644
--- a/scene/resources/skeleton_modification_2d_fabrik.h
+++ b/scene/resources/skeleton_modification_2d_fabrik.h
@@ -68,8 +68,8 @@ private:
float chain_tolarance = 0.01;
int chain_max_iterations = 10;
int chain_iterations = 0;
- Transform2D target_global_pose = Transform2D();
- Transform2D origin_global_pose = Transform2D();
+ Transform2D target_global_pose;
+ Transform2D origin_global_pose;
void fabrik_joint_update_bone2d_cache(int p_joint_idx);
void chain_backwards();
diff --git a/scene/resources/skeleton_modification_3d_fabrik.h b/scene/resources/skeleton_modification_3d_fabrik.h
index e2e490d636..3e3aa5e587 100644
--- a/scene/resources/skeleton_modification_3d_fabrik.h
+++ b/scene/resources/skeleton_modification_3d_fabrik.h
@@ -47,7 +47,7 @@ private:
bool auto_calculate_length = true;
bool use_tip_node = false;
- NodePath tip_node = NodePath();
+ NodePath tip_node;
ObjectID tip_node_cache;
bool use_target_basis = false;
@@ -68,8 +68,8 @@ private:
void update_joint_tip_cache(int p_joint_idx);
int final_joint_idx = 0;
- Transform3D target_global_pose = Transform3D();
- Transform3D origin_global_pose = Transform3D();
+ Transform3D target_global_pose;
+ Transform3D origin_global_pose;
void chain_backwards();
void chain_forwards();
diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp
index f1eddd8ffc..cb5cb4ef96 100644
--- a/scene/resources/syntax_highlighter.cpp
+++ b/scene/resources/syntax_highlighter.cpp
@@ -336,7 +336,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) {
}
String word = str.substr(j, to - j);
- Color col = Color();
+ Color col;
if (keywords.has(word)) {
col = keywords[word];
} else if (member_keywords.has(word)) {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index a6fb359051..b5754caa6a 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -64,6 +64,7 @@ bool Texture2D::is_pixel_opaque(int p_x, int p_y) const {
GDVIRTUAL_CALL(_is_pixel_opaque, p_x, p_y, ret);
return ret;
}
+
bool Texture2D::has_alpha() const {
bool ret = true;
GDVIRTUAL_CALL(_has_alpha, ret);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 3caf6484d9..d4ad81614d 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -3789,7 +3789,7 @@ Vector2i TileSetAtlasSource::get_atlas_grid_size() const {
Size2i valid_area = txt->get_size() - margins;
// Compute the number of valid tiles in the tiles atlas
- Size2i grid_size = Size2i();
+ Size2i grid_size;
if (valid_area.x >= texture_region_size.x && valid_area.y >= texture_region_size.y) {
valid_area -= texture_region_size;
grid_size = Size2i(1, 1) + valid_area / (texture_region_size + separation);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 8f175e99a6..9f465a17e9 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -785,7 +785,7 @@ private:
bool flip_h = false;
bool flip_v = false;
bool transpose = false;
- Vector2i tex_offset = Vector2i();
+ Vector2i tex_offset;
Ref<Material> material = Ref<Material>();
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
int z_index = 0;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 04637983b5..03abac1b3e 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -3108,9 +3108,9 @@ void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_fun
return;
}
if (p_func == FUNC_PANNING) {
- set_input_port_default_value(2, Vector2()); // offset
+ set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); // offset
} else { // FUNC_SCALING
- set_input_port_default_value(2, Vector2(0.5, 0.5)); // pivot
+ set_input_port_default_value(2, Vector2(0.5, 0.5), get_input_port_default_value(2)); // pivot
}
func = p_func;
emit_changed();
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index a15c03d675..bc7918c662 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -206,8 +206,6 @@ SceneStringNames::SceneStringNames() {
theme_changed = StaticCString::create("theme_changed");
parameters_base_path = "parameters/";
- tracks_changed = "tracks_changed";
-
shader_overrides_group = StaticCString::create("_shader_overrides_group_");
shader_overrides_group_active = StaticCString::create("_shader_overrides_group_active_");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 5589ab327f..7ff866cacd 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -209,8 +209,6 @@ public:
StringName parameters_base_path;
- StringName tracks_changed;
-
StringName _window_group;
StringName _window_input;
StringName _window_unhandled_input;
diff --git a/servers/navigation/navigation_utilities.h b/servers/navigation/navigation_utilities.h
index bedcc16a67..e99c139528 100644
--- a/servers/navigation/navigation_utilities.h
+++ b/servers/navigation/navigation_utilities.h
@@ -48,8 +48,8 @@ struct PathQueryParameters {
PathfindingAlgorithm pathfinding_algorithm = PATHFINDING_ALGORITHM_ASTAR;
PathPostProcessing path_postprocessing = PATH_POSTPROCESSING_CORRIDORFUNNEL;
RID map;
- Vector3 start_position = Vector3();
- Vector3 target_position = Vector3();
+ Vector3 start_position;
+ Vector3 target_position;
uint32_t navigation_layers = 1;
};
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 77110c5fbc..31b6b9e12f 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -1011,7 +1011,6 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) {
} break;
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
- gravity = Vector3(0, 0, 0);
gravity = area_gravity;
gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
} break;
diff --git a/servers/rendering/dummy/storage/mesh_storage.cpp b/servers/rendering/dummy/storage/mesh_storage.cpp
index adf736eee3..52de998835 100644
--- a/servers/rendering/dummy/storage/mesh_storage.cpp
+++ b/servers/rendering/dummy/storage/mesh_storage.cpp
@@ -56,3 +56,10 @@ void MeshStorage::mesh_free(RID p_rid) {
mesh_owner.free(p_rid);
}
+
+void MeshStorage::mesh_clear(RID p_mesh) {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!m);
+
+ m->surfaces.clear();
+}
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index 4399f4ab66..28fe8cb80d 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -116,7 +116,7 @@ public:
virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
- virtual void mesh_clear(RID p_mesh) override {}
+ virtual void mesh_clear(RID p_mesh) override;
/* MESH INSTANCE */
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
index 7cee55922d..beedff0a76 100644
--- a/servers/rendering/dummy/storage/particles_storage.h
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -89,8 +89,6 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_instance) override {}
virtual void particles_remove_collision(RID p_particles, RID p_instance) override {}
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
-
virtual void update_particles() override {}
/* PARTICLES COLLISION */
@@ -111,7 +109,6 @@ public:
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
- virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); }
virtual void particles_collision_instance_free(RID p_rid) override {}
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index a17d734e10..dd89504f38 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -80,6 +80,7 @@ public:
virtual void texture_free(RID p_rid) override {
// delete the texture
DummyTexture *texture = texture_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!texture);
texture_owner.free(p_rid);
memdelete(texture);
};
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 623f0c647b..07394b49a3 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -32,7 +32,7 @@
#include "servers/rendering/rendering_server_globals.h"
const Rect2 &RendererCanvasRender::Item::get_rect() const {
- if (custom_rect || (!rect_dirty && !update_when_visible)) {
+ if (custom_rect || (!rect_dirty && !update_when_visible && skeleton == RID())) {
return rect;
}
@@ -80,7 +80,7 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const {
} break;
case Item::Command::TYPE_MESH: {
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
- AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, RID());
+ AABB aabb = RSG::mesh_storage->mesh_get_aabb(mesh->mesh, skeleton);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index 27f977a80b..a05db8c563 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -56,6 +56,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
+ blur_modes.push_back("\n#define MODE_SET_COLOR\n"); // BLUR_MODE_SET_COLOR
blur_raster.shader.initialize(blur_modes);
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -105,6 +106,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2
copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n"); // COPY_TO_FB_SET_COLOR
copy_to_fb.shader.initialize(copy_modes);
@@ -508,16 +510,18 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
- copy_to_fb.push_constant.use_section = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_USE_SECTION;
copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
+
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -535,25 +539,35 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
RD::get_singleton()->draw_list_draw(draw_list, true);
}
-void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) {
+void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
if (p_force_luminance) {
- copy_to_fb.push_constant.force_luminance = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FORCE_LUMINANCE;
}
if (p_alpha_to_zero) {
- copy_to_fb.push_constant.alpha_to_zero = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ZERO;
}
if (p_srgb) {
- copy_to_fb.push_constant.srgb = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_SRGB;
+ }
+ if (p_alpha_to_one) {
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ONE;
+ }
+ if (p_linear) {
+ // Used for copying to a linear buffer. In the mobile renderer we divide the contents of the linear buffer
+ // to allow for a wider effective range.
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_LINEAR;
+ copy_to_fb.push_constant.luminance_multiplier = prefer_raster_effects ? 2.0 : 1.0;
}
// setup our uniforms
@@ -608,8 +622,6 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
@@ -641,7 +653,6 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- //HORIZONTAL
RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
@@ -654,6 +665,43 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RD::get_singleton()->compute_list_end();
}
+void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian blur with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode blur_mode = BLUR_MODE_GAUSSIAN_BLUR;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
@@ -882,6 +930,36 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect
RD::get_singleton()->compute_list_end();
}
+void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the set_color shader with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+
+ copy_to_fb.push_constant.set_color[0] = p_color.r;
+ copy_to_fb.push_constant.set_color[1] = p_color.g;
+ copy_to_fb.push_constant.set_color[2] = p_color.b;
+ copy_to_fb.push_constant.set_color[3] = p_color.a;
+
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
+ CopyToFBMode mode = COPY_TO_FB_SET_COLOR;
+
+ RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index 0ddb60ebef..83f7a51a36 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -63,6 +63,8 @@ private:
BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
BLUR_MODE_COPY,
+ BLUR_MODE_SET_COLOR,
+
BLUR_MODE_MAX
};
@@ -174,19 +176,28 @@ private:
COPY_TO_FB_MULTIVIEW,
COPY_TO_FB_MULTIVIEW_WITH_DEPTH,
+
+ COPY_TO_FB_SET_COLOR,
COPY_TO_FB_MAX,
};
+ enum CopyToFBFlags {
+ COPY_TO_FB_FLAG_FLIP_Y = (1 << 0),
+ COPY_TO_FB_FLAG_USE_SECTION = (1 << 1),
+ COPY_TO_FB_FLAG_FORCE_LUMINANCE = (1 << 2),
+ COPY_TO_FB_FLAG_ALPHA_TO_ZERO = (1 << 3),
+ COPY_TO_FB_FLAG_SRGB = (1 << 4),
+ COPY_TO_FB_FLAG_ALPHA_TO_ONE = (1 << 5),
+ COPY_TO_FB_FLAG_LINEAR = (1 << 6),
+ };
+
struct CopyToFbPushConstant {
float section[4];
float pixel_size[2];
- uint32_t flip_y;
- uint32_t use_section;
+ float luminance_multiplier;
+ uint32_t flags;
- uint32_t force_luminance;
- uint32_t alpha_to_zero;
- uint32_t srgb;
- uint32_t pad;
+ float set_color[4];
};
struct CopyToFb {
@@ -316,11 +327,12 @@ public:
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
- void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false);
+ void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false);
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
+ void gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size);
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
@@ -328,6 +340,7 @@ public:
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
+ void set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index 9653382e96..8e43869b4d 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -1332,7 +1332,6 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
for (int pass = 0; pass < blur_passes; pass++) {
int blur_pipeline = SSAO_BLUR_PASS;
if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
if (pass < blur_passes - 2) {
blur_pipeline = SSAO_BLUR_PASS_WIDE;
} else {
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h
index dfaf3881bb..a04dfc4a74 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.h
+++ b/servers/rendering/renderer_rd/effects/ss_effects.h
@@ -100,7 +100,7 @@ public:
float sharpness = 0.98;
float normal_rejection = 1.0;
- Size2i full_screen_size = Size2i();
+ Size2i full_screen_size;
};
void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth);
@@ -137,7 +137,7 @@ public:
float horizon = 0.06;
float sharpness = 0.98;
- Size2i full_screen_size = Size2i();
+ Size2i full_screen_size;
};
void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth);
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 5ff00aa94c..701d53b41d 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -92,18 +92,15 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
}
Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
- // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
- // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
- // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
- // of the VRS buffer to supply.
- Size2i texel_size = Size2i(16, 16);
-
- int width = p_base_size.x / texel_size.x;
- if (p_base_size.x % texel_size.x != 0) {
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
+
+ int width = p_base_size.x / texel_width;
+ if (p_base_size.x % texel_width != 0) {
width++;
}
- int height = p_base_size.y / texel_size.y;
- if (p_base_size.y % texel_size.y != 0) {
+ int height = p_base_size.y / texel_height;
+ if (p_base_size.y % texel_height != 0) {
height++;
}
return Size2i(width, height);
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 74082906c4..eece195946 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -727,9 +727,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
any_uses_time |= shader_data->uses_time;
- Vector3i min = Vector3i();
- Vector3i max = Vector3i();
- Vector3i kernel_size = Vector3i();
+ Vector3i min;
+ Vector3i max;
+ Vector3i kernel_size;
Vector3 position = fog_volume_instance->transform.get_origin();
RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 0e4a223f69..41fceac7c2 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -1765,6 +1765,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
+ if (rb.is_valid()) {
+ RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ }
keep_color = true;
} break;
case RS::ENV_BG_KEEP: {
@@ -2311,6 +2315,8 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
scene_data.lod_distance_multiplier = p_lod_distance_multiplier;
scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
scene_data.opaque_prepass_threshold = 0.1f;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -2401,6 +2407,8 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
scene_data.z_far = p_cam_projection.get_z_far();
scene_data.dual_paraboloid_side = 0;
scene_data.opaque_prepass_threshold = 0.0;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -2443,6 +2451,8 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_data.material_uv2_mode = false;
scene_data.opaque_prepass_threshold = 0.0f;
scene_data.emissive_exposure_normalization = p_exposure_normalization;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -3083,7 +3093,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 19;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID vfog = RID();
+ RID vfog;
if (rb_data.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) {
Ref<RendererRD::Fog::VolumetricFog> fog = rb->get_custom_data(RB_SCOPE_FOG);
vfog = fog->fog_map;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index c1b23af82f..6c8ce5265e 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -115,6 +115,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
+ // Use alpha clip pipeline for alpha hash/dither.
+ // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows.
+ actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -151,6 +154,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+ uses_vertex_time = gen_code.uses_vertex_time;
+ uses_fragment_time = gen_code.uses_fragment_time;
#if 0
print_line("**compiling shader:");
@@ -457,11 +462,15 @@ bool SceneShaderForwardClustered::ShaderData::is_parameter_texture(const StringN
}
bool SceneShaderForwardClustered::ShaderData::is_animated() const {
- return false;
+ return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
}
bool SceneShaderForwardClustered::ShaderData::casts_shadows() const {
- return false;
+ bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
+ bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
+ bool has_alpha = has_base_alpha || uses_blend_alpha;
+
+ return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
}
Variant SceneShaderForwardClustered::ShaderData::get_default_parameter(const StringName &p_parameter) const {
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index a9a9fa94de..194edf2dcb 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -150,8 +150,8 @@ public:
String code;
HashMap<StringName, HashMap<int, RID>> default_texture_params;
- DepthDraw depth_draw;
- DepthTest depth_test;
+ DepthDraw depth_draw = DEPTH_DRAW_OPAQUE;
+ DepthTest depth_test = DEPTH_TEST_ENABLED;
bool uses_point_size = false;
bool uses_alpha = false;
@@ -172,6 +172,8 @@ public:
bool uses_depth_texture = false;
bool uses_normal_texture = false;
bool uses_time = false;
+ bool uses_vertex_time = false;
+ bool uses_fragment_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
bool uses_screen_texture_mipmaps = false;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 898521ca4d..2506f4578b 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -796,6 +796,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
+ if (rb.is_valid()) {
+ RID dest_framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
+ RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
+ copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
+ }
keep_color = true;
} break;
case RS::ENV_BG_KEEP: {
@@ -1269,6 +1274,8 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
scene_data.lod_distance_multiplier = p_lod_distance_multiplier;
scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
scene_data.opaque_prepass_threshold = 0.1;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -1361,6 +1368,8 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
scene_data.material_uv2_mode = false;
scene_data.opaque_prepass_threshold = 0.0f;
scene_data.emissive_exposure_normalization = p_exposure_normalization;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
@@ -1484,6 +1493,8 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
scene_data.z_far = p_cam_projection.get_z_far();
scene_data.dual_paraboloid_side = 0;
scene_data.opaque_prepass_threshold = 0.0;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
RenderDataRD render_data;
render_data.scene_data = &scene_data;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 02bd30d32d..ee82fa7c7d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -116,6 +116,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
+ // Use alpha clip pipeline for alpha hash/dither.
+ // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows.
+ actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip;
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
// actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
@@ -150,6 +153,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
+ uses_vertex_time = gen_code.uses_vertex_time;
+ uses_fragment_time = gen_code.uses_fragment_time;
#if 0
print_line("**compiling shader:");
@@ -412,11 +417,15 @@ bool SceneShaderForwardMobile::ShaderData::is_parameter_texture(const StringName
}
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
- return false;
+ return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
}
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
- return false;
+ bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
+ bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha;
+ bool has_alpha = has_base_alpha || uses_blend_alpha;
+
+ return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
}
Variant SceneShaderForwardMobile::ShaderData::get_default_parameter(const StringName &p_parameter) const {
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index f67665a02f..5b51cfc8c3 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -132,6 +132,8 @@ public:
bool uses_depth_texture = false;
bool uses_normal_texture = false;
bool uses_time = false;
+ bool uses_vertex_time = false;
+ bool uses_fragment_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 7e0070f8b7..cc8238a8dd 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -796,7 +796,6 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RenderingServerDefault::redraw_request(); // active particles means redraw request
- bool local_coords = true;
int dpc = particles_storage->particles_get_draw_passes(pt->particles);
if (dpc == 0) {
break; //nothing to draw
@@ -818,12 +817,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
//pass collision information
- Transform2D xform;
- if (local_coords) {
- xform = p_item->final_transform;
- } else {
- xform = p_canvas_transform_inverse;
- }
+ Transform2D xform = p_item->final_transform;
RID sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
@@ -2681,16 +2675,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
primitive_arrays.index_array[3] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6);
}
- { //default skeleton buffer
-
- shader.default_skeleton_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform));
- SkeletonUniform su;
- _update_transform_2d_to_mat4(Transform2D(), su.skeleton_inverse);
- _update_transform_2d_to_mat4(Transform2D(), su.skeleton_transform);
- RD::get_singleton()->buffer_update(shader.default_skeleton_uniform_buffer, 0, sizeof(SkeletonUniform), &su);
-
- shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT);
- }
{
//default shadow texture to keep uniform set happy
RD::TextureFormat tf;
@@ -2834,8 +2818,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
memdelete_arr(state.light_uniforms);
RD::get_singleton()->free(state.lights_uniform_buffer);
- RD::get_singleton()->free(shader.default_skeleton_uniform_buffer);
- RD::get_singleton()->free(shader.default_skeleton_texture_buffer);
}
//shadow rendering
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index d1f3c9ec6a..3fff574098 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -144,10 +144,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID quad_index_array;
PipelineVariants pipeline_variants;
- // default_skeleton uniform set
- RID default_skeleton_uniform_buffer;
- RID default_skeleton_texture_buffer;
-
ShaderCompiler compiler;
} shader;
@@ -409,11 +405,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t lights[4];
};
- struct SkeletonUniform {
- float skeleton_transform[16];
- float skeleton_inverse[16];
- };
-
Item *items[MAX_RENDER_ITEMS];
bool using_directional_lights = false;
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 8593e6b265..eb5f68849e 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -191,48 +191,6 @@ void main() {
uv += 1e-5;
}
-#ifdef USE_ATTRIBUTES
-#if 0
- if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
- //skeleton transform
- ivec4 bone_indicesi = ivec4(bone_indices);
-
- uvec2 tex_ofs = bone_indicesi.x * 2;
-
- mat2x4 m;
- m = mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.x;
-
- tex_ofs = bone_indicesi.y * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.y;
-
- tex_ofs = bone_indicesi.z * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.z;
-
- tex_ofs = bone_indicesi.w * 2;
-
- m += mat2x4(
- texelFetch(skeleton_buffer, tex_ofs + 0),
- texelFetch(skeleton_buffer, tex_ofs + 1)) *
- bone_weights.w;
-
- mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse;
-
- //outvec = bone_matrix * outvec;
- }
-#endif
-#endif
-
vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
vertex_interp = vertex;
diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
index 932312de82..8c26a67926 100644
--- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl
+++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
@@ -142,7 +142,11 @@ void main() {
}
}
#else
- if (!gl_HelperInvocation) {
+// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs
+#ifndef MOLTENVK_USED
+ if (!gl_HelperInvocation)
+#endif
+ {
atomicOr(cluster_render.data[usage_write_offset], usage_write_bit);
}
#endif
@@ -162,7 +166,11 @@ void main() {
}
}
#else
- if (!gl_HelperInvocation) {
+// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs
+#ifndef MOLTENVK_USED
+ if (!gl_HelperInvocation)
+#endif
+ {
atomicOr(cluster_render.data[z_write_offset], z_write_bit);
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
index cb06250cf2..31aabbe9d2 100644
--- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
@@ -53,30 +53,31 @@ void main() {
#ifdef MODE_GAUSSIAN_BLUR
- // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-
- // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount.
-
- if (bool(blur.flags & FLAG_HORIZONTAL)) {
- vec2 pix_size = blur.pixel_size;
- pix_size *= 0.5; //reading from larger buffer, so use more samples
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
- color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
- color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
- color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
- color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
- color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
- color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
- frag_color = color;
- } else {
- vec2 pix_size = blur.pixel_size;
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
- color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
- color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
- color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
- color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
- frag_color = color;
- }
+ // For Gaussian Blur we use 13 taps in a single pass instead of 12 taps over 2 passes.
+ // This minimizes the number of times we change framebuffers which is very important for mobile.
+ // Source: http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
+ vec4 A = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, -1.0));
+ vec4 B = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, -1.0));
+ vec4 C = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, -1.0));
+ vec4 D = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, -0.5));
+ vec4 E = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, -0.5));
+ vec4 F = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 0.0));
+ vec4 G = texture(source_color, uv_interp);
+ vec4 H = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 0.0));
+ vec4 I = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, 0.5));
+ vec4 J = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, 0.5));
+ vec4 K = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 1.0));
+ vec4 L = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, 1.0));
+ vec4 M = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 1.0));
+
+ float base_weight = 0.5 / 4.0;
+ float lesser_weight = 0.125 / 4.0;
+
+ frag_color = (D + E + I + J) * base_weight;
+ frag_color += (A + B + G + F) * lesser_weight;
+ frag_color += (B + C + H + G) * lesser_weight;
+ frag_color += (F + G + L + K) * lesser_weight;
+ frag_color += (G + H + M + L) * lesser_weight;
#endif
#ifdef MODE_GAUSSIAN_GLOW
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
index bfe329b8ec..5cc2ed7622 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
@@ -194,10 +194,10 @@ void main() {
color = min(color * feedback, vec4(params.glow_luminance_cap));
}
-#endif
+#endif // MODE_GLOW
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // MODE_GAUSSIAN_BLUR
#ifdef MODE_SIMPLE_COPY
@@ -227,7 +227,7 @@ void main() {
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // MODE_SIMPLE_COPY
#ifdef MODE_SIMPLE_COPY_DEPTH
@@ -239,7 +239,7 @@ void main() {
imageStore(dest_buffer, pos + params.target, vec4(color.r));
-#endif
+#endif // MODE_SIMPLE_COPY_DEPTH
#ifdef MODE_LINEARIZE_DEPTH_COPY
@@ -253,7 +253,7 @@ void main() {
}
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // MODE_LINEARIZE_DEPTH_COPY
#if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA)
@@ -276,7 +276,7 @@ void main() {
vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne
#endif
imageStore(dest_buffer, pos + params.target, color);
-#endif
+#endif // defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA)
#ifdef MODE_SET_COLOR
imageStore(dest_buffer, pos + params.target, params.set_color);
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
index 1c17eabb56..46bb99794d 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
@@ -13,6 +13,14 @@
#endif // has_VK_KHR_multiview
#endif //MULTIVIEW
+#define FLAG_FLIP_Y (1 << 0)
+#define FLAG_USE_SECTION (1 << 1)
+#define FLAG_FORCE_LUMINANCE (1 << 2)
+#define FLAG_ALPHA_TO_ZERO (1 << 3)
+#define FLAG_SRGB (1 << 4)
+#define FLAG_ALPHA_TO_ONE (1 << 5)
+#define FLAG_LINEAR (1 << 6)
+
#ifdef MULTIVIEW
layout(location = 0) out vec3 uv_interp;
#else
@@ -22,11 +30,10 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, std430) uniform Params {
vec4 section;
vec2 pixel_size;
- bool flip_y;
- bool use_section;
+ float luminance_multiplier;
+ uint flags;
- bool force_luminance;
- uint pad[3];
+ vec4 color;
}
params;
@@ -37,13 +44,13 @@ void main() {
uv_interp.z = ViewIndex;
#endif
vec2 vpos = uv_interp.xy;
- if (params.use_section) {
+ if (bool(params.flags & FLAG_USE_SECTION)) {
vpos = params.section.xy + vpos * params.section.zw;
}
gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0);
- if (params.flip_y) {
+ if (bool(params.flags & FLAG_FLIP_Y)) {
uv_interp.y = 1.0 - uv_interp.y;
}
}
@@ -63,16 +70,21 @@ void main() {
#endif // has_VK_KHR_multiview
#endif //MULTIVIEW
+#define FLAG_FLIP_Y (1 << 0)
+#define FLAG_USE_SECTION (1 << 1)
+#define FLAG_FORCE_LUMINANCE (1 << 2)
+#define FLAG_ALPHA_TO_ZERO (1 << 3)
+#define FLAG_SRGB (1 << 4)
+#define FLAG_ALPHA_TO_ONE (1 << 5)
+#define FLAG_LINEAR (1 << 6)
+
layout(push_constant, std430) uniform Params {
vec4 section;
vec2 pixel_size;
- bool flip_y;
- bool use_section;
+ float luminance_multiplier;
+ uint flags;
- bool force_luminance;
- bool alpha_to_zero;
- bool srgb;
- uint pad;
+ vec4 color;
}
params;
@@ -104,7 +116,15 @@ vec3 linear_to_srgb(vec3 color) {
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
+vec3 srgb_to_linear(vec3 color) {
+ return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045)));
+}
+
void main() {
+#ifdef MODE_SET_COLOR
+ frag_color = params.color;
+#else
+
#ifdef MULTIVIEW
vec3 uv = uv_interp;
#else
@@ -155,15 +175,22 @@ void main() {
#endif /* MODE_TWO_SOURCES */
#endif /* MULTIVIEW */
- if (params.force_luminance) {
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
color.rgb = vec3(max(max(color.r, color.g), color.b));
}
- if (params.alpha_to_zero) {
+ if (bool(params.flags & FLAG_ALPHA_TO_ZERO)) {
color.rgb *= color.a;
}
- if (params.srgb) {
+ if (bool(params.flags & FLAG_SRGB)) {
color.rgb = linear_to_srgb(color.rgb);
}
+ if (bool(params.flags & FLAG_ALPHA_TO_ONE)) {
+ color.a = 1.0;
+ }
+ if (bool(params.flags & FLAG_LINEAR)) {
+ color.rgb = srgb_to_linear(color.rgb);
+ }
- frag_color = color;
+ frag_color = color / params.luminance_multiplier;
+#endif // MODE_SET_COLOR
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index 5ef83c0b44..b450bb9fe9 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -63,10 +63,18 @@ void main() {
#ifdef MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
+ frag_color = uint(color.r * 255.0);
#else /* MULTIVIEW */
vec4 color = textureLod(source_color, uv, 0.0);
-#endif /* MULTIVIEW */
- // See if we can change the sampler to one that returns int...
- frag_color = uint(color.r * 256.0);
+ // for user supplied VRS map we do a color mapping
+ color.r *= 3.0;
+ frag_color = int(color.r) << 2;
+
+ color.g *= 3.0;
+ frag_color += int(color.g);
+
+ // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported
+ // 4x8, 8x4 and 8x8 are only available on some GPUs
+#endif /* MULTIVIEW */
}
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 0bdf0e50aa..896f51ca01 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -62,7 +62,7 @@ vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
/* Varyings */
@@ -826,7 +826,8 @@ void fragment_shader(in SceneData scene_data) {
// alpha hash can be used in unison with alpha antialiasing
#ifdef ALPHA_HASH_USED
- if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) {
+ vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz;
+ if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) {
discard;
}
#endif // ALPHA_HASH_USED
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index 9aeaa6d978..d50749306e 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -63,7 +63,7 @@ vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
/* Varyings */
@@ -779,7 +779,8 @@ void main() {
// alpha hash can be used in unison with alpha antialiasing
#ifdef ALPHA_HASH_USED
- if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) {
+ vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz;
+ if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) {
discard;
}
#endif // ALPHA_HASH_USED
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 3a6dd579b9..9f6aa7adc0 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -462,7 +462,7 @@ void main() {
if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) {
continue;
}
- vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * 2.0 - 1.0;
+ vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * -2.0 + 1.0;
dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction
amount = length(s);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
index 97c913d489..71510ee06a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
@@ -11,7 +11,8 @@ float hash_3d(vec3 p) {
float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
vec3 dx = dFdx(pos);
- vec3 dy = dFdx(pos);
+ vec3 dy = dFdy(pos);
+
float delta_max_sqr = max(length(dx), length(dy));
float pix_scale = 1.0 / (hash_scale * delta_max_sqr);
@@ -32,9 +33,9 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / (2.0 * min_lerp * (1.0 - min_lerp))));
float alpha_hash_threshold =
- (lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z;
+ (a_interp < (1.0 - min_lerp)) ? ((a_interp < min_lerp) ? cases.x : cases.y) : cases.z;
- return clamp(alpha_hash_threshold, 0.0, 1.0);
+ return clamp(alpha_hash_threshold, 0.00001, 1.0);
}
#endif // ALPHA_HASH_USED
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index 75bea9300b..f5b233cca0 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -63,7 +63,7 @@ vec3 oct_to_vec3(vec2 oct) {
vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
- return v;
+ return normalize(v);
}
vec3 decode_uint_oct_to_norm(uint base) {
@@ -143,8 +143,8 @@ void main() {
uint skin_offset = params.skin_stride * index;
uvec2 bones = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]);
- uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 3; //pre-add xform offset
- uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 3;
+ uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 2; //pre-add xform offset
+ uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 2;
skin_offset += params.skin_weight_offset;
@@ -161,6 +161,13 @@ void main() {
//reverse order because its transposed
vertex = (vec4(vertex, 0.0, 1.0) * m).xy;
}
+
+ uint dst_offset = index * params.vertex_stride;
+
+ uvec2 uvertex = floatBitsToUint(vertex);
+ dst_vertices.data[dst_offset + 0] = uvertex.x;
+ dst_vertices.data[dst_offset + 1] = uvertex.y;
+
#else
vec3 vertex;
vec3 normal;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index c83473ef07..1dd95969e6 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -653,6 +653,14 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
if (light_data.shadow_opacity > 0.001) {
RS::LightDirectionalShadowMode smode = light->directional_shadow_mode;
+ light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR];
+ light_data.softshadow_angle = angular_diameter;
+ light_data.bake_mode = light->bake_mode;
+
+ if (angular_diameter <= 0.0) {
+ light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF
+ }
+
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light->directional_blend_splits;
for (int j = 0; j < 4; j++) {
@@ -669,7 +677,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
Projection shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
- float bias_scale = light_instance->shadow_transform[j].bias_scale;
+ float bias_scale = light_instance->shadow_transform[j].bias_scale * light_data.soft_shadow_scale;
light_data.shadow_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0 * bias_scale;
light_data.shadow_normal_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[j].shadow_texel_size;
light_data.shadow_transmittance_bias[j] = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] * bias_scale;
@@ -702,14 +710,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
float fade_start = light->param[RS::LIGHT_PARAM_SHADOW_FADE_START];
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
light_data.fade_to = -light_data.shadow_split_offsets[3];
-
- light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR];
- light_data.softshadow_angle = angular_diameter;
- light_data.bake_mode = light->bake_mode;
-
- if (angular_diameter <= 0.0) {
- light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF
- }
}
r_directional_light_count++;
@@ -978,6 +978,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
light_data.soft_shadow_size = 0.0;
light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF
}
+ light_data.shadow_bias *= light_data.soft_shadow_scale;
}
} else {
light_data.shadow_opacity = 0.0;
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 1e74d31383..adb882986f 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -616,7 +616,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- if (!skeleton || skeleton->size == 0) {
+ if (!skeleton || skeleton->size == 0 || mesh->skeleton_aabb_version == skeleton->version) {
return mesh->aabb;
}
@@ -708,6 +708,7 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
}
+ mesh->skeleton_aabb_version = skeleton->version;
return aabb;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 6a7400631d..4765475804 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -144,6 +144,7 @@ private:
AABB aabb;
AABB custom_aabb;
+ uint64_t skeleton_aabb_version = 0;
Vector<RID> material_cache;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 854976692e..51aa81745b 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -1027,6 +1027,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
uniforms.push_back(u);
}
p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2);
+ p_particles->collision_heightmap_texture = collision_heightmap_texture;
}
}
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index a9cc98abb9..49a8444e2f 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -54,8 +54,7 @@ private:
float velocity[3];
uint32_t active;
float color[4];
- float custom[3];
- float lifetime;
+ float custom[4];
};
struct ParticlesFrameParams {
@@ -127,9 +126,6 @@ private:
Collider colliders[MAX_COLLIDERS];
};
- struct ParticleEmissionBufferData {
- };
-
struct ParticleEmissionBuffer {
struct Data {
float xform[16];
@@ -412,7 +408,7 @@ public:
bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
virtual RID particles_allocate() override;
- virtual void particles_initialize(RID p_particles_collision) override;
+ virtual void particles_initialize(RID p_rid) override;
virtual void particles_free(RID p_rid) override;
virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
@@ -519,7 +515,7 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override;
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+ void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
virtual void update_particles() override;
@@ -546,7 +542,7 @@ public:
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
Vector3 particles_collision_get_extents(RID p_particles_collision) const;
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
- virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+ RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
Dependency *particles_collision_get_dependency(RID p_particles) const;
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 077fde58b8..15c5687665 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -560,6 +560,7 @@ void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS:
void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
ERR_FAIL_NULL(ct);
+
ct->texture_repeat = p_repeat;
ct->clear_sets();
}
@@ -3119,9 +3120,11 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
// TODO figure out stereo support here
- //single texture copy for backbuffer
- //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
- copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+ } else {
+ copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true);
+ }
if (!p_gen_mipmaps) {
return;
@@ -3130,6 +3133,8 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
//then mipmap blur
RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
+ Size2i texture_size = rt->size;
+
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
region.position.x >>= 1;
region.position.y >>= 1;
@@ -3137,7 +3142,13 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
region.size.y = MAX(1, region.size.y >> 1);
RID mipmap = rt->backbuffer_mipmaps[i];
- copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+ } else {
+ texture_size.x = MAX(1, texture_size.x >> 1);
+ texture_size.y = MAX(1, texture_size.y >> 1);
+ copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
+ }
prev_texture = mipmap;
}
RD::get_singleton()->draw_command_end_label();
@@ -3165,7 +3176,11 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const
}
//single texture copy for backbuffer
- copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ } else {
+ copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ }
}
void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
@@ -3191,6 +3206,7 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target,
RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2");
//then mipmap blur
RID prev_texture = rt->backbuffer_mipmap0;
+ Size2i texture_size = rt->size;
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
region.position.x >>= 1;
@@ -3199,7 +3215,14 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target,
region.size.y = MAX(1, region.size.y >> 1);
RID mipmap = rt->backbuffer_mipmaps[i];
- copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
+ } else {
+ texture_size.x = MAX(1, texture_size.x >> 1);
+ texture_size.y = MAX(1, texture_size.y >> 1);
+ copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
+ }
prev_texture = mipmap;
}
RD::get_singleton()->draw_command_end_label();
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 348f6e4695..4ee355ee9f 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -3319,7 +3319,7 @@ void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_rend
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(Transform3D(), Projection(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), environment, RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 2836889de5..8cec531393 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -550,6 +550,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
+ // There may be an outstanding clear request if a clear was requested, but no 2D elements were drawn.
+ // Clear now otherwise we copy over garbage from the render target.
+ RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target);
_draw_3d(p_viewport);
}
}
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index e6a7575343..d3f3972029 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1257,6 +1257,8 @@ public:
LIMIT_SUBGROUP_SIZE,
LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
LIMIT_SUBGROUP_OPERATIONS,
+ LIMIT_VRS_TEXEL_WIDTH,
+ LIMIT_VRS_TEXEL_HEIGHT,
};
virtual uint64_t limit_get(Limit p_limit) const = 0;
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index fc644fcae6..7ccf3af6eb 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -1141,8 +1141,18 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
case SL::OP_STRUCT:
case SL::OP_CONSTRUCT: {
ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
-
- SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
+ const SL::VariableNode *vnode = static_cast<const SL::VariableNode *>(onode->arguments[0]);
+ const SL::FunctionNode *func = nullptr;
+ const bool is_internal_func = internal_functions.has(vnode->name);
+
+ if (!is_internal_func) {
+ for (int i = 0; i < shader->functions.size(); i++) {
+ if (shader->functions[i].name == vnode->name) {
+ func = shader->functions[i].function;
+ break;
+ }
+ }
+ }
bool is_texture_func = false;
bool is_screen_texture = false;
@@ -1156,7 +1166,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
used_flag_pointers.insert(vnode->name);
}
- if (internal_functions.has(vnode->name)) {
+ if (is_internal_func) {
code += vnode->name;
is_texture_func = texture_functions.has(vnode->name);
} else if (p_default_actions.renames.has(vnode->name)) {
@@ -1172,6 +1182,44 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (i > 1) {
code += ", ";
}
+
+ bool is_out_qualifier = false;
+ if (is_internal_func) {
+ is_out_qualifier = SL::is_builtin_func_out_parameter(vnode->name, i - 1);
+ } else if (func != nullptr) {
+ const SL::ArgumentQualifier qualifier = func->arguments[i - 1].qualifier;
+ is_out_qualifier = qualifier == SL::ARGUMENT_QUALIFIER_OUT || qualifier == SL::ARGUMENT_QUALIFIER_INOUT;
+ }
+
+ if (is_out_qualifier) {
+ StringName name;
+ bool found = false;
+ {
+ const SL::Node *node = onode->arguments[i];
+
+ bool done = false;
+ do {
+ switch (node->type) {
+ case SL::Node::TYPE_VARIABLE: {
+ name = static_cast<const SL::VariableNode *>(node)->name;
+ done = true;
+ found = true;
+ } break;
+ case SL::Node::TYPE_MEMBER: {
+ node = static_cast<const SL::MemberNode *>(node)->owner;
+ } break;
+ default: {
+ done = true;
+ } break;
+ }
+ } while (!done);
+ }
+
+ if (found && p_actions.write_flag_pointers.has(name)) {
+ *p_actions.write_flag_pointers[name] = true;
+ }
+ }
+
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
//need to map from texture to sampler in order to sample when using Vulkan GLSL
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 14c09c1512..79fbc59b06 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -3645,7 +3645,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
switch (p_type) {
case ShaderLanguage::TYPE_BOOL:
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3658,7 +3658,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 2;
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3671,7 +3671,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 3;
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3684,7 +3684,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 4;
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].boolean);
}
@@ -3695,7 +3695,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
break;
case ShaderLanguage::TYPE_INT:
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3708,7 +3708,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 2;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3721,7 +3721,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 3;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3734,7 +3734,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 4;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].sint);
}
@@ -3745,7 +3745,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
break;
case ShaderLanguage::TYPE_UINT:
if (array_size > 0) {
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3758,7 +3758,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 2;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3771,7 +3771,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 3;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3784,7 +3784,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 4;
- PackedInt32Array array = PackedInt32Array();
+ PackedInt32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].uint);
}
@@ -3795,7 +3795,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
break;
case ShaderLanguage::TYPE_FLOAT:
if (array_size > 0) {
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i++) {
array.push_back(p_value[i].real);
}
@@ -3808,7 +3808,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 2;
- PackedVector2Array array = PackedVector2Array();
+ PackedVector2Array array;
for (int i = 0; i < array_size; i += 2) {
array.push_back(Vector2(p_value[i].real, p_value[i + 1].real));
}
@@ -3822,13 +3822,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 3;
if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
- PackedColorArray array = PackedColorArray();
+ PackedColorArray array;
for (int i = 0; i < array_size; i += 3) {
array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
}
value = Variant(array);
} else {
- PackedVector3Array array = PackedVector3Array();
+ PackedVector3Array array;
for (int i = 0; i < array_size; i += 3) {
array.push_back(Vector3(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real));
}
@@ -3847,13 +3847,13 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
array_size *= 4;
if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
- PackedColorArray array = PackedColorArray();
+ PackedColorArray array;
for (int i = 0; i < array_size; i += 4) {
array.push_back(Color(p_value[i].real, p_value[i + 1].real, p_value[i + 2].real, p_value[i + 3].real));
}
value = Variant(array);
} else {
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 4) {
array.push_back(p_value[i].real);
array.push_back(p_value[i + 1].real);
@@ -3874,7 +3874,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 4;
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 4) {
array.push_back(p_value[i].real);
array.push_back(p_value[i + 1].real);
@@ -3890,7 +3890,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 9;
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 9) {
for (int j = 0; j < 9; j++) {
array.push_back(p_value[i + j].real);
@@ -3916,7 +3916,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (array_size > 0) {
array_size *= 16;
- PackedFloat32Array array = PackedFloat32Array();
+ PackedFloat32Array array;
for (int i = 0; i < array_size; i += 16) {
for (int j = 0; j < 16; j++) {
array.push_back(p_value[i + j].real);
@@ -4309,8 +4309,18 @@ ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
TYPE_INT,
TYPE_UINT,
TYPE_FLOAT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_FLOAT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_VOID,
};
+ static_assert(sizeof(scalar_types) / sizeof(*scalar_types) == TYPE_MAX);
+
return scalar_types[p_type];
}
@@ -4340,8 +4350,18 @@ int ShaderLanguage::get_cardinality(DataType p_type) {
1,
1,
1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
};
+ static_assert(sizeof(cardinality_table) / sizeof(*cardinality_table) == TYPE_MAX);
+
return cardinality_table[p_type];
}
@@ -7570,7 +7590,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
- if (b && b->parent_function && p_function_info.main_function) {
+ if (b->parent_function && p_function_info.main_function) {
_set_error(vformat(RTR("Using '%s' in the '%s' processor function is incorrect."), "return", b->parent_function->name));
return ERR_PARSE_ERROR;
}
@@ -8170,25 +8190,27 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
};
[[fallthrough]];
case TK_INSTANCE: {
+ if (tk.type == TK_INSTANCE) {
#ifdef DEBUG_ENABLED
- keyword_completion_context = CF_UNIFORM_KEYWORD;
- if (_lookup_next(next)) {
- if (next.type == TK_UNIFORM) {
- keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ keyword_completion_context = CF_UNIFORM_KEYWORD;
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ }
}
- }
#endif // DEBUG_ENABLED
- if (String(shader_type_identifier) != "spatial") {
- _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
- return ERR_PARSE_ERROR;
- }
- if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
- tk = _get_token();
- if (tk.type != TK_UNIFORM) {
- _set_expected_after_error("uniform", "instance");
+ if (String(shader_type_identifier) != "spatial") {
+ _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
- uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
+ tk = _get_token();
+ if (tk.type != TK_UNIFORM) {
+ _set_expected_after_error("uniform", "instance");
+ return ERR_PARSE_ERROR;
+ }
+ uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
+ }
}
};
[[fallthrough]];
@@ -8858,7 +8880,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
_set_error(RTR("Expected an uniform group identifier or `;`."));
}
return ERR_PARSE_ERROR;
- } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) {
+ } else if (current_uniform_group_name.is_empty()) {
_set_error(RTR("Group needs to be opened before."));
return ERR_PARSE_ERROR;
} else {
@@ -9717,6 +9739,25 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
return String();
}
+bool ShaderLanguage::is_builtin_func_out_parameter(const String &p_name, int p_param) {
+ int i = 0;
+ while (builtin_func_out_args[i].name) {
+ if (p_name == builtin_func_out_args[i].name) {
+ for (int j = 0; j < BuiltinFuncOutArgs::MAX_ARGS; j++) {
+ int arg = builtin_func_out_args[i].arguments[j];
+ if (arg == p_param) {
+ return true;
+ }
+ if (arg < 0) {
+ return false;
+ }
+ }
+ }
+ i++;
+ }
+ return false;
+}
+
#ifdef DEBUG_ENABLED
void ShaderLanguage::_check_warning_accums() {
for (const KeyValue<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> &E : warnings_check_map2) {
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 1e302f5805..2534d1f252 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -1119,6 +1119,7 @@ public:
void clear();
static String get_shader_type(const String &p_code);
+ static bool is_builtin_func_out_parameter(const String &p_name, int p_param);
struct ShaderCompileInfo {
HashMap<StringName, FunctionInfo> functions;
diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h
index 17bde94902..dea9487af6 100644
--- a/servers/rendering/storage/environment_storage.h
+++ b/servers/rendering/storage/environment_storage.h
@@ -98,7 +98,7 @@ private:
float glow_hdr_luminance_cap = 12.0;
float glow_hdr_bleed_scale = 2.0;
float glow_map_strength = 0.0f; // 1.0f in GLES3 ??
- RID glow_map = RID();
+ RID glow_map;
// SSR
bool ssr_enabled = false;
@@ -143,7 +143,7 @@ private:
float adjustments_contrast = 1.0f;
float adjustments_saturation = 1.0f;
bool use_1d_color_correction = false;
- RID color_correction = RID();
+ RID color_correction;
};
mutable RID_Owner<Environment, true> environment_owner;
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
index ee4b8679b3..5ef54346f2 100644
--- a/servers/rendering/storage/particles_storage.h
+++ b/servers/rendering/storage/particles_storage.h
@@ -94,8 +94,6 @@ public:
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
-
virtual void update_particles() = 0;
/* PARTICLES COLLISION */
@@ -116,7 +114,6 @@ public:
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0;
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
- virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision) = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 7691bede07..6cb1684baf 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -1476,7 +1476,11 @@ RenderingDevice *RenderingServer::get_rendering_device() const {
}
RenderingDevice *RenderingServer::create_local_rendering_device() const {
- return RenderingDevice::get_singleton()->create_local_device();
+ RenderingDevice *device = RenderingDevice::get_singleton();
+ if (!device) {
+ return nullptr;
+ }
+ return device->create_local_device();
}
static Vector<Ref<Image>> _get_imgvec(const TypedArray<Image> &p_layers) {
@@ -2850,8 +2854,12 @@ void RenderingServer::init() {
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2", true);
GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false);
- GLOBAL_DEF("rendering/textures/lossless_compression/webp_compression_level", 2);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/lossless_compression/webp_compression_level", PropertyInfo(Variant::INT, "rendering/textures/lossless_compression/webp_compression_level", PROPERTY_HINT_RANGE, "0,9,1"));
+
+ GLOBAL_DEF("rendering/textures/webp_compression/compression_method", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/webp_compression/compression_method", PropertyInfo(Variant::INT, "rendering/textures/webp_compression/compression_method", PROPERTY_HINT_RANGE, "0,6,1"));
+
+ GLOBAL_DEF("rendering/textures/webp_compression/lossless_compression_factor", 25);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/webp_compression/lossless_compression_factor", PropertyInfo(Variant::FLOAT, "rendering/textures/webp_compression/lossless_compression_factor", PROPERTY_HINT_RANGE, "0,100,1"));
GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::FLOAT, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"));
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 4d58d24405..ec4ae98397 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -167,11 +167,12 @@ RID XRInterface::get_vrs_texture() {
// Default logic will return a standard VRS image based on our target size and default projections.
// Note that this only gets called if VRS is supported on the hardware.
- Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard.
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
int view_count = get_view_count();
Size2 target_size = get_render_target_size();
real_t aspect = target_size.x / target_size.y; // is this y/x ?
- Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y));
+ Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_width), round(0.5 + target_size.y / texel_height));
real_t radius = vrs_size.length() * 0.5;
Size2 vrs_sizei = vrs_size;
@@ -179,6 +180,8 @@ RID XRInterface::get_vrs_texture() {
const uint8_t densities[] = {
0, // 1x1
1, // 1x2
+ // 2, // 1x4 - not supported
+ // 3, // 1x8 - not supported
// 4, // 2x1
5, // 2x2
6, // 2x4
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 86d328d41c..2960074dd2 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -138,8 +138,6 @@ public:
virtual bool start_passthrough() { return false; }
virtual void stop_passthrough() {}
- virtual void notification(int p_what){};
-
XRInterface();
~XRInterface();
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 89752b3017..2142ecd262 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -58,8 +58,6 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_post_draw_viewport, "render_target", "screen_rect");
GDVIRTUAL_BIND(_end_frame);
- GDVIRTUAL_BIND(_notification, "what");
-
/** input and output **/
GDVIRTUAL_BIND(_get_suggested_tracker_names);
@@ -309,10 +307,6 @@ void XRInterfaceExtension::end_frame() {
GDVIRTUAL_CALL(_end_frame);
}
-void XRInterfaceExtension::notification(int p_what) {
- GDVIRTUAL_CALL(_notification, p_what);
-}
-
RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
// In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine.
// So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too.
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 2235b57cb3..123626864d 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -123,7 +123,6 @@ public:
virtual bool pre_draw_viewport(RID p_render_target) override;
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void end_frame() override;
- virtual void notification(int p_what) override;
GDVIRTUAL0(_process);
GDVIRTUAL0(_pre_render);
@@ -131,8 +130,6 @@ public:
GDVIRTUAL2(_post_draw_viewport, RID, const Rect2 &);
GDVIRTUAL0(_end_frame);
- GDVIRTUAL1(_notification, int);
-
/* access to some internals we need */
RID get_render_target_texture(RID p_render_target);
// RID get_render_target_depth(RID p_render_target);
diff --git a/tests/core/math/test_math_funcs.h b/tests/core/math/test_math_funcs.h
index c468e73b74..c9d14bbd21 100644
--- a/tests/core/math/test_math_funcs.h
+++ b/tests/core/math/test_math_funcs.h
@@ -88,290 +88,280 @@ TEST_CASE("[Math] Power of two functions") {
CHECK(nearest_shift(65535) == 16);
}
-TEST_CASE("[Math] abs") {
- // int
- CHECK(Math::abs(-1) == 1);
- CHECK(Math::abs(0) == 0);
- CHECK(Math::abs(1) == 1);
-
- // double
- CHECK(Math::abs(-0.1) == 0.1);
- CHECK(Math::abs(0.0) == 0.0);
- CHECK(Math::abs(0.1) == 0.1);
-
- // float
- CHECK(Math::abs(-0.1f) == 0.1f);
- CHECK(Math::abs(0.0f) == 0.0f);
- CHECK(Math::abs(0.1f) == 0.1f);
-}
-
-TEST_CASE("[Math] round/floor/ceil") {
- CHECK(Math::round(1.5) == 2.0);
- CHECK(Math::round(1.6) == 2.0);
- CHECK(Math::round(-1.5) == -2.0);
- CHECK(Math::round(-1.1) == -1.0);
-
- CHECK(Math::floor(1.5) == 1.0);
- CHECK(Math::floor(-1.5) == -2.0);
-
- CHECK(Math::ceil(1.5) == 2.0);
- CHECK(Math::ceil(-1.9) == -1.0);
-}
-
-TEST_CASE("[Math] sin/cos/tan") {
- CHECK(Math::sin(-0.1) == doctest::Approx(-0.0998334166));
- CHECK(Math::sin(0.1) == doctest::Approx(0.0998334166));
- CHECK(Math::sin(0.5) == doctest::Approx(0.4794255386));
- CHECK(Math::sin(1.0) == doctest::Approx(0.8414709848));
- CHECK(Math::sin(1.5) == doctest::Approx(0.9974949866));
- CHECK(Math::sin(450.0) == doctest::Approx(-0.683283725));
-
- CHECK(Math::cos(-0.1) == doctest::Approx(0.99500416530));
- CHECK(Math::cos(0.1) == doctest::Approx(0.9950041653));
- CHECK(Math::cos(0.5) == doctest::Approx(0.8775825619));
- CHECK(Math::cos(1.0) == doctest::Approx(0.5403023059));
- CHECK(Math::cos(1.5) == doctest::Approx(0.0707372017));
- CHECK(Math::cos(450.0) == doctest::Approx(-0.7301529642));
-
- CHECK(Math::tan(-0.1) == doctest::Approx(-0.1003346721));
- CHECK(Math::tan(0.1) == doctest::Approx(0.1003346721));
- CHECK(Math::tan(0.5) == doctest::Approx(0.5463024898));
- CHECK(Math::tan(1.0) == doctest::Approx(1.5574077247));
- CHECK(Math::tan(1.5) == doctest::Approx(14.1014199472));
- CHECK(Math::tan(450.0) == doctest::Approx(0.9358090134));
-}
-
-TEST_CASE("[Math] sinh/cosh/tanh") {
- CHECK(Math::sinh(-0.1) == doctest::Approx(-0.10016675));
- CHECK(Math::sinh(0.1) == doctest::Approx(0.10016675));
- CHECK(Math::sinh(0.5) == doctest::Approx(0.5210953055));
- CHECK(Math::sinh(1.0) == doctest::Approx(1.1752011936));
- CHECK(Math::sinh(1.5) == doctest::Approx(2.1292794551));
-
- CHECK(Math::cosh(-0.1) == doctest::Approx(1.0050041681));
- CHECK(Math::cosh(0.1) == doctest::Approx(1.0050041681));
- CHECK(Math::cosh(0.5) == doctest::Approx(1.1276259652));
- CHECK(Math::cosh(1.0) == doctest::Approx(1.5430806348));
- CHECK(Math::cosh(1.5) == doctest::Approx(2.3524096152));
-
- CHECK(Math::tanh(-0.1) == doctest::Approx(-0.0996679946));
- CHECK(Math::tanh(0.1) == doctest::Approx(0.0996679946));
- CHECK(Math::tanh(0.5) == doctest::Approx(0.4621171573));
- CHECK(Math::tanh(1.0) == doctest::Approx(0.761594156));
- CHECK(Math::tanh(1.5) == doctest::Approx(0.9051482536));
- CHECK(Math::tanh(450.0) == doctest::Approx(1.0));
-}
-
-TEST_CASE("[Math] asin/acos/atan") {
- CHECK(Math::asin(-0.1) == doctest::Approx(-0.1001674212));
- CHECK(Math::asin(0.1) == doctest::Approx(0.1001674212));
- CHECK(Math::asin(0.5) == doctest::Approx(0.5235987756));
- CHECK(Math::asin(1.0) == doctest::Approx(1.5707963268));
- CHECK(Math::is_nan(Math::asin(1.5)));
- CHECK(Math::is_nan(Math::asin(450.0)));
-
- CHECK(Math::acos(-0.1) == doctest::Approx(1.670963748));
- CHECK(Math::acos(0.1) == doctest::Approx(1.4706289056));
- CHECK(Math::acos(0.5) == doctest::Approx(1.0471975512));
- CHECK(Math::acos(1.0) == doctest::Approx(0.0));
- CHECK(Math::is_nan(Math::acos(1.5)));
- CHECK(Math::is_nan(Math::acos(450.0)));
-
- CHECK(Math::atan(-0.1) == doctest::Approx(-0.0996686525));
- CHECK(Math::atan(0.1) == doctest::Approx(0.0996686525));
- CHECK(Math::atan(0.5) == doctest::Approx(0.463647609));
- CHECK(Math::atan(1.0) == doctest::Approx(0.7853981634));
- CHECK(Math::atan(1.5) == doctest::Approx(0.9827937232));
- CHECK(Math::atan(450.0) == doctest::Approx(1.5685741082));
-}
-
-TEST_CASE("[Math] sinc/sincn/atan2") {
- CHECK(Math::sinc(-0.1) == doctest::Approx(0.9983341665));
- CHECK(Math::sinc(0.1) == doctest::Approx(0.9983341665));
- CHECK(Math::sinc(0.5) == doctest::Approx(0.9588510772));
- CHECK(Math::sinc(1.0) == doctest::Approx(0.8414709848));
- CHECK(Math::sinc(1.5) == doctest::Approx(0.6649966577));
- CHECK(Math::sinc(450.0) == doctest::Approx(-0.0015184083));
-
- CHECK(Math::sincn(-0.1) == doctest::Approx(0.9836316431));
- CHECK(Math::sincn(0.1) == doctest::Approx(0.9836316431));
- CHECK(Math::sincn(0.5) == doctest::Approx(0.6366197724));
- CHECK(Math::sincn(1.0) == doctest::Approx(0.0));
- CHECK(Math::sincn(1.5) == doctest::Approx(-0.2122065908));
- CHECK(Math::sincn(450.0) == doctest::Approx(0.0));
-
- CHECK(Math::atan2(-0.1, 0.5) == doctest::Approx(-0.1973955598));
- CHECK(Math::atan2(0.1, -0.5) == doctest::Approx(2.9441970937));
- CHECK(Math::atan2(0.5, 1.5) == doctest::Approx(0.3217505544));
- CHECK(Math::atan2(1.0, 2.5) == doctest::Approx(0.3805063771));
- CHECK(Math::atan2(1.5, 1.0) == doctest::Approx(0.9827937232));
- CHECK(Math::atan2(450.0, 1.0) == doctest::Approx(1.5685741082));
-}
-
-TEST_CASE("[Math] pow/log/log2/exp/sqrt") {
- CHECK(Math::pow(-0.1, 2.0) == doctest::Approx(0.01));
- CHECK(Math::pow(0.1, 2.5) == doctest::Approx(0.0031622777));
- CHECK(Math::pow(0.5, 0.5) == doctest::Approx(0.7071067812));
- CHECK(Math::pow(1.0, 1.0) == doctest::Approx(1.0));
- CHECK(Math::pow(1.5, -1.0) == doctest::Approx(0.6666666667));
- CHECK(Math::pow(450.0, -2.0) == doctest::Approx(0.0000049383));
- CHECK(Math::pow(450.0, 0.0) == doctest::Approx(1.0));
-
- CHECK(Math::is_nan(Math::log(-0.1)));
- CHECK(Math::log(0.1) == doctest::Approx(-2.302585093));
- CHECK(Math::log(0.5) == doctest::Approx(-0.6931471806));
- CHECK(Math::log(1.0) == doctest::Approx(0.0));
- CHECK(Math::log(1.5) == doctest::Approx(0.4054651081));
- CHECK(Math::log(450.0) == doctest::Approx(6.1092475828));
-
- CHECK(Math::is_nan(Math::log2(-0.1)));
- CHECK(Math::log2(0.1) == doctest::Approx(-3.3219280949));
- CHECK(Math::log2(0.5) == doctest::Approx(-1.0));
- CHECK(Math::log2(1.0) == doctest::Approx(0.0));
- CHECK(Math::log2(1.5) == doctest::Approx(0.5849625007));
- CHECK(Math::log2(450.0) == doctest::Approx(8.8137811912));
-
- CHECK(Math::exp(-0.1) == doctest::Approx(0.904837418));
- CHECK(Math::exp(0.1) == doctest::Approx(1.1051709181));
- CHECK(Math::exp(0.5) == doctest::Approx(1.6487212707));
- CHECK(Math::exp(1.0) == doctest::Approx(2.7182818285));
- CHECK(Math::exp(1.5) == doctest::Approx(4.4816890703));
-
- CHECK(Math::is_nan(Math::sqrt(-0.1)));
- CHECK(Math::sqrt(0.1) == doctest::Approx(0.316228));
- CHECK(Math::sqrt(0.5) == doctest::Approx(0.707107));
- CHECK(Math::sqrt(1.0) == doctest::Approx(1.0));
- CHECK(Math::sqrt(1.5) == doctest::Approx(1.224745));
-}
-
-TEST_CASE("[Math] is_nan/is_inf") {
- CHECK(!Math::is_nan(0.0));
- CHECK(Math::is_nan(NAN));
-
- CHECK(!Math::is_inf(0.0));
- CHECK(Math::is_inf(INFINITY));
-}
-
-TEST_CASE("[Math] linear_to_db") {
- CHECK(Math::linear_to_db(1.0) == doctest::Approx(0.0));
- CHECK(Math::linear_to_db(20.0) == doctest::Approx(26.0206));
- CHECK(Math::is_inf(Math::linear_to_db(0.0)));
- CHECK(Math::is_nan(Math::linear_to_db(-20.0)));
-}
-
-TEST_CASE("[Math] db_to_linear") {
- CHECK(Math::db_to_linear(0.0) == doctest::Approx(1.0));
- CHECK(Math::db_to_linear(1.0) == doctest::Approx(1.122018));
- CHECK(Math::db_to_linear(20.0) == doctest::Approx(10.0));
- CHECK(Math::db_to_linear(-20.0) == doctest::Approx(0.1));
-}
-
-TEST_CASE("[Math] step_decimals") {
- CHECK(Math::step_decimals(-0.5) == 1);
- CHECK(Math::step_decimals(0) == 0);
- CHECK(Math::step_decimals(1) == 0);
- CHECK(Math::step_decimals(0.1) == 1);
- CHECK(Math::step_decimals(0.01) == 2);
- CHECK(Math::step_decimals(0.001) == 3);
- CHECK(Math::step_decimals(0.0001) == 4);
- CHECK(Math::step_decimals(0.00001) == 5);
- CHECK(Math::step_decimals(0.000001) == 6);
- CHECK(Math::step_decimals(0.0000001) == 7);
- CHECK(Math::step_decimals(0.00000001) == 8);
- CHECK(Math::step_decimals(0.000000001) == 9);
+TEST_CASE_TEMPLATE("[Math] abs", T, int, float, double) {
+ CHECK(Math::abs((T)-1) == (T)1);
+ CHECK(Math::abs((T)0) == (T)0);
+ CHECK(Math::abs((T)1) == (T)1);
+ CHECK(Math::abs((T)0.1) == (T)0.1);
+}
+
+TEST_CASE_TEMPLATE("[Math] round/floor/ceil", T, float, double) {
+ CHECK(Math::round((T)1.5) == (T)2.0);
+ CHECK(Math::round((T)1.6) == (T)2.0);
+ CHECK(Math::round((T)-1.5) == (T)-2.0);
+ CHECK(Math::round((T)-1.1) == (T)-1.0);
+
+ CHECK(Math::floor((T)1.5) == (T)1.0);
+ CHECK(Math::floor((T)-1.5) == (T)-2.0);
+
+ CHECK(Math::ceil((T)1.5) == (T)2.0);
+ CHECK(Math::ceil((T)-1.9) == (T)-1.0);
+}
+
+TEST_CASE_TEMPLATE("[Math] sin/cos/tan", T, float, double) {
+ CHECK(Math::sin((T)-0.1) == doctest::Approx((T)-0.0998334166));
+ CHECK(Math::sin((T)0.1) == doctest::Approx((T)0.0998334166));
+ CHECK(Math::sin((T)0.5) == doctest::Approx((T)0.4794255386));
+ CHECK(Math::sin((T)1.0) == doctest::Approx((T)0.8414709848));
+ CHECK(Math::sin((T)1.5) == doctest::Approx((T)0.9974949866));
+ CHECK(Math::sin((T)450.0) == doctest::Approx((T)-0.683283725));
+
+ CHECK(Math::cos((T)-0.1) == doctest::Approx((T)0.99500416530));
+ CHECK(Math::cos((T)0.1) == doctest::Approx((T)0.9950041653));
+ CHECK(Math::cos((T)0.5) == doctest::Approx((T)0.8775825619));
+ CHECK(Math::cos((T)1.0) == doctest::Approx((T)0.5403023059));
+ CHECK(Math::cos((T)1.5) == doctest::Approx((T)0.0707372017));
+ CHECK(Math::cos((T)450.0) == doctest::Approx((T)-0.7301529642));
+
+ CHECK(Math::tan((T)-0.1) == doctest::Approx((T)-0.1003346721));
+ CHECK(Math::tan((T)0.1) == doctest::Approx((T)0.1003346721));
+ CHECK(Math::tan((T)0.5) == doctest::Approx((T)0.5463024898));
+ CHECK(Math::tan((T)1.0) == doctest::Approx((T)1.5574077247));
+ CHECK(Math::tan((T)1.5) == doctest::Approx((T)14.1014199472));
+ CHECK(Math::tan((T)450.0) == doctest::Approx((T)0.9358090134));
+}
+
+TEST_CASE_TEMPLATE("[Math] sinh/cosh/tanh", T, float, double) {
+ CHECK(Math::sinh((T)-0.1) == doctest::Approx((T)-0.10016675));
+ CHECK(Math::sinh((T)0.1) == doctest::Approx((T)0.10016675));
+ CHECK(Math::sinh((T)0.5) == doctest::Approx((T)0.5210953055));
+ CHECK(Math::sinh((T)1.0) == doctest::Approx((T)1.1752011936));
+ CHECK(Math::sinh((T)1.5) == doctest::Approx((T)2.1292794551));
+
+ CHECK(Math::cosh((T)-0.1) == doctest::Approx((T)1.0050041681));
+ CHECK(Math::cosh((T)0.1) == doctest::Approx((T)1.0050041681));
+ CHECK(Math::cosh((T)0.5) == doctest::Approx((T)1.1276259652));
+ CHECK(Math::cosh((T)1.0) == doctest::Approx((T)1.5430806348));
+ CHECK(Math::cosh((T)1.5) == doctest::Approx((T)2.3524096152));
+
+ CHECK(Math::tanh((T)-0.1) == doctest::Approx((T)-0.0996679946));
+ CHECK(Math::tanh((T)0.1) == doctest::Approx((T)0.0996679946));
+ CHECK(Math::tanh((T)0.5) == doctest::Approx((T)0.4621171573));
+ CHECK(Math::tanh((T)1.0) == doctest::Approx((T)0.761594156));
+ CHECK(Math::tanh((T)1.5) == doctest::Approx((T)0.9051482536));
+ CHECK(Math::tanh((T)450.0) == doctest::Approx((T)1.0));
+}
+
+TEST_CASE_TEMPLATE("[Math] asin/acos/atan", T, float, double) {
+ CHECK(Math::asin((T)-0.1) == doctest::Approx((T)-0.1001674212));
+ CHECK(Math::asin((T)0.1) == doctest::Approx((T)0.1001674212));
+ CHECK(Math::asin((T)0.5) == doctest::Approx((T)0.5235987756));
+ CHECK(Math::asin((T)1.0) == doctest::Approx((T)1.5707963268));
+ CHECK(Math::is_nan(Math::asin((T)1.5)));
+ CHECK(Math::is_nan(Math::asin((T)450.0)));
+
+ CHECK(Math::acos((T)-0.1) == doctest::Approx((T)1.670963748));
+ CHECK(Math::acos((T)0.1) == doctest::Approx((T)1.4706289056));
+ CHECK(Math::acos((T)0.5) == doctest::Approx((T)1.0471975512));
+ CHECK(Math::acos((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::is_nan(Math::acos((T)1.5)));
+ CHECK(Math::is_nan(Math::acos((T)450.0)));
+
+ CHECK(Math::atan((T)-0.1) == doctest::Approx((T)-0.0996686525));
+ CHECK(Math::atan((T)0.1) == doctest::Approx((T)0.0996686525));
+ CHECK(Math::atan((T)0.5) == doctest::Approx((T)0.463647609));
+ CHECK(Math::atan((T)1.0) == doctest::Approx((T)0.7853981634));
+ CHECK(Math::atan((T)1.5) == doctest::Approx((T)0.9827937232));
+ CHECK(Math::atan((T)450.0) == doctest::Approx((T)1.5685741082));
+}
+
+TEST_CASE_TEMPLATE("[Math] sinc/sincn/atan2", T, float, double) {
+ CHECK(Math::sinc((T)-0.1) == doctest::Approx((T)0.9983341665));
+ CHECK(Math::sinc((T)0.1) == doctest::Approx((T)0.9983341665));
+ CHECK(Math::sinc((T)0.5) == doctest::Approx((T)0.9588510772));
+ CHECK(Math::sinc((T)1.0) == doctest::Approx((T)0.8414709848));
+ CHECK(Math::sinc((T)1.5) == doctest::Approx((T)0.6649966577));
+ CHECK(Math::sinc((T)450.0) == doctest::Approx((T)-0.0015184083));
+
+ CHECK(Math::sincn((T)-0.1) == doctest::Approx((T)0.9836316431));
+ CHECK(Math::sincn((T)0.1) == doctest::Approx((T)0.9836316431));
+ CHECK(Math::sincn((T)0.5) == doctest::Approx((T)0.6366197724));
+ CHECK(Math::sincn((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::sincn((T)1.5) == doctest::Approx((T)-0.2122065908));
+ CHECK(Math::sincn((T)450.0) == doctest::Approx((T)0.0));
+
+ CHECK(Math::atan2((T)-0.1, (T)0.5) == doctest::Approx((T)-0.1973955598));
+ CHECK(Math::atan2((T)0.1, (T)-0.5) == doctest::Approx((T)2.9441970937));
+ CHECK(Math::atan2((T)0.5, (T)1.5) == doctest::Approx((T)0.3217505544));
+ CHECK(Math::atan2((T)1.0, (T)2.5) == doctest::Approx((T)0.3805063771));
+ CHECK(Math::atan2((T)1.5, (T)1.0) == doctest::Approx((T)0.9827937232));
+ CHECK(Math::atan2((T)450.0, (T)1.0) == doctest::Approx((T)1.5685741082));
+}
+
+TEST_CASE_TEMPLATE("[Math] pow/log/log2/exp/sqrt", T, float, double) {
+ CHECK(Math::pow((T)-0.1, (T)2.0) == doctest::Approx((T)0.01));
+ CHECK(Math::pow((T)0.1, (T)2.5) == doctest::Approx((T)0.0031622777));
+ CHECK(Math::pow((T)0.5, (T)0.5) == doctest::Approx((T)0.7071067812));
+ CHECK(Math::pow((T)1.0, (T)1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::pow((T)1.5, (T)-1.0) == doctest::Approx((T)0.6666666667));
+ CHECK(Math::pow((T)450.0, (T)-2.0) == doctest::Approx((T)0.0000049383));
+ CHECK(Math::pow((T)450.0, (T)0.0) == doctest::Approx((T)1.0));
+
+ CHECK(Math::is_nan(Math::log((T)-0.1)));
+ CHECK(Math::log((T)0.1) == doctest::Approx((T)-2.302585093));
+ CHECK(Math::log((T)0.5) == doctest::Approx((T)-0.6931471806));
+ CHECK(Math::log((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::log((T)1.5) == doctest::Approx((T)0.4054651081));
+ CHECK(Math::log((T)450.0) == doctest::Approx((T)6.1092475828));
+
+ CHECK(Math::is_nan(Math::log2((T)-0.1)));
+ CHECK(Math::log2((T)0.1) == doctest::Approx((T)-3.3219280949));
+ CHECK(Math::log2((T)0.5) == doctest::Approx((T)-1.0));
+ CHECK(Math::log2((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::log2((T)1.5) == doctest::Approx((T)0.5849625007));
+ CHECK(Math::log2((T)450.0) == doctest::Approx((T)8.8137811912));
+
+ CHECK(Math::exp((T)-0.1) == doctest::Approx((T)0.904837418));
+ CHECK(Math::exp((T)0.1) == doctest::Approx((T)1.1051709181));
+ CHECK(Math::exp((T)0.5) == doctest::Approx((T)1.6487212707));
+ CHECK(Math::exp((T)1.0) == doctest::Approx((T)2.7182818285));
+ CHECK(Math::exp((T)1.5) == doctest::Approx((T)4.4816890703));
+
+ CHECK(Math::is_nan(Math::sqrt((T)-0.1)));
+ CHECK(Math::sqrt((T)0.1) == doctest::Approx((T)0.316228));
+ CHECK(Math::sqrt((T)0.5) == doctest::Approx((T)0.707107));
+ CHECK(Math::sqrt((T)1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::sqrt((T)1.5) == doctest::Approx((T)1.224745));
+}
+
+TEST_CASE_TEMPLATE("[Math] is_nan/is_inf", T, float, double) {
+ CHECK(!Math::is_nan((T)0.0));
+ CHECK(Math::is_nan((T)NAN));
+
+ CHECK(!Math::is_inf((T)0.0));
+ CHECK(Math::is_inf((T)INFINITY));
+}
+
+TEST_CASE_TEMPLATE("[Math] linear_to_db", T, float, double) {
+ CHECK(Math::linear_to_db((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::linear_to_db((T)20.0) == doctest::Approx((T)26.0206));
+ CHECK(Math::is_inf(Math::linear_to_db((T)0.0)));
+ CHECK(Math::is_nan(Math::linear_to_db((T)-20.0)));
+}
+
+TEST_CASE_TEMPLATE("[Math] db_to_linear", T, float, double) {
+ CHECK(Math::db_to_linear((T)0.0) == doctest::Approx((T)1.0));
+ CHECK(Math::db_to_linear((T)1.0) == doctest::Approx((T)1.122018));
+ CHECK(Math::db_to_linear((T)20.0) == doctest::Approx((T)10.0));
+ CHECK(Math::db_to_linear((T)-20.0) == doctest::Approx((T)0.1));
+}
+
+TEST_CASE_TEMPLATE("[Math] step_decimals", T, float, double) {
+ CHECK(Math::step_decimals((T)-0.5) == 1);
+ CHECK(Math::step_decimals((T)0) == 0);
+ CHECK(Math::step_decimals((T)1) == 0);
+ CHECK(Math::step_decimals((T)0.1) == 1);
+ CHECK(Math::step_decimals((T)0.01) == 2);
+ CHECK(Math::step_decimals((T)0.001) == 3);
+ CHECK(Math::step_decimals((T)0.0001) == 4);
+ CHECK(Math::step_decimals((T)0.00001) == 5);
+ CHECK(Math::step_decimals((T)0.000001) == 6);
+ CHECK(Math::step_decimals((T)0.0000001) == 7);
+ CHECK(Math::step_decimals((T)0.00000001) == 8);
+ CHECK(Math::step_decimals((T)0.000000001) == 9);
// Too many decimals to handle.
- CHECK(Math::step_decimals(0.0000000001) == 0);
+ CHECK(Math::step_decimals((T)0.0000000001) == 0);
}
-TEST_CASE("[Math] range_step_decimals") {
- CHECK(Math::range_step_decimals(0.000000001) == 9);
+TEST_CASE_TEMPLATE("[Math] range_step_decimals", T, float, double) {
+ CHECK(Math::range_step_decimals((T)0.000000001) == 9);
// Too many decimals to handle.
- CHECK(Math::range_step_decimals(0.0000000001) == 0);
+ CHECK(Math::range_step_decimals((T)0.0000000001) == 0);
// Should be treated as a step of 0 for use by the editor.
- CHECK(Math::range_step_decimals(0.0) == 16);
- CHECK(Math::range_step_decimals(-0.5) == 16);
+ CHECK(Math::range_step_decimals((T)0.0) == 16);
+ CHECK(Math::range_step_decimals((T)-0.5) == 16);
}
-TEST_CASE("[Math] lerp") {
- CHECK(Math::lerp(2.0, 5.0, -0.1) == doctest::Approx(1.7));
- CHECK(Math::lerp(2.0, 5.0, 0.0) == doctest::Approx(2.0));
- CHECK(Math::lerp(2.0, 5.0, 0.1) == doctest::Approx(2.3));
- CHECK(Math::lerp(2.0, 5.0, 1.0) == doctest::Approx(5.0));
- CHECK(Math::lerp(2.0, 5.0, 2.0) == doctest::Approx(8.0));
+TEST_CASE_TEMPLATE("[Math] lerp", T, float, double) {
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)-0.1) == doctest::Approx((T)1.7));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.0) == doctest::Approx((T)2.0));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)0.1) == doctest::Approx((T)2.3));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)1.0) == doctest::Approx((T)5.0));
+ CHECK(Math::lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)8.0));
- CHECK(Math::lerp(-2.0, -5.0, -0.1) == doctest::Approx(-1.7));
- CHECK(Math::lerp(-2.0, -5.0, 0.0) == doctest::Approx(-2.0));
- CHECK(Math::lerp(-2.0, -5.0, 0.1) == doctest::Approx(-2.3));
- CHECK(Math::lerp(-2.0, -5.0, 1.0) == doctest::Approx(-5.0));
- CHECK(Math::lerp(-2.0, -5.0, 2.0) == doctest::Approx(-8.0));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)-0.1) == doctest::Approx((T)-1.7));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.0) == doctest::Approx((T)-2.0));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)0.1) == doctest::Approx((T)-2.3));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)1.0) == doctest::Approx((T)-5.0));
+ CHECK(Math::lerp((T)-2.0, (T)-5.0, (T)2.0) == doctest::Approx((T)-8.0));
}
-TEST_CASE("[Math] inverse_lerp") {
- CHECK(Math::inverse_lerp(2.0, 5.0, 1.7) == doctest::Approx(-0.1));
- CHECK(Math::inverse_lerp(2.0, 5.0, 2.0) == doctest::Approx(0.0));
- CHECK(Math::inverse_lerp(2.0, 5.0, 2.3) == doctest::Approx(0.1));
- CHECK(Math::inverse_lerp(2.0, 5.0, 5.0) == doctest::Approx(1.0));
- CHECK(Math::inverse_lerp(2.0, 5.0, 8.0) == doctest::Approx(2.0));
+TEST_CASE_TEMPLATE("[Math] inverse_lerp", T, float, double) {
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)1.7) == doctest::Approx((T)-0.1));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.0) == doctest::Approx((T)0.0));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)2.3) == doctest::Approx((T)0.1));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)5.0) == doctest::Approx((T)1.0));
+ CHECK(Math::inverse_lerp((T)2.0, (T)5.0, (T)8.0) == doctest::Approx((T)2.0));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -1.7) == doctest::Approx(-0.1));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -2.0) == doctest::Approx(0.0));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -2.3) == doctest::Approx(0.1));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -5.0) == doctest::Approx(1.0));
- CHECK(Math::inverse_lerp(-2.0, -5.0, -8.0) == doctest::Approx(2.0));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-1.7) == doctest::Approx((T)-0.1));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.0) == doctest::Approx((T)0.0));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-2.3) == doctest::Approx((T)0.1));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-5.0) == doctest::Approx((T)1.0));
+ CHECK(Math::inverse_lerp((T)-2.0, (T)-5.0, (T)-8.0) == doctest::Approx((T)2.0));
}
-TEST_CASE("[Math] remap") {
- CHECK(Math::remap(50.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(-500.0));
- CHECK(Math::remap(100.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(0.0));
- CHECK(Math::remap(200.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(1000.0));
- CHECK(Math::remap(250.0, 100.0, 200.0, 0.0, 1000.0) == doctest::Approx(1500.0));
+TEST_CASE_TEMPLATE("[Math] remap", T, float, double) {
+ CHECK(Math::remap((T)50.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));
+ CHECK(Math::remap((T)100.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));
+ CHECK(Math::remap((T)200.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));
+ CHECK(Math::remap((T)250.0, (T)100.0, (T)200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));
- CHECK(Math::remap(-50.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(-500.0));
- CHECK(Math::remap(-100.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(0.0));
- CHECK(Math::remap(-200.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(1000.0));
- CHECK(Math::remap(-250.0, -100.0, -200.0, 0.0, 1000.0) == doctest::Approx(1500.0));
+ CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)-500.0));
+ CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)0.0));
+ CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1000.0));
+ CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)1000.0) == doctest::Approx((T)1500.0));
- CHECK(Math::remap(-50.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(500.0));
- CHECK(Math::remap(-100.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(0.0));
- CHECK(Math::remap(-200.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(-1000.0));
- CHECK(Math::remap(-250.0, -100.0, -200.0, 0.0, -1000.0) == doctest::Approx(-1500.0));
+ CHECK(Math::remap((T)-50.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)500.0));
+ CHECK(Math::remap((T)-100.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)0.0));
+ CHECK(Math::remap((T)-200.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1000.0));
+ CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1500.0));
}
-TEST_CASE("[Math] lerp_angle") {
+TEST_CASE_TEMPLATE("[Math] lerp_angle", T, float, double) {
// Counter-clockwise rotation.
- CHECK(Math::lerp_angle(0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(-0.005 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)-0.005 * Math_TAU));
// Counter-clockwise rotation.
- CHECK(Math::lerp_angle(0.25 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(0.0));
+ CHECK(Math::lerp_angle((T)0.25 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.0));
// Clockwise rotation.
- CHECK(Math::lerp_angle(0.26 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx(0.505 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.26 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.505 * Math_TAU));
- CHECK(Math::lerp_angle(-0.25 * Math_TAU, 1.25 * Math_TAU, 0.5) == doctest::Approx(-0.5 * Math_TAU));
- CHECK(Math::lerp_angle(0.72 * Math_TAU, 1.44 * Math_TAU, 0.96) == doctest::Approx(0.4512 * Math_TAU));
- CHECK(Math::lerp_angle(0.72 * Math_TAU, 1.44 * Math_TAU, 1.04) == doctest::Approx(0.4288 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-0.25 * Math_TAU, 1.25 * Math_TAU, 0.5) == doctest::Approx((T)-0.5 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 0.96) == doctest::Approx((T)0.4512 * Math_TAU));
+ CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 1.04) == doctest::Approx((T)0.4288 * Math_TAU));
// Initial and final angles are effectively identical, so the value returned
// should always be the same regardless of the `weight` parameter.
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, -1.0) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 0.0) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 0.5) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 1.0) == doctest::Approx(-4.0 * Math_TAU));
- CHECK(Math::lerp_angle(-4 * Math_TAU, 4 * Math_TAU, 500.0) == doctest::Approx(-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, -1.0) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.0) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.5) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 1.0) == doctest::Approx((T)-4.0 * Math_TAU));
+ CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 500.0) == doctest::Approx((T)-4.0 * Math_TAU));
}
-TEST_CASE("[Math] move_toward") {
- CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx(1.0));
- CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx(4.5));
- CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx(5.0));
- CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx(-1.0));
- CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx(-4.5));
- CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx(-5.0));
+TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) {
+ CHECK(Math::move_toward(2.0, 5.0, -1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::move_toward(2.0, 5.0, 2.5) == doctest::Approx((T)4.5));
+ CHECK(Math::move_toward(2.0, 5.0, 4.0) == doctest::Approx((T)5.0));
+ CHECK(Math::move_toward(-2.0, -5.0, -1.0) == doctest::Approx((T)-1.0));
+ CHECK(Math::move_toward(-2.0, -5.0, 2.5) == doctest::Approx((T)-4.5));
+ CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx((T)-5.0));
}
-TEST_CASE("[Math] smoothstep") {
- CHECK(Math::smoothstep(0.0, 2.0, -5.0) == doctest::Approx(0.0));
- CHECK(Math::smoothstep(0.0, 2.0, 0.5) == doctest::Approx(0.15625));
- CHECK(Math::smoothstep(0.0, 2.0, 1.0) == doctest::Approx(0.5));
- CHECK(Math::smoothstep(0.0, 2.0, 2.0) == doctest::Approx(1.0));
+TEST_CASE_TEMPLATE("[Math] smoothstep", T, float, double) {
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)-5.0) == doctest::Approx((T)0.0));
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)0.5) == doctest::Approx((T)0.15625));
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)1.0) == doctest::Approx((T)0.5));
+ CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)2.0) == doctest::Approx((T)1.0));
}
TEST_CASE("[Math] ease") {
@@ -429,34 +419,34 @@ TEST_CASE("[Math] larger_prime") {
ERR_PRINT_ON;
}
-TEST_CASE("[Math] fmod") {
- CHECK(Math::fmod(-2.0, 0.3) == doctest::Approx(-0.2));
- CHECK(Math::fmod(0.0, 0.3) == doctest::Approx(0.0));
- CHECK(Math::fmod(2.0, 0.3) == doctest::Approx(0.2));
+TEST_CASE_TEMPLATE("[Math] fmod", T, float, double) {
+ CHECK(Math::fmod((T)-2.0, (T)0.3) == doctest::Approx((T)-0.2));
+ CHECK(Math::fmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
- CHECK(Math::fmod(-2.0, -0.3) == doctest::Approx(-0.2));
- CHECK(Math::fmod(0.0, -0.3) == doctest::Approx(0.0));
- CHECK(Math::fmod(2.0, -0.3) == doctest::Approx(0.2));
+ CHECK(Math::fmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));
+ CHECK(Math::fmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fmod((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));
}
-TEST_CASE("[Math] fposmod") {
- CHECK(Math::fposmod(-2.0, 0.3) == doctest::Approx(0.1));
- CHECK(Math::fposmod(0.0, 0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmod(2.0, 0.3) == doctest::Approx(0.2));
+TEST_CASE_TEMPLATE("[Math] fposmod", T, float, double) {
+ CHECK(Math::fposmod((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));
+ CHECK(Math::fposmod((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmod((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
- CHECK(Math::fposmod(-2.0, -0.3) == doctest::Approx(-0.2));
- CHECK(Math::fposmod(0.0, -0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmod(2.0, -0.3) == doctest::Approx(-0.1));
+ CHECK(Math::fposmod((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.2));
+ CHECK(Math::fposmod((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmod((T)2.0, (T)-0.3) == doctest::Approx((T)-0.1));
}
-TEST_CASE("[Math] fposmodp") {
- CHECK(Math::fposmodp(-2.0, 0.3) == doctest::Approx(0.1));
- CHECK(Math::fposmodp(0.0, 0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmodp(2.0, 0.3) == doctest::Approx(0.2));
+TEST_CASE_TEMPLATE("[Math] fposmodp", T, float, double) {
+ CHECK(Math::fposmodp((T)-2.0, (T)0.3) == doctest::Approx((T)0.1));
+ CHECK(Math::fposmodp((T)0.0, (T)0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmodp((T)2.0, (T)0.3) == doctest::Approx((T)0.2));
- CHECK(Math::fposmodp(-2.0, -0.3) == doctest::Approx(-0.5));
- CHECK(Math::fposmodp(0.0, -0.3) == doctest::Approx(0.0));
- CHECK(Math::fposmodp(2.0, -0.3) == doctest::Approx(0.2));
+ CHECK(Math::fposmodp((T)-2.0, (T)-0.3) == doctest::Approx((T)-0.5));
+ CHECK(Math::fposmodp((T)0.0, (T)-0.3) == doctest::Approx((T)0.0));
+ CHECK(Math::fposmodp((T)2.0, (T)-0.3) == doctest::Approx((T)0.2));
}
TEST_CASE("[Math] posmod") {
@@ -475,80 +465,83 @@ TEST_CASE("[Math] wrapi") {
CHECK(Math::wrapi(300'000'000'000, -20, 160) == 120);
}
-TEST_CASE("[Math] wrapf") {
- CHECK(Math::wrapf(-30.0, -20.0, 160.0) == doctest::Approx(150.0));
- CHECK(Math::wrapf(30.0, -2.0, 160.0) == doctest::Approx(30.0));
- CHECK(Math::wrapf(300.0, -20.0, 160.0) == doctest::Approx(120.0));
- CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx(120.0));
+TEST_CASE_TEMPLATE("[Math] wrapf", T, float, double) {
+ CHECK(Math::wrapf((T)-30.0, (T)-20.0, (T)160.0) == doctest::Approx((T)150.0));
+ CHECK(Math::wrapf((T)30.0, (T)-2.0, (T)160.0) == doctest::Approx((T)30.0));
+ CHECK(Math::wrapf((T)300.0, (T)-20.0, (T)160.0) == doctest::Approx((T)120.0));
+
+ CHECK(Math::wrapf(300'000'000'000.0, -20.0, 160.0) == doctest::Approx((T)120.0));
+ // float's precision is too low for 300'000'000'000.0, so we reduce it by a factor of 1000.
+ CHECK(Math::wrapf((float)300'000'000.0, (float)-20.0, (float)160.0) == doctest::Approx((T)128.0));
}
-TEST_CASE("[Math] fract") {
- CHECK(Math::fract(1.0) == doctest::Approx(0.0));
- CHECK(Math::fract(77.8) == doctest::Approx(0.8));
- CHECK(Math::fract(-10.1) == doctest::Approx(0.9));
+TEST_CASE_TEMPLATE("[Math] fract", T, float, double) {
+ CHECK(Math::fract((T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::fract((T)77.8) == doctest::Approx((T)0.8));
+ CHECK(Math::fract((T)-10.1) == doctest::Approx((T)0.9));
}
-TEST_CASE("[Math] pingpong") {
- CHECK(Math::pingpong(0.0, 0.0) == doctest::Approx(0.0));
- CHECK(Math::pingpong(1.0, 1.0) == doctest::Approx(1.0));
- CHECK(Math::pingpong(0.5, 2.0) == doctest::Approx(0.5));
- CHECK(Math::pingpong(3.5, 2.0) == doctest::Approx(0.5));
- CHECK(Math::pingpong(11.5, 2.0) == doctest::Approx(0.5));
- CHECK(Math::pingpong(-2.5, 2.0) == doctest::Approx(1.5));
+TEST_CASE_TEMPLATE("[Math] pingpong", T, float, double) {
+ CHECK(Math::pingpong((T)0.0, (T)0.0) == doctest::Approx((T)0.0));
+ CHECK(Math::pingpong((T)1.0, (T)1.0) == doctest::Approx((T)1.0));
+ CHECK(Math::pingpong((T)0.5, (T)2.0) == doctest::Approx((T)0.5));
+ CHECK(Math::pingpong((T)3.5, (T)2.0) == doctest::Approx((T)0.5));
+ CHECK(Math::pingpong((T)11.5, (T)2.0) == doctest::Approx((T)0.5));
+ CHECK(Math::pingpong((T)-2.5, (T)2.0) == doctest::Approx((T)1.5));
}
-TEST_CASE("[Math] deg_to_rad/rad_to_deg") {
- CHECK(Math::deg_to_rad(180.0) == doctest::Approx(Math_PI));
- CHECK(Math::deg_to_rad(-27.0) == doctest::Approx(-0.471239));
+TEST_CASE_TEMPLATE("[Math] deg_to_rad/rad_to_deg", T, float, double) {
+ CHECK(Math::deg_to_rad((T)180.0) == doctest::Approx((T)Math_PI));
+ CHECK(Math::deg_to_rad((T)-27.0) == doctest::Approx((T)-0.471239));
- CHECK(Math::rad_to_deg(Math_PI) == doctest::Approx(180.0));
- CHECK(Math::rad_to_deg(-1.5) == doctest::Approx(-85.94366927));
+ CHECK(Math::rad_to_deg((T)Math_PI) == doctest::Approx((T)180.0));
+ CHECK(Math::rad_to_deg((T)-1.5) == doctest::Approx((T)-85.94366927));
}
-TEST_CASE("[Math] cubic_interpolate") {
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.0) == doctest::Approx(0.2));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.25) == doctest::Approx(0.33125));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.5) == doctest::Approx(0.5));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 0.75) == doctest::Approx(0.66875));
- CHECK(Math::cubic_interpolate(0.2, 0.8, 0.0, 1.0, 1.0) == doctest::Approx(0.8));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate", T, float, double) {
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0) == doctest::Approx((T)0.2));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25) == doctest::Approx((T)0.33125));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75) == doctest::Approx((T)0.66875));
+ CHECK(Math::cubic_interpolate((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0) == doctest::Approx((T)0.8));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, -50.0) == doctest::Approx(-6662732.3));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, -5.0) == doctest::Approx(-9356.3));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 0.0) == doctest::Approx(20.2));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 1.0) == doctest::Approx(30.1));
- CHECK(Math::cubic_interpolate(20.2, 30.1, -100.0, 32.0, 4.0) == doctest::Approx(1853.2));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-50.0) == doctest::Approx((T)-6662732.3));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)-5.0) == doctest::Approx((T)-9356.3));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)0.0) == doctest::Approx((T)20.2));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)1.0) == doctest::Approx((T)30.1));
+ CHECK(Math::cubic_interpolate((T)20.2, (T)30.1, (T)-100.0, (T)32.0, (T)4.0) == doctest::Approx((T)1853.2));
}
-TEST_CASE("[Math] cubic_interpolate_angle") {
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.0) == doctest::Approx(Math_PI * (1.0 / 6.0)));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.25) == doctest::Approx(0.973566));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.5) == doctest::Approx(Math_PI / 2.0));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.75) == doctest::Approx(2.16803));
- CHECK(Math::cubic_interpolate_angle(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 1.0) == doctest::Approx(Math_PI * (5.0 / 6.0)));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle", T, float, double) {
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0) == doctest::Approx((T)Math_PI * (1.0 / 6.0)));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25) == doctest::Approx((T)0.973566));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5) == doctest::Approx((T)Math_PI / 2.0));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75) == doctest::Approx((T)2.16803));
+ CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0)));
}
-TEST_CASE("[Math] cubic_interpolate_in_time") {
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.0, 0.5, 0.0, 1.0) == doctest::Approx(0.0));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.25, 0.5, 0.0, 1.0) == doctest::Approx(0.1625));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.5, 0.5, 0.0, 1.0) == doctest::Approx(0.4));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 0.75, 0.5, 0.0, 1.0) == doctest::Approx(0.6375));
- CHECK(Math::cubic_interpolate_in_time(0.2, 0.8, 0.0, 1.0, 1.0, 0.5, 0.0, 1.0) == doctest::Approx(0.8));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate_in_time", T, float, double) {
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.1625));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.4));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.6375));
+ CHECK(Math::cubic_interpolate_in_time((T)0.2, (T)0.8, (T)0.0, (T)1.0, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.8));
}
-TEST_CASE("[Math] cubic_interpolate_angle_in_time") {
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.0, 0.5, 0.0, 1.0) == doctest::Approx(0.0));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.25, 0.5, 0.0, 1.0) == doctest::Approx(0.494964));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.5, 0.5, 0.0, 1.0) == doctest::Approx(1.27627));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 0.75, 0.5, 0.0, 1.0) == doctest::Approx(2.07394));
- CHECK(Math::cubic_interpolate_angle_in_time(Math_PI * (1.0 / 6.0), Math_PI * (5.0 / 6.0), 0.0, Math_PI, 1.0, 0.5, 0.0, 1.0) == doctest::Approx(Math_PI * (5.0 / 6.0)));
+TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle_in_time", T, float, double) {
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394));
+ CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0)));
}
-TEST_CASE("[Math] bezier_interpolate") {
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.0) == doctest::Approx(0.0));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.25) == doctest::Approx(0.2125));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.5) == doctest::Approx(0.5));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 0.75) == doctest::Approx(0.7875));
- CHECK(Math::bezier_interpolate(0.0, 0.2, 0.8, 1.0, 1.0) == doctest::Approx(1.0));
+TEST_CASE_TEMPLATE("[Math] bezier_interpolate", T, float, double) {
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.0) == doctest::Approx((T)0.0));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.25) == doctest::Approx((T)0.2125));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.5) == doctest::Approx((T)0.5));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)0.75) == doctest::Approx((T)0.7875));
+ CHECK(Math::bezier_interpolate((T)0.0, (T)0.2, (T)0.8, (T)1.0, (T)1.0) == doctest::Approx((T)1.0));
}
} // namespace TestMath
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 7e4e3aa9f0..ebb526b37c 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -516,21 +516,22 @@ TEST_CASE("[String] Splitting") {
s = "1.2;2.3 4.5";
const double slices_d[3] = { 1.2, 2.3, 4.5 };
- Vector<float> f;
- f = s.split_floats(";");
- CHECK(f.size() == 2);
- for (int i = 0; i < f.size(); i++) {
- CHECK(ABS(f[i] - slices_d[i]) <= 0.00001);
+ Vector<double> d_arr;
+ d_arr = s.split_floats(";");
+ CHECK(d_arr.size() == 2);
+ for (int i = 0; i < d_arr.size(); i++) {
+ CHECK(ABS(d_arr[i] - slices_d[i]) <= 0.00001);
}
Vector<String> keys;
keys.push_back(";");
keys.push_back(" ");
- f = s.split_floats_mk(keys);
- CHECK(f.size() == 3);
- for (int i = 0; i < f.size(); i++) {
- CHECK(ABS(f[i] - slices_d[i]) <= 0.00001);
+ Vector<float> f_arr;
+ f_arr = s.split_floats_mk(keys);
+ CHECK(f_arr.size() == 3);
+ for (int i = 0; i < f_arr.size(); i++) {
+ CHECK(ABS(f_arr[i] - slices_d[i]) <= 0.00001);
}
s = "1;2 4";
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
index 7bf56e73cd..58ddd08cdd 100644
--- a/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
+++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_full.glsl
@@ -18,7 +18,7 @@ public:
DISABLE_LIGHTING=1,
};
- _FORCE_INLINE_ void version_bind_shader(RID p_version,ShaderVariant p_variant,uint64_t p_specialization=0) { _version_bind_shader(p_version,p_variant,p_specialization); }
+ _FORCE_INLINE_ bool version_bind_shader(RID p_version,ShaderVariant p_variant,uint64_t p_specialization=0) { return _version_bind_shader(p_version,p_variant,p_specialization); }
protected:
@@ -35,13 +35,14 @@ protected:
{"DISABLE_LIGHTING",false},
};
+ static const Feedback* _feedbacks=nullptr;
static const char _vertex_code[]={
10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,104,105,103,104,112,32,118,101,99,51,32,118,101,114,116,101,120,59,10,10,111,117,116,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,32,61,32,118,101,99,52,40,118,101,114,116,101,120,46,120,44,49,44,48,44,49,41,59,10,125,10,10, 0};
static const char _fragment_code[]={
10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,105,110,116,59,10,10,105,110,32,104,105,103,104,112,32,118,101,99,52,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,59,10,10,118,111,105,100,32,109,97,105,110,40,41,32,123,10,9,104,105,103,104,112,32,102,108,111,97,116,32,100,101,112,116,104,32,61,32,40,40,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,122,32,47,32,112,111,115,105,116,105,111,110,95,105,110,116,101,114,112,46,119,41,32,43,32,49,46,48,41,59,10,9,102,114,97,103,95,99,111,108,111,114,32,61,32,118,101,99,52,40,100,101,112,116,104,41,59,10,125,10, 0};
- _setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines);
+ _setup(_vertex_code,_fragment_code,"VertexFragmentShaderGLES3",0,_uniform_strings,0,_ubo_pairs,0,_feedbacks,0,_texunit_pairs,1,_spec_pairs,1,_variant_defines);
}
};
diff --git a/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
index eaeb5981c0..5ac8092ad0 100644
--- a/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
+++ b/tests/python_build/fixtures/gles3/vertex_fragment_expected_parts.json
@@ -31,6 +31,7 @@
"texunit_names": [],
"ubos": [],
"ubo_names": [],
+ "feedbacks": [],
"vertex_included_files": [],
"fragment_included_files": [],
"reading": "fragment",
diff --git a/tests/scene/test_bit_map.h b/tests/scene/test_bit_map.h
index aca7e5fe22..dc47bd7863 100644
--- a/tests/scene/test_bit_map.h
+++ b/tests/scene/test_bit_map.h
@@ -434,6 +434,37 @@ TEST_CASE("[BitMap] Clip to polygon") {
polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 128, 128));
CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(0, 0, 64, 64), true);
+ bit_map.set_bit_rect(Rect2i(64, 64, 64, 64), true);
+ bit_map.set_bit_rect(Rect2i(192, 128, 64, 64), true);
+ bit_map.set_bit_rect(Rect2i(128, 192, 64, 64), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 256, 256));
+ CHECK_MESSAGE(polygons.size() == 4, "We should have exactly 4 polygons");
+ CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[3].size() == 4, "The polygon should have exactly 4 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit(0, 0, true);
+ bit_map.set_bit(2, 0, true);
+ bit_map.set_bit_rect(Rect2i(1, 1, 1, 2), true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 3, 3));
+ CHECK_MESSAGE(polygons.size() == 3, "We should have exactly 3 polygons");
+ CHECK_MESSAGE(polygons[0].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[1].size() == 4, "The polygon should have exactly 4 points");
+ CHECK_MESSAGE(polygons[2].size() == 4, "The polygon should have exactly 4 points");
+
+ reset_bit_map(bit_map);
+ bit_map.set_bit_rect(Rect2i(0, 0, 2, 1), true);
+ bit_map.set_bit_rect(Rect2i(0, 2, 3, 1), true);
+ bit_map.set_bit(0, 1, true);
+ bit_map.set_bit(2, 1, true);
+ polygons = bit_map.clip_opaque_to_polygons(Rect2i(0, 0, 4, 4));
+ CHECK_MESSAGE(polygons.size() == 1, "We should have exactly 1 polygon");
+ CHECK_MESSAGE(polygons[0].size() == 6, "The polygon should have exactly 6 points");
}
} // namespace TestBitmap
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 383ee3197b..84ed095fd9 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -173,6 +173,23 @@ comments. Apply the patches in the `patches/` folder when syncing on newer upstr
commits.
+## glad
+
+- Upstream: https://github.com/Dav1dde/glad
+- Version: 2.0.2 (f237a2bfcec0d9b82b90ec9af4af265c40de7183, 2022)
+- License: CC0 1.0 and Apache 2.0
+
+Files extracted from upstream source:
+- `LICENSE`
+
+Files generated from [upstream web instance](https://gen.glad.sh/):
+- `KHR/khrplatform.h`
+- `gl.c`
+- `glad/gl.h`
+- `glx.c`
+- `glad/glx.h`
+
+
## glslang
- Upstream: https://github.com/KhronosGroup/glslang
@@ -290,18 +307,15 @@ Files extracted from upstream source:
## libtheora
- Upstream: https://www.theora.org
-- Version: 1.1.1 (2010)
+- Version: git (7180717276af1ebc7da15c83162d6c5d6203aabf, 2020)
- License: BSD-3-Clause
Files extracted from upstream source:
-- all .c, .h in lib/
+- all .c, .h in lib/, except arm/ and c64x/ folders
- all .h files in include/theora/ as theora/
- COPYING and LICENSE
-Upstream patches included in the `patches` directory have been applied
-on top of the 1.1.1 source (not included in any stable release yet).
-
## libvorbis
diff --git a/thirdparty/glad/LICENSE b/thirdparty/glad/LICENSE
index b6e2ca25b0..4965a6bffc 100644
--- a/thirdparty/glad/LICENSE
+++ b/thirdparty/glad/LICENSE
@@ -1,20 +1,63 @@
-The MIT License (MIT)
-
-Copyright (c) 2013-2018 David Herberth
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+The glad source code:
+
+ The MIT License (MIT)
+
+ Copyright (c) 2013-2022 David Herberth
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+The Khronos Specifications:
+
+ Copyright (c) 2013-2020 The Khronos Group Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+The EGL Specification and various headers:
+
+ Copyright (c) 2007-2016 The Khronos Group Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and/or associated documentation files (the
+ "Materials"), to deal in the Materials without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Materials, and to
+ permit persons to whom the Materials are furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Materials.
+
+ THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
diff --git a/thirdparty/glad/gl.c b/thirdparty/glad/gl.c
new file mode 100644
index 0000000000..6be716284c
--- /dev/null
+++ b/thirdparty/glad/gl.c
@@ -0,0 +1,1995 @@
+/**
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/gl.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+int GLAD_GL_ARB_debug_output = 0;
+int GLAD_GL_ARB_framebuffer_object = 0;
+int GLAD_GL_EXT_framebuffer_blit = 0;
+int GLAD_GL_EXT_framebuffer_multisample = 0;
+int GLAD_GL_EXT_framebuffer_object = 0;
+int GLAD_GL_OVR_multiview = 0;
+int GLAD_GL_OVR_multiview2 = 0;
+
+
+
+PFNGLACCUMPROC glad_glAccum = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
+PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
+PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINPROC glad_glBegin = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLBITMAPPROC glad_glBitmap = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCALLLISTPROC glad_glCallList = NULL;
+PFNGLCALLLISTSPROC glad_glCallLists = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
+PFNGLCOLOR3BPROC glad_glColor3b = NULL;
+PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
+PFNGLCOLOR3DPROC glad_glColor3d = NULL;
+PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
+PFNGLCOLOR3FPROC glad_glColor3f = NULL;
+PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
+PFNGLCOLOR3IPROC glad_glColor3i = NULL;
+PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
+PFNGLCOLOR3SPROC glad_glColor3s = NULL;
+PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
+PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
+PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
+PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
+PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
+PFNGLCOLOR3USPROC glad_glColor3us = NULL;
+PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
+PFNGLCOLOR4BPROC glad_glColor4b = NULL;
+PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
+PFNGLCOLOR4DPROC glad_glColor4d = NULL;
+PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
+PFNGLCOLOR4FPROC glad_glColor4f = NULL;
+PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
+PFNGLCOLOR4IPROC glad_glColor4i = NULL;
+PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
+PFNGLCOLOR4SPROC glad_glColor4s = NULL;
+PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
+PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
+PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
+PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
+PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
+PFNGLCOLOR4USPROC glad_glColor4us = NULL;
+PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
+PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
+PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
+PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
+PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
+PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
+PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
+PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL;
+PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
+PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
+PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLENDPROC glad_glEnd = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLENDLISTPROC glad_glEndList = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
+PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
+PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
+PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
+PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
+PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
+PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
+PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
+PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
+PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
+PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
+PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
+PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
+PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
+PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
+PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
+PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
+PFNGLFOGFPROC glad_glFogf = NULL;
+PFNGLFOGFVPROC glad_glFogfv = NULL;
+PFNGLFOGIPROC glad_glFogi = NULL;
+PFNGLFOGIVPROC glad_glFogiv = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLFRUSTUMPROC glad_glFrustum = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL;
+PFNGLGENLISTSPROC glad_glGenLists = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
+PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
+PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
+PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
+PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
+PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
+PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
+PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
+PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
+PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
+PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
+PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
+PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
+PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
+PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
+PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
+PFNGLINDEXDPROC glad_glIndexd = NULL;
+PFNGLINDEXDVPROC glad_glIndexdv = NULL;
+PFNGLINDEXFPROC glad_glIndexf = NULL;
+PFNGLINDEXFVPROC glad_glIndexfv = NULL;
+PFNGLINDEXIPROC glad_glIndexi = NULL;
+PFNGLINDEXIVPROC glad_glIndexiv = NULL;
+PFNGLINDEXSPROC glad_glIndexs = NULL;
+PFNGLINDEXSVPROC glad_glIndexsv = NULL;
+PFNGLINDEXUBPROC glad_glIndexub = NULL;
+PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
+PFNGLINITNAMESPROC glad_glInitNames = NULL;
+PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL;
+PFNGLISLISTPROC glad_glIsList = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
+PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
+PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
+PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
+PFNGLLIGHTFPROC glad_glLightf = NULL;
+PFNGLLIGHTFVPROC glad_glLightfv = NULL;
+PFNGLLIGHTIPROC glad_glLighti = NULL;
+PFNGLLIGHTIVPROC glad_glLightiv = NULL;
+PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLLISTBASEPROC glad_glListBase = NULL;
+PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
+PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
+PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
+PFNGLLOADNAMEPROC glad_glLoadName = NULL;
+PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
+PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLMAP1DPROC glad_glMap1d = NULL;
+PFNGLMAP1FPROC glad_glMap1f = NULL;
+PFNGLMAP2DPROC glad_glMap2d = NULL;
+PFNGLMAP2FPROC glad_glMap2f = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
+PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
+PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
+PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
+PFNGLMATERIALFPROC glad_glMaterialf = NULL;
+PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
+PFNGLMATERIALIPROC glad_glMateriali = NULL;
+PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
+PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
+PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
+PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
+PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
+PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
+PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
+PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
+PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
+PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
+PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
+PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
+PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
+PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
+PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
+PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
+PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
+PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
+PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
+PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
+PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
+PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
+PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
+PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
+PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
+PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
+PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
+PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
+PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
+PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
+PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
+PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
+PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
+PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
+PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
+PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
+PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
+PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
+PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
+PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
+PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
+PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
+PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
+PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
+PFNGLNEWLISTPROC glad_glNewList = NULL;
+PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
+PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
+PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
+PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
+PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
+PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
+PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
+PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
+PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
+PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
+PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
+PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
+PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
+PFNGLORTHOPROC glad_glOrtho = NULL;
+PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
+PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
+PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
+PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
+PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
+PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
+PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
+PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
+PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
+PFNGLPOPNAMEPROC glad_glPopName = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
+PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
+PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
+PFNGLPUSHNAMEPROC glad_glPushName = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
+PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
+PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
+PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
+PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
+PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
+PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
+PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
+PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
+PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
+PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
+PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
+PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
+PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
+PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
+PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
+PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
+PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
+PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
+PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
+PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
+PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
+PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
+PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLRECTDPROC glad_glRectd = NULL;
+PFNGLRECTDVPROC glad_glRectdv = NULL;
+PFNGLRECTFPROC glad_glRectf = NULL;
+PFNGLRECTFVPROC glad_glRectfv = NULL;
+PFNGLRECTIPROC glad_glRecti = NULL;
+PFNGLRECTIVPROC glad_glRectiv = NULL;
+PFNGLRECTSPROC glad_glRects = NULL;
+PFNGLRECTSVPROC glad_glRectsv = NULL;
+PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
+PFNGLROTATEDPROC glad_glRotated = NULL;
+PFNGLROTATEFPROC glad_glRotatef = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLSCALEDPROC glad_glScaled = NULL;
+PFNGLSCALEFPROC glad_glScalef = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
+PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
+PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
+PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
+PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
+PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
+PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
+PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
+PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
+PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
+PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
+PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
+PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
+PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
+PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
+PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
+PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
+PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
+PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
+PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
+PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
+PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
+PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
+PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
+PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
+PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
+PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
+PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
+PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
+PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
+PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
+PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
+PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
+PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
+PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
+PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
+PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
+PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
+PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
+PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
+PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
+PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
+PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
+PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
+PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
+PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
+PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
+PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
+PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
+PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
+PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
+PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
+PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
+PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
+PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
+PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
+PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
+PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
+PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
+PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
+PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
+PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
+PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
+PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
+PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
+PFNGLTEXGENDPROC glad_glTexGend = NULL;
+PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
+PFNGLTEXGENFPROC glad_glTexGenf = NULL;
+PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
+PFNGLTEXGENIPROC glad_glTexGeni = NULL;
+PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
+PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
+PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
+PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
+PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
+PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
+PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
+PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
+PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
+PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
+PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
+PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
+PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
+PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
+PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
+PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
+PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
+PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
+PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
+PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
+PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
+PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
+PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
+PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
+PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
+PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
+PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
+PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
+PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
+PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
+PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
+PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
+PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
+PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
+PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
+PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
+PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
+PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
+PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
+PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
+PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
+PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
+PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
+PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
+PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
+PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
+
+
+static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_0) return;
+ glad_glAccum = (PFNGLACCUMPROC) load(userptr, "glAccum");
+ glad_glAlphaFunc = (PFNGLALPHAFUNCPROC) load(userptr, "glAlphaFunc");
+ glad_glBegin = (PFNGLBEGINPROC) load(userptr, "glBegin");
+ glad_glBitmap = (PFNGLBITMAPPROC) load(userptr, "glBitmap");
+ glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc");
+ glad_glCallList = (PFNGLCALLLISTPROC) load(userptr, "glCallList");
+ glad_glCallLists = (PFNGLCALLLISTSPROC) load(userptr, "glCallLists");
+ glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear");
+ glad_glClearAccum = (PFNGLCLEARACCUMPROC) load(userptr, "glClearAccum");
+ glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor");
+ glad_glClearDepth = (PFNGLCLEARDEPTHPROC) load(userptr, "glClearDepth");
+ glad_glClearIndex = (PFNGLCLEARINDEXPROC) load(userptr, "glClearIndex");
+ glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil");
+ glad_glClipPlane = (PFNGLCLIPPLANEPROC) load(userptr, "glClipPlane");
+ glad_glColor3b = (PFNGLCOLOR3BPROC) load(userptr, "glColor3b");
+ glad_glColor3bv = (PFNGLCOLOR3BVPROC) load(userptr, "glColor3bv");
+ glad_glColor3d = (PFNGLCOLOR3DPROC) load(userptr, "glColor3d");
+ glad_glColor3dv = (PFNGLCOLOR3DVPROC) load(userptr, "glColor3dv");
+ glad_glColor3f = (PFNGLCOLOR3FPROC) load(userptr, "glColor3f");
+ glad_glColor3fv = (PFNGLCOLOR3FVPROC) load(userptr, "glColor3fv");
+ glad_glColor3i = (PFNGLCOLOR3IPROC) load(userptr, "glColor3i");
+ glad_glColor3iv = (PFNGLCOLOR3IVPROC) load(userptr, "glColor3iv");
+ glad_glColor3s = (PFNGLCOLOR3SPROC) load(userptr, "glColor3s");
+ glad_glColor3sv = (PFNGLCOLOR3SVPROC) load(userptr, "glColor3sv");
+ glad_glColor3ub = (PFNGLCOLOR3UBPROC) load(userptr, "glColor3ub");
+ glad_glColor3ubv = (PFNGLCOLOR3UBVPROC) load(userptr, "glColor3ubv");
+ glad_glColor3ui = (PFNGLCOLOR3UIPROC) load(userptr, "glColor3ui");
+ glad_glColor3uiv = (PFNGLCOLOR3UIVPROC) load(userptr, "glColor3uiv");
+ glad_glColor3us = (PFNGLCOLOR3USPROC) load(userptr, "glColor3us");
+ glad_glColor3usv = (PFNGLCOLOR3USVPROC) load(userptr, "glColor3usv");
+ glad_glColor4b = (PFNGLCOLOR4BPROC) load(userptr, "glColor4b");
+ glad_glColor4bv = (PFNGLCOLOR4BVPROC) load(userptr, "glColor4bv");
+ glad_glColor4d = (PFNGLCOLOR4DPROC) load(userptr, "glColor4d");
+ glad_glColor4dv = (PFNGLCOLOR4DVPROC) load(userptr, "glColor4dv");
+ glad_glColor4f = (PFNGLCOLOR4FPROC) load(userptr, "glColor4f");
+ glad_glColor4fv = (PFNGLCOLOR4FVPROC) load(userptr, "glColor4fv");
+ glad_glColor4i = (PFNGLCOLOR4IPROC) load(userptr, "glColor4i");
+ glad_glColor4iv = (PFNGLCOLOR4IVPROC) load(userptr, "glColor4iv");
+ glad_glColor4s = (PFNGLCOLOR4SPROC) load(userptr, "glColor4s");
+ glad_glColor4sv = (PFNGLCOLOR4SVPROC) load(userptr, "glColor4sv");
+ glad_glColor4ub = (PFNGLCOLOR4UBPROC) load(userptr, "glColor4ub");
+ glad_glColor4ubv = (PFNGLCOLOR4UBVPROC) load(userptr, "glColor4ubv");
+ glad_glColor4ui = (PFNGLCOLOR4UIPROC) load(userptr, "glColor4ui");
+ glad_glColor4uiv = (PFNGLCOLOR4UIVPROC) load(userptr, "glColor4uiv");
+ glad_glColor4us = (PFNGLCOLOR4USPROC) load(userptr, "glColor4us");
+ glad_glColor4usv = (PFNGLCOLOR4USVPROC) load(userptr, "glColor4usv");
+ glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask");
+ glad_glColorMaterial = (PFNGLCOLORMATERIALPROC) load(userptr, "glColorMaterial");
+ glad_glCopyPixels = (PFNGLCOPYPIXELSPROC) load(userptr, "glCopyPixels");
+ glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace");
+ glad_glDeleteLists = (PFNGLDELETELISTSPROC) load(userptr, "glDeleteLists");
+ glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc");
+ glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask");
+ glad_glDepthRange = (PFNGLDEPTHRANGEPROC) load(userptr, "glDepthRange");
+ glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable");
+ glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC) load(userptr, "glDrawBuffer");
+ glad_glDrawPixels = (PFNGLDRAWPIXELSPROC) load(userptr, "glDrawPixels");
+ glad_glEdgeFlag = (PFNGLEDGEFLAGPROC) load(userptr, "glEdgeFlag");
+ glad_glEdgeFlagv = (PFNGLEDGEFLAGVPROC) load(userptr, "glEdgeFlagv");
+ glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable");
+ glad_glEnd = (PFNGLENDPROC) load(userptr, "glEnd");
+ glad_glEndList = (PFNGLENDLISTPROC) load(userptr, "glEndList");
+ glad_glEvalCoord1d = (PFNGLEVALCOORD1DPROC) load(userptr, "glEvalCoord1d");
+ glad_glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC) load(userptr, "glEvalCoord1dv");
+ glad_glEvalCoord1f = (PFNGLEVALCOORD1FPROC) load(userptr, "glEvalCoord1f");
+ glad_glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC) load(userptr, "glEvalCoord1fv");
+ glad_glEvalCoord2d = (PFNGLEVALCOORD2DPROC) load(userptr, "glEvalCoord2d");
+ glad_glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC) load(userptr, "glEvalCoord2dv");
+ glad_glEvalCoord2f = (PFNGLEVALCOORD2FPROC) load(userptr, "glEvalCoord2f");
+ glad_glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC) load(userptr, "glEvalCoord2fv");
+ glad_glEvalMesh1 = (PFNGLEVALMESH1PROC) load(userptr, "glEvalMesh1");
+ glad_glEvalMesh2 = (PFNGLEVALMESH2PROC) load(userptr, "glEvalMesh2");
+ glad_glEvalPoint1 = (PFNGLEVALPOINT1PROC) load(userptr, "glEvalPoint1");
+ glad_glEvalPoint2 = (PFNGLEVALPOINT2PROC) load(userptr, "glEvalPoint2");
+ glad_glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC) load(userptr, "glFeedbackBuffer");
+ glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish");
+ glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush");
+ glad_glFogf = (PFNGLFOGFPROC) load(userptr, "glFogf");
+ glad_glFogfv = (PFNGLFOGFVPROC) load(userptr, "glFogfv");
+ glad_glFogi = (PFNGLFOGIPROC) load(userptr, "glFogi");
+ glad_glFogiv = (PFNGLFOGIVPROC) load(userptr, "glFogiv");
+ glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace");
+ glad_glFrustum = (PFNGLFRUSTUMPROC) load(userptr, "glFrustum");
+ glad_glGenLists = (PFNGLGENLISTSPROC) load(userptr, "glGenLists");
+ glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv");
+ glad_glGetClipPlane = (PFNGLGETCLIPPLANEPROC) load(userptr, "glGetClipPlane");
+ glad_glGetDoublev = (PFNGLGETDOUBLEVPROC) load(userptr, "glGetDoublev");
+ glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError");
+ glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv");
+ glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv");
+ glad_glGetLightfv = (PFNGLGETLIGHTFVPROC) load(userptr, "glGetLightfv");
+ glad_glGetLightiv = (PFNGLGETLIGHTIVPROC) load(userptr, "glGetLightiv");
+ glad_glGetMapdv = (PFNGLGETMAPDVPROC) load(userptr, "glGetMapdv");
+ glad_glGetMapfv = (PFNGLGETMAPFVPROC) load(userptr, "glGetMapfv");
+ glad_glGetMapiv = (PFNGLGETMAPIVPROC) load(userptr, "glGetMapiv");
+ glad_glGetMaterialfv = (PFNGLGETMATERIALFVPROC) load(userptr, "glGetMaterialfv");
+ glad_glGetMaterialiv = (PFNGLGETMATERIALIVPROC) load(userptr, "glGetMaterialiv");
+ glad_glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC) load(userptr, "glGetPixelMapfv");
+ glad_glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC) load(userptr, "glGetPixelMapuiv");
+ glad_glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC) load(userptr, "glGetPixelMapusv");
+ glad_glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC) load(userptr, "glGetPolygonStipple");
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ glad_glGetTexEnvfv = (PFNGLGETTEXENVFVPROC) load(userptr, "glGetTexEnvfv");
+ glad_glGetTexEnviv = (PFNGLGETTEXENVIVPROC) load(userptr, "glGetTexEnviv");
+ glad_glGetTexGendv = (PFNGLGETTEXGENDVPROC) load(userptr, "glGetTexGendv");
+ glad_glGetTexGenfv = (PFNGLGETTEXGENFVPROC) load(userptr, "glGetTexGenfv");
+ glad_glGetTexGeniv = (PFNGLGETTEXGENIVPROC) load(userptr, "glGetTexGeniv");
+ glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC) load(userptr, "glGetTexImage");
+ glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load(userptr, "glGetTexLevelParameterfv");
+ glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load(userptr, "glGetTexLevelParameteriv");
+ glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv");
+ glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv");
+ glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint");
+ glad_glIndexMask = (PFNGLINDEXMASKPROC) load(userptr, "glIndexMask");
+ glad_glIndexd = (PFNGLINDEXDPROC) load(userptr, "glIndexd");
+ glad_glIndexdv = (PFNGLINDEXDVPROC) load(userptr, "glIndexdv");
+ glad_glIndexf = (PFNGLINDEXFPROC) load(userptr, "glIndexf");
+ glad_glIndexfv = (PFNGLINDEXFVPROC) load(userptr, "glIndexfv");
+ glad_glIndexi = (PFNGLINDEXIPROC) load(userptr, "glIndexi");
+ glad_glIndexiv = (PFNGLINDEXIVPROC) load(userptr, "glIndexiv");
+ glad_glIndexs = (PFNGLINDEXSPROC) load(userptr, "glIndexs");
+ glad_glIndexsv = (PFNGLINDEXSVPROC) load(userptr, "glIndexsv");
+ glad_glInitNames = (PFNGLINITNAMESPROC) load(userptr, "glInitNames");
+ glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled");
+ glad_glIsList = (PFNGLISLISTPROC) load(userptr, "glIsList");
+ glad_glLightModelf = (PFNGLLIGHTMODELFPROC) load(userptr, "glLightModelf");
+ glad_glLightModelfv = (PFNGLLIGHTMODELFVPROC) load(userptr, "glLightModelfv");
+ glad_glLightModeli = (PFNGLLIGHTMODELIPROC) load(userptr, "glLightModeli");
+ glad_glLightModeliv = (PFNGLLIGHTMODELIVPROC) load(userptr, "glLightModeliv");
+ glad_glLightf = (PFNGLLIGHTFPROC) load(userptr, "glLightf");
+ glad_glLightfv = (PFNGLLIGHTFVPROC) load(userptr, "glLightfv");
+ glad_glLighti = (PFNGLLIGHTIPROC) load(userptr, "glLighti");
+ glad_glLightiv = (PFNGLLIGHTIVPROC) load(userptr, "glLightiv");
+ glad_glLineStipple = (PFNGLLINESTIPPLEPROC) load(userptr, "glLineStipple");
+ glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth");
+ glad_glListBase = (PFNGLLISTBASEPROC) load(userptr, "glListBase");
+ glad_glLoadIdentity = (PFNGLLOADIDENTITYPROC) load(userptr, "glLoadIdentity");
+ glad_glLoadMatrixd = (PFNGLLOADMATRIXDPROC) load(userptr, "glLoadMatrixd");
+ glad_glLoadMatrixf = (PFNGLLOADMATRIXFPROC) load(userptr, "glLoadMatrixf");
+ glad_glLoadName = (PFNGLLOADNAMEPROC) load(userptr, "glLoadName");
+ glad_glLogicOp = (PFNGLLOGICOPPROC) load(userptr, "glLogicOp");
+ glad_glMap1d = (PFNGLMAP1DPROC) load(userptr, "glMap1d");
+ glad_glMap1f = (PFNGLMAP1FPROC) load(userptr, "glMap1f");
+ glad_glMap2d = (PFNGLMAP2DPROC) load(userptr, "glMap2d");
+ glad_glMap2f = (PFNGLMAP2FPROC) load(userptr, "glMap2f");
+ glad_glMapGrid1d = (PFNGLMAPGRID1DPROC) load(userptr, "glMapGrid1d");
+ glad_glMapGrid1f = (PFNGLMAPGRID1FPROC) load(userptr, "glMapGrid1f");
+ glad_glMapGrid2d = (PFNGLMAPGRID2DPROC) load(userptr, "glMapGrid2d");
+ glad_glMapGrid2f = (PFNGLMAPGRID2FPROC) load(userptr, "glMapGrid2f");
+ glad_glMaterialf = (PFNGLMATERIALFPROC) load(userptr, "glMaterialf");
+ glad_glMaterialfv = (PFNGLMATERIALFVPROC) load(userptr, "glMaterialfv");
+ glad_glMateriali = (PFNGLMATERIALIPROC) load(userptr, "glMateriali");
+ glad_glMaterialiv = (PFNGLMATERIALIVPROC) load(userptr, "glMaterialiv");
+ glad_glMatrixMode = (PFNGLMATRIXMODEPROC) load(userptr, "glMatrixMode");
+ glad_glMultMatrixd = (PFNGLMULTMATRIXDPROC) load(userptr, "glMultMatrixd");
+ glad_glMultMatrixf = (PFNGLMULTMATRIXFPROC) load(userptr, "glMultMatrixf");
+ glad_glNewList = (PFNGLNEWLISTPROC) load(userptr, "glNewList");
+ glad_glNormal3b = (PFNGLNORMAL3BPROC) load(userptr, "glNormal3b");
+ glad_glNormal3bv = (PFNGLNORMAL3BVPROC) load(userptr, "glNormal3bv");
+ glad_glNormal3d = (PFNGLNORMAL3DPROC) load(userptr, "glNormal3d");
+ glad_glNormal3dv = (PFNGLNORMAL3DVPROC) load(userptr, "glNormal3dv");
+ glad_glNormal3f = (PFNGLNORMAL3FPROC) load(userptr, "glNormal3f");
+ glad_glNormal3fv = (PFNGLNORMAL3FVPROC) load(userptr, "glNormal3fv");
+ glad_glNormal3i = (PFNGLNORMAL3IPROC) load(userptr, "glNormal3i");
+ glad_glNormal3iv = (PFNGLNORMAL3IVPROC) load(userptr, "glNormal3iv");
+ glad_glNormal3s = (PFNGLNORMAL3SPROC) load(userptr, "glNormal3s");
+ glad_glNormal3sv = (PFNGLNORMAL3SVPROC) load(userptr, "glNormal3sv");
+ glad_glOrtho = (PFNGLORTHOPROC) load(userptr, "glOrtho");
+ glad_glPassThrough = (PFNGLPASSTHROUGHPROC) load(userptr, "glPassThrough");
+ glad_glPixelMapfv = (PFNGLPIXELMAPFVPROC) load(userptr, "glPixelMapfv");
+ glad_glPixelMapuiv = (PFNGLPIXELMAPUIVPROC) load(userptr, "glPixelMapuiv");
+ glad_glPixelMapusv = (PFNGLPIXELMAPUSVPROC) load(userptr, "glPixelMapusv");
+ glad_glPixelStoref = (PFNGLPIXELSTOREFPROC) load(userptr, "glPixelStoref");
+ glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei");
+ glad_glPixelTransferf = (PFNGLPIXELTRANSFERFPROC) load(userptr, "glPixelTransferf");
+ glad_glPixelTransferi = (PFNGLPIXELTRANSFERIPROC) load(userptr, "glPixelTransferi");
+ glad_glPixelZoom = (PFNGLPIXELZOOMPROC) load(userptr, "glPixelZoom");
+ glad_glPointSize = (PFNGLPOINTSIZEPROC) load(userptr, "glPointSize");
+ glad_glPolygonMode = (PFNGLPOLYGONMODEPROC) load(userptr, "glPolygonMode");
+ glad_glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC) load(userptr, "glPolygonStipple");
+ glad_glPopAttrib = (PFNGLPOPATTRIBPROC) load(userptr, "glPopAttrib");
+ glad_glPopMatrix = (PFNGLPOPMATRIXPROC) load(userptr, "glPopMatrix");
+ glad_glPopName = (PFNGLPOPNAMEPROC) load(userptr, "glPopName");
+ glad_glPushAttrib = (PFNGLPUSHATTRIBPROC) load(userptr, "glPushAttrib");
+ glad_glPushMatrix = (PFNGLPUSHMATRIXPROC) load(userptr, "glPushMatrix");
+ glad_glPushName = (PFNGLPUSHNAMEPROC) load(userptr, "glPushName");
+ glad_glRasterPos2d = (PFNGLRASTERPOS2DPROC) load(userptr, "glRasterPos2d");
+ glad_glRasterPos2dv = (PFNGLRASTERPOS2DVPROC) load(userptr, "glRasterPos2dv");
+ glad_glRasterPos2f = (PFNGLRASTERPOS2FPROC) load(userptr, "glRasterPos2f");
+ glad_glRasterPos2fv = (PFNGLRASTERPOS2FVPROC) load(userptr, "glRasterPos2fv");
+ glad_glRasterPos2i = (PFNGLRASTERPOS2IPROC) load(userptr, "glRasterPos2i");
+ glad_glRasterPos2iv = (PFNGLRASTERPOS2IVPROC) load(userptr, "glRasterPos2iv");
+ glad_glRasterPos2s = (PFNGLRASTERPOS2SPROC) load(userptr, "glRasterPos2s");
+ glad_glRasterPos2sv = (PFNGLRASTERPOS2SVPROC) load(userptr, "glRasterPos2sv");
+ glad_glRasterPos3d = (PFNGLRASTERPOS3DPROC) load(userptr, "glRasterPos3d");
+ glad_glRasterPos3dv = (PFNGLRASTERPOS3DVPROC) load(userptr, "glRasterPos3dv");
+ glad_glRasterPos3f = (PFNGLRASTERPOS3FPROC) load(userptr, "glRasterPos3f");
+ glad_glRasterPos3fv = (PFNGLRASTERPOS3FVPROC) load(userptr, "glRasterPos3fv");
+ glad_glRasterPos3i = (PFNGLRASTERPOS3IPROC) load(userptr, "glRasterPos3i");
+ glad_glRasterPos3iv = (PFNGLRASTERPOS3IVPROC) load(userptr, "glRasterPos3iv");
+ glad_glRasterPos3s = (PFNGLRASTERPOS3SPROC) load(userptr, "glRasterPos3s");
+ glad_glRasterPos3sv = (PFNGLRASTERPOS3SVPROC) load(userptr, "glRasterPos3sv");
+ glad_glRasterPos4d = (PFNGLRASTERPOS4DPROC) load(userptr, "glRasterPos4d");
+ glad_glRasterPos4dv = (PFNGLRASTERPOS4DVPROC) load(userptr, "glRasterPos4dv");
+ glad_glRasterPos4f = (PFNGLRASTERPOS4FPROC) load(userptr, "glRasterPos4f");
+ glad_glRasterPos4fv = (PFNGLRASTERPOS4FVPROC) load(userptr, "glRasterPos4fv");
+ glad_glRasterPos4i = (PFNGLRASTERPOS4IPROC) load(userptr, "glRasterPos4i");
+ glad_glRasterPos4iv = (PFNGLRASTERPOS4IVPROC) load(userptr, "glRasterPos4iv");
+ glad_glRasterPos4s = (PFNGLRASTERPOS4SPROC) load(userptr, "glRasterPos4s");
+ glad_glRasterPos4sv = (PFNGLRASTERPOS4SVPROC) load(userptr, "glRasterPos4sv");
+ glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer");
+ glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels");
+ glad_glRectd = (PFNGLRECTDPROC) load(userptr, "glRectd");
+ glad_glRectdv = (PFNGLRECTDVPROC) load(userptr, "glRectdv");
+ glad_glRectf = (PFNGLRECTFPROC) load(userptr, "glRectf");
+ glad_glRectfv = (PFNGLRECTFVPROC) load(userptr, "glRectfv");
+ glad_glRecti = (PFNGLRECTIPROC) load(userptr, "glRecti");
+ glad_glRectiv = (PFNGLRECTIVPROC) load(userptr, "glRectiv");
+ glad_glRects = (PFNGLRECTSPROC) load(userptr, "glRects");
+ glad_glRectsv = (PFNGLRECTSVPROC) load(userptr, "glRectsv");
+ glad_glRenderMode = (PFNGLRENDERMODEPROC) load(userptr, "glRenderMode");
+ glad_glRotated = (PFNGLROTATEDPROC) load(userptr, "glRotated");
+ glad_glRotatef = (PFNGLROTATEFPROC) load(userptr, "glRotatef");
+ glad_glScaled = (PFNGLSCALEDPROC) load(userptr, "glScaled");
+ glad_glScalef = (PFNGLSCALEFPROC) load(userptr, "glScalef");
+ glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor");
+ glad_glSelectBuffer = (PFNGLSELECTBUFFERPROC) load(userptr, "glSelectBuffer");
+ glad_glShadeModel = (PFNGLSHADEMODELPROC) load(userptr, "glShadeModel");
+ glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc");
+ glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask");
+ glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp");
+ glad_glTexCoord1d = (PFNGLTEXCOORD1DPROC) load(userptr, "glTexCoord1d");
+ glad_glTexCoord1dv = (PFNGLTEXCOORD1DVPROC) load(userptr, "glTexCoord1dv");
+ glad_glTexCoord1f = (PFNGLTEXCOORD1FPROC) load(userptr, "glTexCoord1f");
+ glad_glTexCoord1fv = (PFNGLTEXCOORD1FVPROC) load(userptr, "glTexCoord1fv");
+ glad_glTexCoord1i = (PFNGLTEXCOORD1IPROC) load(userptr, "glTexCoord1i");
+ glad_glTexCoord1iv = (PFNGLTEXCOORD1IVPROC) load(userptr, "glTexCoord1iv");
+ glad_glTexCoord1s = (PFNGLTEXCOORD1SPROC) load(userptr, "glTexCoord1s");
+ glad_glTexCoord1sv = (PFNGLTEXCOORD1SVPROC) load(userptr, "glTexCoord1sv");
+ glad_glTexCoord2d = (PFNGLTEXCOORD2DPROC) load(userptr, "glTexCoord2d");
+ glad_glTexCoord2dv = (PFNGLTEXCOORD2DVPROC) load(userptr, "glTexCoord2dv");
+ glad_glTexCoord2f = (PFNGLTEXCOORD2FPROC) load(userptr, "glTexCoord2f");
+ glad_glTexCoord2fv = (PFNGLTEXCOORD2FVPROC) load(userptr, "glTexCoord2fv");
+ glad_glTexCoord2i = (PFNGLTEXCOORD2IPROC) load(userptr, "glTexCoord2i");
+ glad_glTexCoord2iv = (PFNGLTEXCOORD2IVPROC) load(userptr, "glTexCoord2iv");
+ glad_glTexCoord2s = (PFNGLTEXCOORD2SPROC) load(userptr, "glTexCoord2s");
+ glad_glTexCoord2sv = (PFNGLTEXCOORD2SVPROC) load(userptr, "glTexCoord2sv");
+ glad_glTexCoord3d = (PFNGLTEXCOORD3DPROC) load(userptr, "glTexCoord3d");
+ glad_glTexCoord3dv = (PFNGLTEXCOORD3DVPROC) load(userptr, "glTexCoord3dv");
+ glad_glTexCoord3f = (PFNGLTEXCOORD3FPROC) load(userptr, "glTexCoord3f");
+ glad_glTexCoord3fv = (PFNGLTEXCOORD3FVPROC) load(userptr, "glTexCoord3fv");
+ glad_glTexCoord3i = (PFNGLTEXCOORD3IPROC) load(userptr, "glTexCoord3i");
+ glad_glTexCoord3iv = (PFNGLTEXCOORD3IVPROC) load(userptr, "glTexCoord3iv");
+ glad_glTexCoord3s = (PFNGLTEXCOORD3SPROC) load(userptr, "glTexCoord3s");
+ glad_glTexCoord3sv = (PFNGLTEXCOORD3SVPROC) load(userptr, "glTexCoord3sv");
+ glad_glTexCoord4d = (PFNGLTEXCOORD4DPROC) load(userptr, "glTexCoord4d");
+ glad_glTexCoord4dv = (PFNGLTEXCOORD4DVPROC) load(userptr, "glTexCoord4dv");
+ glad_glTexCoord4f = (PFNGLTEXCOORD4FPROC) load(userptr, "glTexCoord4f");
+ glad_glTexCoord4fv = (PFNGLTEXCOORD4FVPROC) load(userptr, "glTexCoord4fv");
+ glad_glTexCoord4i = (PFNGLTEXCOORD4IPROC) load(userptr, "glTexCoord4i");
+ glad_glTexCoord4iv = (PFNGLTEXCOORD4IVPROC) load(userptr, "glTexCoord4iv");
+ glad_glTexCoord4s = (PFNGLTEXCOORD4SPROC) load(userptr, "glTexCoord4s");
+ glad_glTexCoord4sv = (PFNGLTEXCOORD4SVPROC) load(userptr, "glTexCoord4sv");
+ glad_glTexEnvf = (PFNGLTEXENVFPROC) load(userptr, "glTexEnvf");
+ glad_glTexEnvfv = (PFNGLTEXENVFVPROC) load(userptr, "glTexEnvfv");
+ glad_glTexEnvi = (PFNGLTEXENVIPROC) load(userptr, "glTexEnvi");
+ glad_glTexEnviv = (PFNGLTEXENVIVPROC) load(userptr, "glTexEnviv");
+ glad_glTexGend = (PFNGLTEXGENDPROC) load(userptr, "glTexGend");
+ glad_glTexGendv = (PFNGLTEXGENDVPROC) load(userptr, "glTexGendv");
+ glad_glTexGenf = (PFNGLTEXGENFPROC) load(userptr, "glTexGenf");
+ glad_glTexGenfv = (PFNGLTEXGENFVPROC) load(userptr, "glTexGenfv");
+ glad_glTexGeni = (PFNGLTEXGENIPROC) load(userptr, "glTexGeni");
+ glad_glTexGeniv = (PFNGLTEXGENIVPROC) load(userptr, "glTexGeniv");
+ glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC) load(userptr, "glTexImage1D");
+ glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D");
+ glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf");
+ glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv");
+ glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri");
+ glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv");
+ glad_glTranslated = (PFNGLTRANSLATEDPROC) load(userptr, "glTranslated");
+ glad_glTranslatef = (PFNGLTRANSLATEFPROC) load(userptr, "glTranslatef");
+ glad_glVertex2d = (PFNGLVERTEX2DPROC) load(userptr, "glVertex2d");
+ glad_glVertex2dv = (PFNGLVERTEX2DVPROC) load(userptr, "glVertex2dv");
+ glad_glVertex2f = (PFNGLVERTEX2FPROC) load(userptr, "glVertex2f");
+ glad_glVertex2fv = (PFNGLVERTEX2FVPROC) load(userptr, "glVertex2fv");
+ glad_glVertex2i = (PFNGLVERTEX2IPROC) load(userptr, "glVertex2i");
+ glad_glVertex2iv = (PFNGLVERTEX2IVPROC) load(userptr, "glVertex2iv");
+ glad_glVertex2s = (PFNGLVERTEX2SPROC) load(userptr, "glVertex2s");
+ glad_glVertex2sv = (PFNGLVERTEX2SVPROC) load(userptr, "glVertex2sv");
+ glad_glVertex3d = (PFNGLVERTEX3DPROC) load(userptr, "glVertex3d");
+ glad_glVertex3dv = (PFNGLVERTEX3DVPROC) load(userptr, "glVertex3dv");
+ glad_glVertex3f = (PFNGLVERTEX3FPROC) load(userptr, "glVertex3f");
+ glad_glVertex3fv = (PFNGLVERTEX3FVPROC) load(userptr, "glVertex3fv");
+ glad_glVertex3i = (PFNGLVERTEX3IPROC) load(userptr, "glVertex3i");
+ glad_glVertex3iv = (PFNGLVERTEX3IVPROC) load(userptr, "glVertex3iv");
+ glad_glVertex3s = (PFNGLVERTEX3SPROC) load(userptr, "glVertex3s");
+ glad_glVertex3sv = (PFNGLVERTEX3SVPROC) load(userptr, "glVertex3sv");
+ glad_glVertex4d = (PFNGLVERTEX4DPROC) load(userptr, "glVertex4d");
+ glad_glVertex4dv = (PFNGLVERTEX4DVPROC) load(userptr, "glVertex4dv");
+ glad_glVertex4f = (PFNGLVERTEX4FPROC) load(userptr, "glVertex4f");
+ glad_glVertex4fv = (PFNGLVERTEX4FVPROC) load(userptr, "glVertex4fv");
+ glad_glVertex4i = (PFNGLVERTEX4IPROC) load(userptr, "glVertex4i");
+ glad_glVertex4iv = (PFNGLVERTEX4IVPROC) load(userptr, "glVertex4iv");
+ glad_glVertex4s = (PFNGLVERTEX4SPROC) load(userptr, "glVertex4s");
+ glad_glVertex4sv = (PFNGLVERTEX4SVPROC) load(userptr, "glVertex4sv");
+ glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport");
+}
+static void glad_gl_load_GL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_1) return;
+ glad_glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC) load(userptr, "glAreTexturesResident");
+ glad_glArrayElement = (PFNGLARRAYELEMENTPROC) load(userptr, "glArrayElement");
+ glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture");
+ glad_glColorPointer = (PFNGLCOLORPOINTERPROC) load(userptr, "glColorPointer");
+ glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load(userptr, "glCopyTexImage1D");
+ glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D");
+ glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load(userptr, "glCopyTexSubImage1D");
+ glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D");
+ glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures");
+ glad_glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC) load(userptr, "glDisableClientState");
+ glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays");
+ glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements");
+ glad_glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC) load(userptr, "glEdgeFlagPointer");
+ glad_glEnableClientState = (PFNGLENABLECLIENTSTATEPROC) load(userptr, "glEnableClientState");
+ glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures");
+ glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv");
+ glad_glIndexPointer = (PFNGLINDEXPOINTERPROC) load(userptr, "glIndexPointer");
+ glad_glIndexub = (PFNGLINDEXUBPROC) load(userptr, "glIndexub");
+ glad_glIndexubv = (PFNGLINDEXUBVPROC) load(userptr, "glIndexubv");
+ glad_glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC) load(userptr, "glInterleavedArrays");
+ glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture");
+ glad_glNormalPointer = (PFNGLNORMALPOINTERPROC) load(userptr, "glNormalPointer");
+ glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset");
+ glad_glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC) load(userptr, "glPopClientAttrib");
+ glad_glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC) load(userptr, "glPrioritizeTextures");
+ glad_glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC) load(userptr, "glPushClientAttrib");
+ glad_glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC) load(userptr, "glTexCoordPointer");
+ glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load(userptr, "glTexSubImage1D");
+ glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D");
+ glad_glVertexPointer = (PFNGLVERTEXPOINTERPROC) load(userptr, "glVertexPointer");
+}
+static void glad_gl_load_GL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_2) return;
+ glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D");
+ glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements");
+ glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D");
+ glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D");
+}
+static void glad_gl_load_GL_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_3) return;
+ glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture");
+ glad_glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC) load(userptr, "glClientActiveTexture");
+ glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load(userptr, "glCompressedTexImage1D");
+ glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D");
+ glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D");
+ glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load(userptr, "glCompressedTexSubImage1D");
+ glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D");
+ glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D");
+ glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load(userptr, "glGetCompressedTexImage");
+ glad_glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC) load(userptr, "glLoadTransposeMatrixd");
+ glad_glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC) load(userptr, "glLoadTransposeMatrixf");
+ glad_glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC) load(userptr, "glMultTransposeMatrixd");
+ glad_glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC) load(userptr, "glMultTransposeMatrixf");
+ glad_glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC) load(userptr, "glMultiTexCoord1d");
+ glad_glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC) load(userptr, "glMultiTexCoord1dv");
+ glad_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC) load(userptr, "glMultiTexCoord1f");
+ glad_glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC) load(userptr, "glMultiTexCoord1fv");
+ glad_glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC) load(userptr, "glMultiTexCoord1i");
+ glad_glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC) load(userptr, "glMultiTexCoord1iv");
+ glad_glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC) load(userptr, "glMultiTexCoord1s");
+ glad_glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC) load(userptr, "glMultiTexCoord1sv");
+ glad_glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC) load(userptr, "glMultiTexCoord2d");
+ glad_glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC) load(userptr, "glMultiTexCoord2dv");
+ glad_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC) load(userptr, "glMultiTexCoord2f");
+ glad_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC) load(userptr, "glMultiTexCoord2fv");
+ glad_glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC) load(userptr, "glMultiTexCoord2i");
+ glad_glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC) load(userptr, "glMultiTexCoord2iv");
+ glad_glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC) load(userptr, "glMultiTexCoord2s");
+ glad_glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC) load(userptr, "glMultiTexCoord2sv");
+ glad_glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC) load(userptr, "glMultiTexCoord3d");
+ glad_glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC) load(userptr, "glMultiTexCoord3dv");
+ glad_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC) load(userptr, "glMultiTexCoord3f");
+ glad_glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC) load(userptr, "glMultiTexCoord3fv");
+ glad_glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC) load(userptr, "glMultiTexCoord3i");
+ glad_glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC) load(userptr, "glMultiTexCoord3iv");
+ glad_glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC) load(userptr, "glMultiTexCoord3s");
+ glad_glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC) load(userptr, "glMultiTexCoord3sv");
+ glad_glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC) load(userptr, "glMultiTexCoord4d");
+ glad_glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC) load(userptr, "glMultiTexCoord4dv");
+ glad_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC) load(userptr, "glMultiTexCoord4f");
+ glad_glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC) load(userptr, "glMultiTexCoord4fv");
+ glad_glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC) load(userptr, "glMultiTexCoord4i");
+ glad_glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC) load(userptr, "glMultiTexCoord4iv");
+ glad_glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC) load(userptr, "glMultiTexCoord4s");
+ glad_glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC) load(userptr, "glMultiTexCoord4sv");
+ glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage");
+}
+static void glad_gl_load_GL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_4) return;
+ glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor");
+ glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation");
+ glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate");
+ glad_glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC) load(userptr, "glFogCoordPointer");
+ glad_glFogCoordd = (PFNGLFOGCOORDDPROC) load(userptr, "glFogCoordd");
+ glad_glFogCoorddv = (PFNGLFOGCOORDDVPROC) load(userptr, "glFogCoorddv");
+ glad_glFogCoordf = (PFNGLFOGCOORDFPROC) load(userptr, "glFogCoordf");
+ glad_glFogCoordfv = (PFNGLFOGCOORDFVPROC) load(userptr, "glFogCoordfv");
+ glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load(userptr, "glMultiDrawArrays");
+ glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load(userptr, "glMultiDrawElements");
+ glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load(userptr, "glPointParameterf");
+ glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load(userptr, "glPointParameterfv");
+ glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load(userptr, "glPointParameteri");
+ glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load(userptr, "glPointParameteriv");
+ glad_glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC) load(userptr, "glSecondaryColor3b");
+ glad_glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC) load(userptr, "glSecondaryColor3bv");
+ glad_glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC) load(userptr, "glSecondaryColor3d");
+ glad_glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC) load(userptr, "glSecondaryColor3dv");
+ glad_glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC) load(userptr, "glSecondaryColor3f");
+ glad_glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC) load(userptr, "glSecondaryColor3fv");
+ glad_glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC) load(userptr, "glSecondaryColor3i");
+ glad_glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC) load(userptr, "glSecondaryColor3iv");
+ glad_glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC) load(userptr, "glSecondaryColor3s");
+ glad_glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC) load(userptr, "glSecondaryColor3sv");
+ glad_glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC) load(userptr, "glSecondaryColor3ub");
+ glad_glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC) load(userptr, "glSecondaryColor3ubv");
+ glad_glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC) load(userptr, "glSecondaryColor3ui");
+ glad_glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC) load(userptr, "glSecondaryColor3uiv");
+ glad_glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC) load(userptr, "glSecondaryColor3us");
+ glad_glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC) load(userptr, "glSecondaryColor3usv");
+ glad_glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC) load(userptr, "glSecondaryColorPointer");
+ glad_glWindowPos2d = (PFNGLWINDOWPOS2DPROC) load(userptr, "glWindowPos2d");
+ glad_glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC) load(userptr, "glWindowPos2dv");
+ glad_glWindowPos2f = (PFNGLWINDOWPOS2FPROC) load(userptr, "glWindowPos2f");
+ glad_glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC) load(userptr, "glWindowPos2fv");
+ glad_glWindowPos2i = (PFNGLWINDOWPOS2IPROC) load(userptr, "glWindowPos2i");
+ glad_glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC) load(userptr, "glWindowPos2iv");
+ glad_glWindowPos2s = (PFNGLWINDOWPOS2SPROC) load(userptr, "glWindowPos2s");
+ glad_glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC) load(userptr, "glWindowPos2sv");
+ glad_glWindowPos3d = (PFNGLWINDOWPOS3DPROC) load(userptr, "glWindowPos3d");
+ glad_glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC) load(userptr, "glWindowPos3dv");
+ glad_glWindowPos3f = (PFNGLWINDOWPOS3FPROC) load(userptr, "glWindowPos3f");
+ glad_glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC) load(userptr, "glWindowPos3fv");
+ glad_glWindowPos3i = (PFNGLWINDOWPOS3IPROC) load(userptr, "glWindowPos3i");
+ glad_glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC) load(userptr, "glWindowPos3iv");
+ glad_glWindowPos3s = (PFNGLWINDOWPOS3SPROC) load(userptr, "glWindowPos3s");
+ glad_glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC) load(userptr, "glWindowPos3sv");
+}
+static void glad_gl_load_GL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_5) return;
+ glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery");
+ glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer");
+ glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData");
+ glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData");
+ glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers");
+ glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries");
+ glad_glEndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery");
+ glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers");
+ glad_glGenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries");
+ glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv");
+ glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv");
+ glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load(userptr, "glGetBufferSubData");
+ glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load(userptr, "glGetQueryObjectiv");
+ glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv");
+ glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv");
+ glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer");
+ glad_glIsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery");
+ glad_glMapBuffer = (PFNGLMAPBUFFERPROC) load(userptr, "glMapBuffer");
+ glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer");
+}
+static void glad_gl_load_GL_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_0) return;
+ glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader");
+ glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation");
+ glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate");
+ glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader");
+ glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram");
+ glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader");
+ glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram");
+ glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader");
+ glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader");
+ glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray");
+ glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers");
+ glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray");
+ glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib");
+ glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform");
+ glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders");
+ glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation");
+ glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog");
+ glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv");
+ glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog");
+ glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource");
+ glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv");
+ glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation");
+ glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv");
+ glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv");
+ glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv");
+ glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load(userptr, "glGetVertexAttribdv");
+ glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv");
+ glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv");
+ glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram");
+ glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader");
+ glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram");
+ glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource");
+ glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate");
+ glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate");
+ glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate");
+ glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f");
+ glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv");
+ glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i");
+ glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv");
+ glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f");
+ glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv");
+ glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i");
+ glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv");
+ glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f");
+ glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv");
+ glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i");
+ glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv");
+ glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f");
+ glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv");
+ glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i");
+ glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv");
+ glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv");
+ glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv");
+ glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv");
+ glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram");
+ glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram");
+ glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load(userptr, "glVertexAttrib1d");
+ glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load(userptr, "glVertexAttrib1dv");
+ glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f");
+ glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv");
+ glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load(userptr, "glVertexAttrib1s");
+ glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load(userptr, "glVertexAttrib1sv");
+ glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load(userptr, "glVertexAttrib2d");
+ glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load(userptr, "glVertexAttrib2dv");
+ glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f");
+ glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv");
+ glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load(userptr, "glVertexAttrib2s");
+ glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load(userptr, "glVertexAttrib2sv");
+ glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load(userptr, "glVertexAttrib3d");
+ glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load(userptr, "glVertexAttrib3dv");
+ glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f");
+ glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv");
+ glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load(userptr, "glVertexAttrib3s");
+ glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load(userptr, "glVertexAttrib3sv");
+ glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load(userptr, "glVertexAttrib4Nbv");
+ glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load(userptr, "glVertexAttrib4Niv");
+ glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load(userptr, "glVertexAttrib4Nsv");
+ glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load(userptr, "glVertexAttrib4Nub");
+ glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load(userptr, "glVertexAttrib4Nubv");
+ glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load(userptr, "glVertexAttrib4Nuiv");
+ glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load(userptr, "glVertexAttrib4Nusv");
+ glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load(userptr, "glVertexAttrib4bv");
+ glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load(userptr, "glVertexAttrib4d");
+ glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load(userptr, "glVertexAttrib4dv");
+ glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f");
+ glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv");
+ glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load(userptr, "glVertexAttrib4iv");
+ glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load(userptr, "glVertexAttrib4s");
+ glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load(userptr, "glVertexAttrib4sv");
+ glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load(userptr, "glVertexAttrib4ubv");
+ glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load(userptr, "glVertexAttrib4uiv");
+ glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load(userptr, "glVertexAttrib4usv");
+ glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer");
+}
+static void glad_gl_load_GL_VERSION_2_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_1) return;
+ glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv");
+ glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv");
+ glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv");
+ glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv");
+ glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv");
+ glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv");
+}
+static void glad_gl_load_GL_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_0) return;
+ glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load(userptr, "glBeginConditionalRender");
+ glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback");
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load(userptr, "glBindFragDataLocation");
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glClampColor = (PFNGLCLAMPCOLORPROC) load(userptr, "glClampColor");
+ glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi");
+ glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv");
+ glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv");
+ glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv");
+ glad_glColorMaski = (PFNGLCOLORMASKIPROC) load(userptr, "glColorMaski");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays");
+ glad_glDisablei = (PFNGLDISABLEIPROC) load(userptr, "glDisablei");
+ glad_glEnablei = (PFNGLENABLEIPROC) load(userptr, "glEnablei");
+ glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load(userptr, "glEndConditionalRender");
+ glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback");
+ glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load(userptr, "glGetBooleani_v");
+ glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glGetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi");
+ glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load(userptr, "glGetTexParameterIiv");
+ glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load(userptr, "glGetTexParameterIuiv");
+ glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying");
+ glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv");
+ glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv");
+ glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv");
+ glad_glIsEnabledi = (PFNGLISENABLEDIPROC) load(userptr, "glIsEnabledi");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray");
+ glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
+ glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load(userptr, "glTexParameterIiv");
+ glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load(userptr, "glTexParameterIuiv");
+ glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings");
+ glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui");
+ glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv");
+ glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui");
+ glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv");
+ glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui");
+ glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv");
+ glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui");
+ glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv");
+ glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load(userptr, "glVertexAttribI1i");
+ glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load(userptr, "glVertexAttribI1iv");
+ glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load(userptr, "glVertexAttribI1ui");
+ glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load(userptr, "glVertexAttribI1uiv");
+ glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load(userptr, "glVertexAttribI2i");
+ glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load(userptr, "glVertexAttribI2iv");
+ glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load(userptr, "glVertexAttribI2ui");
+ glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load(userptr, "glVertexAttribI2uiv");
+ glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load(userptr, "glVertexAttribI3i");
+ glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load(userptr, "glVertexAttribI3iv");
+ glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load(userptr, "glVertexAttribI3ui");
+ glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load(userptr, "glVertexAttribI3uiv");
+ glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load(userptr, "glVertexAttribI4bv");
+ glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i");
+ glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv");
+ glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load(userptr, "glVertexAttribI4sv");
+ glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load(userptr, "glVertexAttribI4ubv");
+ glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui");
+ glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv");
+ glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load(userptr, "glVertexAttribI4usv");
+ glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer");
+}
+static void glad_gl_load_GL_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_1) return;
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData");
+ glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced");
+ glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced");
+ glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName");
+ glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv");
+ glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName");
+ glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex");
+ glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices");
+ glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load(userptr, "glPrimitiveRestartIndex");
+ glad_glTexBuffer = (PFNGLTEXBUFFERPROC) load(userptr, "glTexBuffer");
+ glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding");
+}
+static void glad_gl_load_GL_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_2) return;
+ glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync");
+ glad_glDeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync");
+ glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex");
+ glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex");
+ glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex");
+ glad_glFenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync");
+ glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load(userptr, "glFramebufferTexture");
+ glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v");
+ glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v");
+ glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v");
+ glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv");
+ glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv");
+ glad_glIsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync");
+ glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex");
+ glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load(userptr, "glProvokingVertex");
+ glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski");
+ glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample");
+ glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample");
+ glad_glWaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync");
+}
+static void glad_gl_load_GL_VERSION_3_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_3) return;
+ glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load(userptr, "glBindFragDataLocationIndexed");
+ glad_glBindSampler = (PFNGLBINDSAMPLERPROC) load(userptr, "glBindSampler");
+ glad_glColorP3ui = (PFNGLCOLORP3UIPROC) load(userptr, "glColorP3ui");
+ glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC) load(userptr, "glColorP3uiv");
+ glad_glColorP4ui = (PFNGLCOLORP4UIPROC) load(userptr, "glColorP4ui");
+ glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC) load(userptr, "glColorP4uiv");
+ glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load(userptr, "glDeleteSamplers");
+ glad_glGenSamplers = (PFNGLGENSAMPLERSPROC) load(userptr, "glGenSamplers");
+ glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load(userptr, "glGetFragDataIndex");
+ glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v");
+ glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v");
+ glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load(userptr, "glGetSamplerParameterIiv");
+ glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load(userptr, "glGetSamplerParameterIuiv");
+ glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load(userptr, "glGetSamplerParameterfv");
+ glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load(userptr, "glGetSamplerParameteriv");
+ glad_glIsSampler = (PFNGLISSAMPLERPROC) load(userptr, "glIsSampler");
+ glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC) load(userptr, "glMultiTexCoordP1ui");
+ glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC) load(userptr, "glMultiTexCoordP1uiv");
+ glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC) load(userptr, "glMultiTexCoordP2ui");
+ glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC) load(userptr, "glMultiTexCoordP2uiv");
+ glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC) load(userptr, "glMultiTexCoordP3ui");
+ glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC) load(userptr, "glMultiTexCoordP3uiv");
+ glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC) load(userptr, "glMultiTexCoordP4ui");
+ glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC) load(userptr, "glMultiTexCoordP4uiv");
+ glad_glNormalP3ui = (PFNGLNORMALP3UIPROC) load(userptr, "glNormalP3ui");
+ glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC) load(userptr, "glNormalP3uiv");
+ glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter");
+ glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load(userptr, "glSamplerParameterIiv");
+ glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load(userptr, "glSamplerParameterIuiv");
+ glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load(userptr, "glSamplerParameterf");
+ glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load(userptr, "glSamplerParameterfv");
+ glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load(userptr, "glSamplerParameteri");
+ glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load(userptr, "glSamplerParameteriv");
+ glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC) load(userptr, "glSecondaryColorP3ui");
+ glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC) load(userptr, "glSecondaryColorP3uiv");
+ glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC) load(userptr, "glTexCoordP1ui");
+ glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC) load(userptr, "glTexCoordP1uiv");
+ glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC) load(userptr, "glTexCoordP2ui");
+ glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC) load(userptr, "glTexCoordP2uiv");
+ glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC) load(userptr, "glTexCoordP3ui");
+ glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC) load(userptr, "glTexCoordP3uiv");
+ glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC) load(userptr, "glTexCoordP4ui");
+ glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC) load(userptr, "glTexCoordP4uiv");
+ glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load(userptr, "glVertexAttribDivisor");
+ glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load(userptr, "glVertexAttribP1ui");
+ glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load(userptr, "glVertexAttribP1uiv");
+ glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load(userptr, "glVertexAttribP2ui");
+ glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load(userptr, "glVertexAttribP2uiv");
+ glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load(userptr, "glVertexAttribP3ui");
+ glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load(userptr, "glVertexAttribP3uiv");
+ glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load(userptr, "glVertexAttribP4ui");
+ glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load(userptr, "glVertexAttribP4uiv");
+ glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC) load(userptr, "glVertexP2ui");
+ glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC) load(userptr, "glVertexP2uiv");
+ glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC) load(userptr, "glVertexP3ui");
+ glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC) load(userptr, "glVertexP3uiv");
+ glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC) load(userptr, "glVertexP4ui");
+ glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC) load(userptr, "glVertexP4uiv");
+}
+static void glad_gl_load_GL_ARB_debug_output( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_debug_output) return;
+ glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) load(userptr, "glDebugMessageCallbackARB");
+ glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) load(userptr, "glDebugMessageControlARB");
+ glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load(userptr, "glDebugMessageInsertARB");
+ glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load(userptr, "glGetDebugMessageLogARB");
+}
+static void glad_gl_load_GL_ARB_framebuffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_framebuffer_object) return;
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
+}
+static void glad_gl_load_GL_EXT_framebuffer_blit( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_blit) return;
+ glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) load(userptr, "glBlitFramebufferEXT");
+}
+static void glad_gl_load_GL_EXT_framebuffer_multisample( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_multisample) return;
+ glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glRenderbufferStorageMultisampleEXT");
+}
+static void glad_gl_load_GL_EXT_framebuffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_object) return;
+ glad_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) load(userptr, "glBindFramebufferEXT");
+ glad_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) load(userptr, "glBindRenderbufferEXT");
+ glad_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) load(userptr, "glCheckFramebufferStatusEXT");
+ glad_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) load(userptr, "glDeleteFramebuffersEXT");
+ glad_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) load(userptr, "glDeleteRenderbuffersEXT");
+ glad_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) load(userptr, "glFramebufferRenderbufferEXT");
+ glad_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) load(userptr, "glFramebufferTexture1DEXT");
+ glad_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) load(userptr, "glFramebufferTexture2DEXT");
+ glad_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) load(userptr, "glFramebufferTexture3DEXT");
+ glad_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) load(userptr, "glGenFramebuffersEXT");
+ glad_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) load(userptr, "glGenRenderbuffersEXT");
+ glad_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) load(userptr, "glGenerateMipmapEXT");
+ glad_glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) load(userptr, "glGetFramebufferAttachmentParameterivEXT");
+ glad_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetRenderbufferParameterivEXT");
+ glad_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) load(userptr, "glIsFramebufferEXT");
+ glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) load(userptr, "glIsRenderbufferEXT");
+ glad_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) load(userptr, "glRenderbufferStorageEXT");
+}
+static void glad_gl_load_GL_OVR_multiview( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OVR_multiview) return;
+ glad_glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) load(userptr, "glFramebufferTextureMultiviewOVR");
+}
+
+
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define GLAD_GL_IS_SOME_NEW_VERSION 1
+#else
+#define GLAD_GL_IS_SOME_NEW_VERSION 0
+#endif
+
+static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ if(GLAD_VERSION_MAJOR(version) < 3) {
+#else
+ GLAD_UNUSED(version);
+ GLAD_UNUSED(out_num_exts_i);
+ GLAD_UNUSED(out_exts_i);
+#endif
+ if (glad_glGetString == NULL) {
+ return 0;
+ }
+ *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS);
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ } else {
+ unsigned int index = 0;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) {
+ return 0;
+ }
+ glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
+ if (num_exts_i > 0) {
+ exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i));
+ }
+ if (exts_i == NULL) {
+ return 0;
+ }
+ for(index = 0; index < num_exts_i; index++) {
+ const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index);
+ size_t len = strlen(gl_str_tmp) + 1;
+
+ char *local_str = (char*) malloc(len * sizeof(char));
+ if(local_str != NULL) {
+ memcpy(local_str, gl_str_tmp, len * sizeof(char));
+ }
+
+ exts_i[index] = local_str;
+ }
+
+ *out_num_exts_i = num_exts_i;
+ *out_exts_i = exts_i;
+ }
+#endif
+ return 1;
+}
+static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
+ if (exts_i != NULL) {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ free((void *) (exts_i[index]));
+ }
+ free((void *)exts_i);
+ exts_i = NULL;
+ }
+}
+static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
+ if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
+ const char *extensions;
+ const char *loc;
+ const char *terminator;
+ extensions = exts;
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL) {
+ return 0;
+ }
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+ } else {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ const char *e = exts_i[index];
+ if(strcmp(e, ext) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) {
+ return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_gl_find_extensions_gl( int version) {
+ const char *exts = NULL;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
+
+ GLAD_GL_ARB_debug_output = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_debug_output");
+ GLAD_GL_ARB_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_framebuffer_object");
+ GLAD_GL_EXT_framebuffer_blit = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_blit");
+ GLAD_GL_EXT_framebuffer_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_multisample");
+ GLAD_GL_EXT_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_object");
+ GLAD_GL_OVR_multiview = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview");
+ GLAD_GL_OVR_multiview2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview2");
+
+ glad_gl_free_extensions(exts_i, num_exts_i);
+
+ return 1;
+}
+
+static int glad_gl_find_core_gl(void) {
+ int i;
+ const char* version;
+ const char* prefixes[] = {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ "OpenGL SC ",
+ NULL
+ };
+ int major = 0;
+ int minor = 0;
+ version = (const char*) glad_glGetString(GL_VERSION);
+ if (!version) return 0;
+ for (i = 0; prefixes[i]; i++) {
+ const size_t length = strlen(prefixes[i]);
+ if (strncmp(version, prefixes[i], length) == 0) {
+ version += length;
+ break;
+ }
+ }
+
+ GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
+
+ GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+ GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+ GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+ GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+ GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+ GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
+ GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+ GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
+ GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
+ GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
+ GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
+ GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
+
+ return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
+ int version;
+
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ if(glad_glGetString == NULL) return 0;
+ if(glad_glGetString(GL_VERSION) == NULL) return 0;
+ version = glad_gl_find_core_gl();
+
+ glad_gl_load_GL_VERSION_1_0(load, userptr);
+ glad_gl_load_GL_VERSION_1_1(load, userptr);
+ glad_gl_load_GL_VERSION_1_2(load, userptr);
+ glad_gl_load_GL_VERSION_1_3(load, userptr);
+ glad_gl_load_GL_VERSION_1_4(load, userptr);
+ glad_gl_load_GL_VERSION_1_5(load, userptr);
+ glad_gl_load_GL_VERSION_2_0(load, userptr);
+ glad_gl_load_GL_VERSION_2_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_0(load, userptr);
+ glad_gl_load_GL_VERSION_3_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_2(load, userptr);
+ glad_gl_load_GL_VERSION_3_3(load, userptr);
+
+ if (!glad_gl_find_extensions_gl(version)) return 0;
+ glad_gl_load_GL_ARB_debug_output(load, userptr);
+ glad_gl_load_GL_ARB_framebuffer_object(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_blit(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_multisample(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_object(load, userptr);
+ glad_gl_load_GL_OVR_multiview(load, userptr);
+
+
+
+ return version;
+}
+
+
+int gladLoadGL( GLADloadfunc load) {
+ return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+
+
+#ifdef GLAD_GL
+
+#ifndef GLAD_LOADER_LIBRARY_C_
+#define GLAD_LOADER_LIBRARY_C_
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if GLAD_PLATFORM_WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+
+static void* glad_get_dlopen_handle(const char *lib_names[], int length) {
+ void *handle = NULL;
+ int i;
+
+ for (i = 0; i < length; ++i) {
+#if GLAD_PLATFORM_WIN32
+ #if GLAD_PLATFORM_UWP
+ size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR);
+ LPWSTR buffer = (LPWSTR) malloc(buffer_size);
+ if (buffer != NULL) {
+ int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size);
+ if (ret != 0) {
+ handle = (void*) LoadPackagedLibrary(buffer, 0);
+ }
+ free((void*) buffer);
+ }
+ #else
+ handle = (void*) LoadLibraryA(lib_names[i]);
+ #endif
+#else
+ handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL);
+#endif
+ if (handle != NULL) {
+ return handle;
+ }
+ }
+
+ return NULL;
+}
+
+static void glad_close_dlopen_handle(void* handle) {
+ if (handle != NULL) {
+#if GLAD_PLATFORM_WIN32
+ FreeLibrary((HMODULE) handle);
+#else
+ dlclose(handle);
+#endif
+ }
+}
+
+static GLADapiproc glad_dlsym_handle(void* handle, const char *name) {
+ if (handle == NULL) {
+ return NULL;
+ }
+
+#if GLAD_PLATFORM_WIN32
+ return (GLADapiproc) GetProcAddress((HMODULE) handle, name);
+#else
+ return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name);
+#endif
+}
+
+#endif /* GLAD_LOADER_LIBRARY_C_ */
+
+typedef void* (GLAD_API_PTR *GLADglprocaddrfunc)(const char*);
+struct _glad_gl_userptr {
+ void *handle;
+ GLADglprocaddrfunc gl_get_proc_address_ptr;
+};
+
+static GLADapiproc glad_gl_get_proc(void *vuserptr, const char *name) {
+ struct _glad_gl_userptr userptr = *(struct _glad_gl_userptr*) vuserptr;
+ GLADapiproc result = NULL;
+
+ if(userptr.gl_get_proc_address_ptr != NULL) {
+ result = GLAD_GNUC_EXTENSION (GLADapiproc) userptr.gl_get_proc_address_ptr(name);
+ }
+ if(result == NULL) {
+ result = glad_dlsym_handle(userptr.handle, name);
+ }
+
+ return result;
+}
+
+static void* _glad_GL_loader_handle = NULL;
+
+static void* glad_gl_dlopen_handle(void) {
+#if GLAD_PLATFORM_APPLE
+ static const char *NAMES[] = {
+ "../Frameworks/OpenGL.framework/OpenGL",
+ "/Library/Frameworks/OpenGL.framework/OpenGL",
+ "/System/Library/Frameworks/OpenGL.framework/OpenGL",
+ "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
+ };
+#elif GLAD_PLATFORM_WIN32
+ static const char *NAMES[] = {"opengl32.dll"};
+#else
+ static const char *NAMES[] = {
+ #if defined(__CYGWIN__)
+ "libGL-1.so",
+ #endif
+ "libGL.so.1",
+ "libGL.so"
+ };
+#endif
+
+ if (_glad_GL_loader_handle == NULL) {
+ _glad_GL_loader_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0]));
+ }
+
+ return _glad_GL_loader_handle;
+}
+
+static struct _glad_gl_userptr glad_gl_build_userptr(void *handle) {
+ struct _glad_gl_userptr userptr;
+
+ userptr.handle = handle;
+#if GLAD_PLATFORM_APPLE || defined(__HAIKU__)
+ userptr.gl_get_proc_address_ptr = NULL;
+#elif GLAD_PLATFORM_WIN32
+ userptr.gl_get_proc_address_ptr =
+ (GLADglprocaddrfunc) glad_dlsym_handle(handle, "wglGetProcAddress");
+#else
+ userptr.gl_get_proc_address_ptr =
+ (GLADglprocaddrfunc) glad_dlsym_handle(handle, "glXGetProcAddressARB");
+#endif
+
+ return userptr;
+}
+
+int gladLoaderLoadGL(void) {
+ int version = 0;
+ void *handle;
+ int did_load = 0;
+ struct _glad_gl_userptr userptr;
+
+ did_load = _glad_GL_loader_handle == NULL;
+ handle = glad_gl_dlopen_handle();
+ if (handle) {
+ userptr = glad_gl_build_userptr(handle);
+
+ version = gladLoadGLUserPtr(glad_gl_get_proc, &userptr);
+
+ if (did_load) {
+ gladLoaderUnloadGL();
+ }
+ }
+
+ return version;
+}
+
+
+
+void gladLoaderUnloadGL(void) {
+ if (_glad_GL_loader_handle != NULL) {
+ glad_close_dlopen_handle(_glad_GL_loader_handle);
+ _glad_GL_loader_handle = NULL;
+ }
+}
+
+#endif /* GLAD_GL */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c
deleted file mode 100644
index 4b20178ef7..0000000000
--- a/thirdparty/glad/glad.c
+++ /dev/null
@@ -1,1951 +0,0 @@
-/*
-
- OpenGL loader generated by glad 0.1.36 on Sun Sep 4 15:50:32 2022.
-
- Language/Generator: C/C++
- Specification: gl
- APIs: gl=3.3
- Profile: compatibility
- Extensions:
- GL_ARB_debug_output,
- GL_ARB_framebuffer_object,
- GL_EXT_framebuffer_blit,
- GL_EXT_framebuffer_multisample,
- GL_EXT_framebuffer_object,
- GL_OVR_multiview,
- GL_OVR_multiview2
- Loader: True
- Local files: False
- Omit khrplatform: False
- Reproducible: False
-
- Commandline:
- --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_OVR_multiview,GL_OVR_multiview2"
- Online:
- https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_OVR_multiview&extensions=GL_OVR_multiview2
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glad/glad.h>
-
-static void* get_proc(const char *namez);
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-#ifndef _WINDOWS_
-#undef APIENTRY
-#endif
-#include <windows.h>
-static HMODULE libGL;
-
-typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*);
-static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
-
-#ifdef _MSC_VER
-#ifdef __has_include
- #if __has_include(<winapifamily.h>)
- #define HAVE_WINAPIFAMILY 1
- #endif
-#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
- #define HAVE_WINAPIFAMILY 1
-#endif
-#endif
-
-#ifdef HAVE_WINAPIFAMILY
- #include <winapifamily.h>
- #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
- #define IS_UWP 1
- #endif
-#endif
-
-static
-int open_gl(void) {
-#ifndef IS_UWP
- libGL = LoadLibraryW(L"opengl32.dll");
- if(libGL != NULL) {
- void (* tmp)(void);
- tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress");
- gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp;
- return gladGetProcAddressPtr != NULL;
- }
-#endif
-
- return 0;
-}
-
-static
-void close_gl(void) {
- if(libGL != NULL) {
- FreeLibrary((HMODULE) libGL);
- libGL = NULL;
- }
-}
-#else
-#include <dlfcn.h>
-static void* libGL;
-
-#if !defined(__APPLE__) && !defined(__HAIKU__)
-typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*);
-static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
-#endif
-
-static
-int open_gl(void) {
-#ifdef __APPLE__
- static const char *NAMES[] = {
- "../Frameworks/OpenGL.framework/OpenGL",
- "/Library/Frameworks/OpenGL.framework/OpenGL",
- "/System/Library/Frameworks/OpenGL.framework/OpenGL",
- "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
- };
-#else
- static const char *NAMES[] = {"libGL.so.1", "libGL.so"};
-#endif
-
- unsigned int index = 0;
- for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) {
- libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL);
-
- if(libGL != NULL) {
-#if defined(__APPLE__) || defined(__HAIKU__)
- return 1;
-#else
- gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL,
- "glXGetProcAddressARB");
- return gladGetProcAddressPtr != NULL;
-#endif
- }
- }
-
- return 0;
-}
-
-static
-void close_gl(void) {
- if(libGL != NULL) {
- dlclose(libGL);
- libGL = NULL;
- }
-}
-#endif
-
-static
-void* get_proc(const char *namez) {
- void* result = NULL;
- if(libGL == NULL) return NULL;
-
-#if !defined(__APPLE__) && !defined(__HAIKU__)
- if(gladGetProcAddressPtr != NULL) {
- result = gladGetProcAddressPtr(namez);
- }
-#endif
- if(result == NULL) {
-#if defined(_WIN32) || defined(__CYGWIN__)
- result = (void*)GetProcAddress((HMODULE) libGL, namez);
-#else
- result = dlsym(libGL, namez);
-#endif
- }
-
- return result;
-}
-
-int gladLoadGL(void) {
- int status = 0;
-
- if(open_gl()) {
- status = gladLoadGLLoader(&get_proc);
- close_gl();
- }
-
- return status;
-}
-
-struct gladGLversionStruct GLVersion = { 0, 0 };
-
-#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
-#define _GLAD_IS_SOME_NEW_VERSION 1
-#endif
-
-static int max_loaded_major;
-static int max_loaded_minor;
-
-static const char *exts = NULL;
-static int num_exts_i = 0;
-static char **exts_i = NULL;
-
-static int get_exts(void) {
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- if(max_loaded_major < 3) {
-#endif
- exts = (const char *)glGetString(GL_EXTENSIONS);
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- } else {
- unsigned int index;
-
- num_exts_i = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
- if (num_exts_i > 0) {
- exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i));
- }
-
- if (exts_i == NULL) {
- return 0;
- }
-
- for(index = 0; index < (unsigned)num_exts_i; index++) {
- const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index);
- size_t len = strlen(gl_str_tmp);
-
- char *local_str = (char*)malloc((len+1) * sizeof(char));
- if(local_str != NULL) {
- memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char));
- }
- exts_i[index] = local_str;
- }
- }
-#endif
- return 1;
-}
-
-static void free_exts(void) {
- if (exts_i != NULL) {
- int index;
- for(index = 0; index < num_exts_i; index++) {
- free((char *)exts_i[index]);
- }
- free((void *)exts_i);
- exts_i = NULL;
- }
-}
-
-static int has_ext(const char *ext) {
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- if(max_loaded_major < 3) {
-#endif
- const char *extensions;
- const char *loc;
- const char *terminator;
- extensions = exts;
- if(extensions == NULL || ext == NULL) {
- return 0;
- }
-
- while(1) {
- loc = strstr(extensions, ext);
- if(loc == NULL) {
- return 0;
- }
-
- terminator = loc + strlen(ext);
- if((loc == extensions || *(loc - 1) == ' ') &&
- (*terminator == ' ' || *terminator == '\0')) {
- return 1;
- }
- extensions = terminator;
- }
-#ifdef _GLAD_IS_SOME_NEW_VERSION
- } else {
- int index;
- if(exts_i == NULL) return 0;
- for(index = 0; index < num_exts_i; index++) {
- const char *e = exts_i[index];
-
- if(exts_i[index] != NULL && strcmp(e, ext) == 0) {
- return 1;
- }
- }
- }
-#endif
-
- return 0;
-}
-int GLAD_GL_VERSION_1_0 = 0;
-int GLAD_GL_VERSION_1_1 = 0;
-int GLAD_GL_VERSION_1_2 = 0;
-int GLAD_GL_VERSION_1_3 = 0;
-int GLAD_GL_VERSION_1_4 = 0;
-int GLAD_GL_VERSION_1_5 = 0;
-int GLAD_GL_VERSION_2_0 = 0;
-int GLAD_GL_VERSION_2_1 = 0;
-int GLAD_GL_VERSION_3_0 = 0;
-int GLAD_GL_VERSION_3_1 = 0;
-int GLAD_GL_VERSION_3_2 = 0;
-int GLAD_GL_VERSION_3_3 = 0;
-PFNGLACCUMPROC glad_glAccum = NULL;
-PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
-PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
-PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
-PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
-PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
-PFNGLBEGINPROC glad_glBegin = NULL;
-PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
-PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
-PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
-PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
-PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
-PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
-PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
-PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
-PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
-PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
-PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
-PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
-PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
-PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
-PFNGLBITMAPPROC glad_glBitmap = NULL;
-PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
-PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
-PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
-PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
-PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
-PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
-PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
-PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
-PFNGLCALLLISTPROC glad_glCallList = NULL;
-PFNGLCALLLISTSPROC glad_glCallLists = NULL;
-PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
-PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
-PFNGLCLEARPROC glad_glClear = NULL;
-PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
-PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
-PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
-PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
-PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
-PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
-PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
-PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
-PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
-PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
-PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
-PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
-PFNGLCOLOR3BPROC glad_glColor3b = NULL;
-PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
-PFNGLCOLOR3DPROC glad_glColor3d = NULL;
-PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
-PFNGLCOLOR3FPROC glad_glColor3f = NULL;
-PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
-PFNGLCOLOR3IPROC glad_glColor3i = NULL;
-PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
-PFNGLCOLOR3SPROC glad_glColor3s = NULL;
-PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
-PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
-PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
-PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
-PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
-PFNGLCOLOR3USPROC glad_glColor3us = NULL;
-PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
-PFNGLCOLOR4BPROC glad_glColor4b = NULL;
-PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
-PFNGLCOLOR4DPROC glad_glColor4d = NULL;
-PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
-PFNGLCOLOR4FPROC glad_glColor4f = NULL;
-PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
-PFNGLCOLOR4IPROC glad_glColor4i = NULL;
-PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
-PFNGLCOLOR4SPROC glad_glColor4s = NULL;
-PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
-PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
-PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
-PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
-PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
-PFNGLCOLOR4USPROC glad_glColor4us = NULL;
-PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
-PFNGLCOLORMASKPROC glad_glColorMask = NULL;
-PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
-PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
-PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
-PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
-PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
-PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
-PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
-PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
-PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
-PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
-PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
-PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
-PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
-PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
-PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
-PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
-PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
-PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
-PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
-PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
-PFNGLCULLFACEPROC glad_glCullFace = NULL;
-PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
-PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
-PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
-PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
-PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
-PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
-PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
-PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
-PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
-PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
-PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
-PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
-PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
-PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
-PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
-PFNGLDISABLEPROC glad_glDisable = NULL;
-PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
-PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
-PFNGLDISABLEIPROC glad_glDisablei = NULL;
-PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
-PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
-PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
-PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
-PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
-PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
-PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
-PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
-PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
-PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
-PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
-PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
-PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
-PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
-PFNGLENABLEPROC glad_glEnable = NULL;
-PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
-PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
-PFNGLENABLEIPROC glad_glEnablei = NULL;
-PFNGLENDPROC glad_glEnd = NULL;
-PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
-PFNGLENDLISTPROC glad_glEndList = NULL;
-PFNGLENDQUERYPROC glad_glEndQuery = NULL;
-PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
-PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
-PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
-PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
-PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
-PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
-PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
-PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
-PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
-PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
-PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
-PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
-PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
-PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
-PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
-PFNGLFINISHPROC glad_glFinish = NULL;
-PFNGLFLUSHPROC glad_glFlush = NULL;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
-PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
-PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
-PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
-PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
-PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
-PFNGLFOGFPROC glad_glFogf = NULL;
-PFNGLFOGFVPROC glad_glFogfv = NULL;
-PFNGLFOGIPROC glad_glFogi = NULL;
-PFNGLFOGIVPROC glad_glFogiv = NULL;
-PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
-PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
-PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
-PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
-PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
-PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
-PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
-PFNGLFRUSTUMPROC glad_glFrustum = NULL;
-PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
-PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
-PFNGLGENLISTSPROC glad_glGenLists = NULL;
-PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
-PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
-PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
-PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
-PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
-PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
-PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
-PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
-PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
-PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
-PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
-PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
-PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
-PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
-PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
-PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
-PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
-PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
-PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
-PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
-PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
-PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
-PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
-PFNGLGETERRORPROC glad_glGetError = NULL;
-PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
-PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
-PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
-PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
-PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
-PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
-PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
-PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
-PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
-PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
-PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
-PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
-PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
-PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
-PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
-PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
-PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
-PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
-PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
-PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
-PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
-PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
-PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
-PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
-PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
-PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
-PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
-PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
-PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
-PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
-PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
-PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
-PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
-PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
-PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
-PFNGLGETSTRINGPROC glad_glGetString = NULL;
-PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
-PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
-PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
-PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
-PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
-PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
-PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
-PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
-PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
-PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
-PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
-PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
-PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
-PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
-PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
-PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
-PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
-PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
-PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
-PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
-PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
-PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
-PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
-PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
-PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
-PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
-PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
-PFNGLHINTPROC glad_glHint = NULL;
-PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
-PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
-PFNGLINDEXDPROC glad_glIndexd = NULL;
-PFNGLINDEXDVPROC glad_glIndexdv = NULL;
-PFNGLINDEXFPROC glad_glIndexf = NULL;
-PFNGLINDEXFVPROC glad_glIndexfv = NULL;
-PFNGLINDEXIPROC glad_glIndexi = NULL;
-PFNGLINDEXIVPROC glad_glIndexiv = NULL;
-PFNGLINDEXSPROC glad_glIndexs = NULL;
-PFNGLINDEXSVPROC glad_glIndexsv = NULL;
-PFNGLINDEXUBPROC glad_glIndexub = NULL;
-PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
-PFNGLINITNAMESPROC glad_glInitNames = NULL;
-PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
-PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
-PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
-PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
-PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
-PFNGLISLISTPROC glad_glIsList = NULL;
-PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
-PFNGLISQUERYPROC glad_glIsQuery = NULL;
-PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
-PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
-PFNGLISSHADERPROC glad_glIsShader = NULL;
-PFNGLISSYNCPROC glad_glIsSync = NULL;
-PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
-PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
-PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
-PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
-PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
-PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
-PFNGLLIGHTFPROC glad_glLightf = NULL;
-PFNGLLIGHTFVPROC glad_glLightfv = NULL;
-PFNGLLIGHTIPROC glad_glLighti = NULL;
-PFNGLLIGHTIVPROC glad_glLightiv = NULL;
-PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
-PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
-PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
-PFNGLLISTBASEPROC glad_glListBase = NULL;
-PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
-PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
-PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
-PFNGLLOADNAMEPROC glad_glLoadName = NULL;
-PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
-PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
-PFNGLLOGICOPPROC glad_glLogicOp = NULL;
-PFNGLMAP1DPROC glad_glMap1d = NULL;
-PFNGLMAP1FPROC glad_glMap1f = NULL;
-PFNGLMAP2DPROC glad_glMap2d = NULL;
-PFNGLMAP2FPROC glad_glMap2f = NULL;
-PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
-PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
-PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
-PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
-PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
-PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
-PFNGLMATERIALFPROC glad_glMaterialf = NULL;
-PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
-PFNGLMATERIALIPROC glad_glMateriali = NULL;
-PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
-PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
-PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
-PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
-PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
-PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
-PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
-PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
-PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
-PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
-PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
-PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
-PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
-PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
-PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
-PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
-PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
-PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
-PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
-PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
-PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
-PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
-PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
-PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
-PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
-PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
-PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
-PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
-PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
-PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
-PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
-PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
-PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
-PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
-PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
-PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
-PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
-PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
-PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
-PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
-PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
-PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
-PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
-PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
-PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
-PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
-PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
-PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
-PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
-PFNGLNEWLISTPROC glad_glNewList = NULL;
-PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
-PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
-PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
-PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
-PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
-PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
-PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
-PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
-PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
-PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
-PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
-PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
-PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
-PFNGLORTHOPROC glad_glOrtho = NULL;
-PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
-PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
-PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
-PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
-PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
-PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
-PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
-PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
-PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
-PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
-PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
-PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
-PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
-PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
-PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
-PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
-PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
-PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
-PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
-PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
-PFNGLPOPNAMEPROC glad_glPopName = NULL;
-PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
-PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
-PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
-PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
-PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
-PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
-PFNGLPUSHNAMEPROC glad_glPushName = NULL;
-PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
-PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
-PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
-PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
-PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
-PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
-PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
-PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
-PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
-PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
-PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
-PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
-PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
-PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
-PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
-PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
-PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
-PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
-PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
-PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
-PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
-PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
-PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
-PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
-PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
-PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
-PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
-PFNGLRECTDPROC glad_glRectd = NULL;
-PFNGLRECTDVPROC glad_glRectdv = NULL;
-PFNGLRECTFPROC glad_glRectf = NULL;
-PFNGLRECTFVPROC glad_glRectfv = NULL;
-PFNGLRECTIPROC glad_glRecti = NULL;
-PFNGLRECTIVPROC glad_glRectiv = NULL;
-PFNGLRECTSPROC glad_glRects = NULL;
-PFNGLRECTSVPROC glad_glRectsv = NULL;
-PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
-PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
-PFNGLROTATEDPROC glad_glRotated = NULL;
-PFNGLROTATEFPROC glad_glRotatef = NULL;
-PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
-PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
-PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
-PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
-PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
-PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
-PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
-PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
-PFNGLSCALEDPROC glad_glScaled = NULL;
-PFNGLSCALEFPROC glad_glScalef = NULL;
-PFNGLSCISSORPROC glad_glScissor = NULL;
-PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
-PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
-PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
-PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
-PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
-PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
-PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
-PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
-PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
-PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
-PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
-PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
-PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
-PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
-PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
-PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
-PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
-PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
-PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
-PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
-PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
-PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
-PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
-PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
-PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
-PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
-PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
-PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
-PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
-PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
-PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
-PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
-PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
-PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
-PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
-PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
-PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
-PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
-PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
-PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
-PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
-PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
-PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
-PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
-PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
-PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
-PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
-PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
-PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
-PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
-PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
-PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
-PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
-PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
-PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
-PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
-PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
-PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
-PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
-PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
-PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
-PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
-PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
-PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
-PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
-PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
-PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
-PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
-PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
-PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
-PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
-PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
-PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
-PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
-PFNGLTEXGENDPROC glad_glTexGend = NULL;
-PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
-PFNGLTEXGENFPROC glad_glTexGenf = NULL;
-PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
-PFNGLTEXGENIPROC glad_glTexGeni = NULL;
-PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
-PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
-PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
-PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
-PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
-PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
-PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
-PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
-PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
-PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
-PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
-PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
-PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
-PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
-PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
-PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
-PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
-PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
-PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
-PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
-PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
-PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
-PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
-PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
-PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
-PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
-PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
-PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
-PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
-PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
-PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
-PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
-PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
-PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
-PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
-PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
-PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
-PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
-PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
-PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
-PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
-PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
-PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
-PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
-PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
-PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
-PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
-PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
-PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
-PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
-PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
-PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
-PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
-PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
-PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
-PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
-PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
-PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
-PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
-PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
-PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
-PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
-PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
-PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
-PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
-PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
-PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
-PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
-PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
-PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
-PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
-PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
-PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
-PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
-PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
-PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
-PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
-PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
-PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
-PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
-PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
-PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
-PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
-PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
-PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
-PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
-PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
-PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
-PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
-PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
-PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
-PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
-PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
-PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
-PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
-PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
-PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
-PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
-PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
-PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
-PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
-PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
-PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
-PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
-PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
-PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
-PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
-PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
-PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
-PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
-PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
-PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
-PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
-PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
-PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
-PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
-PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
-PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
-PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
-PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
-PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
-PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
-PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
-PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
-PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
-PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
-PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
-PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
-PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
-PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
-PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
-PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
-PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
-PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
-PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
-PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
-PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
-PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
-PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
-PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
-PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
-PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
-PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
-PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
-PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
-PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
-PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
-PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
-PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
-PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
-PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
-PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
-PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
-PFNGLVIEWPORTPROC glad_glViewport = NULL;
-PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
-PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
-PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
-PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
-PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
-PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
-PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
-PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
-PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
-PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
-PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
-PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
-PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
-PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
-PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
-PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
-PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
-int GLAD_GL_ARB_debug_output = 0;
-int GLAD_GL_ARB_framebuffer_object = 0;
-int GLAD_GL_EXT_framebuffer_blit = 0;
-int GLAD_GL_EXT_framebuffer_multisample = 0;
-int GLAD_GL_EXT_framebuffer_object = 0;
-int GLAD_GL_OVR_multiview = 0;
-int GLAD_GL_OVR_multiview2 = 0;
-PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
-PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
-PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
-PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
-PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
-PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
-PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
-PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
-PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL;
-PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL;
-PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL;
-PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL;
-PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL;
-PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL;
-PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL;
-PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL;
-PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL;
-PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL;
-PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL;
-PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL;
-PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL;
-PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR = NULL;
-static void load_GL_VERSION_1_0(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_0) return;
- glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
- glad_glFrontFace = (PFNGLFRONTFACEPROC)load("glFrontFace");
- glad_glHint = (PFNGLHINTPROC)load("glHint");
- glad_glLineWidth = (PFNGLLINEWIDTHPROC)load("glLineWidth");
- glad_glPointSize = (PFNGLPOINTSIZEPROC)load("glPointSize");
- glad_glPolygonMode = (PFNGLPOLYGONMODEPROC)load("glPolygonMode");
- glad_glScissor = (PFNGLSCISSORPROC)load("glScissor");
- glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC)load("glTexParameterf");
- glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)load("glTexParameterfv");
- glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC)load("glTexParameteri");
- glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)load("glTexParameteriv");
- glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC)load("glTexImage1D");
- glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC)load("glTexImage2D");
- glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC)load("glDrawBuffer");
- glad_glClear = (PFNGLCLEARPROC)load("glClear");
- glad_glClearColor = (PFNGLCLEARCOLORPROC)load("glClearColor");
- glad_glClearStencil = (PFNGLCLEARSTENCILPROC)load("glClearStencil");
- glad_glClearDepth = (PFNGLCLEARDEPTHPROC)load("glClearDepth");
- glad_glStencilMask = (PFNGLSTENCILMASKPROC)load("glStencilMask");
- glad_glColorMask = (PFNGLCOLORMASKPROC)load("glColorMask");
- glad_glDepthMask = (PFNGLDEPTHMASKPROC)load("glDepthMask");
- glad_glDisable = (PFNGLDISABLEPROC)load("glDisable");
- glad_glEnable = (PFNGLENABLEPROC)load("glEnable");
- glad_glFinish = (PFNGLFINISHPROC)load("glFinish");
- glad_glFlush = (PFNGLFLUSHPROC)load("glFlush");
- glad_glBlendFunc = (PFNGLBLENDFUNCPROC)load("glBlendFunc");
- glad_glLogicOp = (PFNGLLOGICOPPROC)load("glLogicOp");
- glad_glStencilFunc = (PFNGLSTENCILFUNCPROC)load("glStencilFunc");
- glad_glStencilOp = (PFNGLSTENCILOPPROC)load("glStencilOp");
- glad_glDepthFunc = (PFNGLDEPTHFUNCPROC)load("glDepthFunc");
- glad_glPixelStoref = (PFNGLPIXELSTOREFPROC)load("glPixelStoref");
- glad_glPixelStorei = (PFNGLPIXELSTOREIPROC)load("glPixelStorei");
- glad_glReadBuffer = (PFNGLREADBUFFERPROC)load("glReadBuffer");
- glad_glReadPixels = (PFNGLREADPIXELSPROC)load("glReadPixels");
- glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC)load("glGetBooleanv");
- glad_glGetDoublev = (PFNGLGETDOUBLEVPROC)load("glGetDoublev");
- glad_glGetError = (PFNGLGETERRORPROC)load("glGetError");
- glad_glGetFloatv = (PFNGLGETFLOATVPROC)load("glGetFloatv");
- glad_glGetIntegerv = (PFNGLGETINTEGERVPROC)load("glGetIntegerv");
- glad_glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
- glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC)load("glGetTexImage");
- glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)load("glGetTexParameterfv");
- glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)load("glGetTexParameteriv");
- glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC)load("glGetTexLevelParameterfv");
- glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC)load("glGetTexLevelParameteriv");
- glad_glIsEnabled = (PFNGLISENABLEDPROC)load("glIsEnabled");
- glad_glDepthRange = (PFNGLDEPTHRANGEPROC)load("glDepthRange");
- glad_glViewport = (PFNGLVIEWPORTPROC)load("glViewport");
- glad_glNewList = (PFNGLNEWLISTPROC)load("glNewList");
- glad_glEndList = (PFNGLENDLISTPROC)load("glEndList");
- glad_glCallList = (PFNGLCALLLISTPROC)load("glCallList");
- glad_glCallLists = (PFNGLCALLLISTSPROC)load("glCallLists");
- glad_glDeleteLists = (PFNGLDELETELISTSPROC)load("glDeleteLists");
- glad_glGenLists = (PFNGLGENLISTSPROC)load("glGenLists");
- glad_glListBase = (PFNGLLISTBASEPROC)load("glListBase");
- glad_glBegin = (PFNGLBEGINPROC)load("glBegin");
- glad_glBitmap = (PFNGLBITMAPPROC)load("glBitmap");
- glad_glColor3b = (PFNGLCOLOR3BPROC)load("glColor3b");
- glad_glColor3bv = (PFNGLCOLOR3BVPROC)load("glColor3bv");
- glad_glColor3d = (PFNGLCOLOR3DPROC)load("glColor3d");
- glad_glColor3dv = (PFNGLCOLOR3DVPROC)load("glColor3dv");
- glad_glColor3f = (PFNGLCOLOR3FPROC)load("glColor3f");
- glad_glColor3fv = (PFNGLCOLOR3FVPROC)load("glColor3fv");
- glad_glColor3i = (PFNGLCOLOR3IPROC)load("glColor3i");
- glad_glColor3iv = (PFNGLCOLOR3IVPROC)load("glColor3iv");
- glad_glColor3s = (PFNGLCOLOR3SPROC)load("glColor3s");
- glad_glColor3sv = (PFNGLCOLOR3SVPROC)load("glColor3sv");
- glad_glColor3ub = (PFNGLCOLOR3UBPROC)load("glColor3ub");
- glad_glColor3ubv = (PFNGLCOLOR3UBVPROC)load("glColor3ubv");
- glad_glColor3ui = (PFNGLCOLOR3UIPROC)load("glColor3ui");
- glad_glColor3uiv = (PFNGLCOLOR3UIVPROC)load("glColor3uiv");
- glad_glColor3us = (PFNGLCOLOR3USPROC)load("glColor3us");
- glad_glColor3usv = (PFNGLCOLOR3USVPROC)load("glColor3usv");
- glad_glColor4b = (PFNGLCOLOR4BPROC)load("glColor4b");
- glad_glColor4bv = (PFNGLCOLOR4BVPROC)load("glColor4bv");
- glad_glColor4d = (PFNGLCOLOR4DPROC)load("glColor4d");
- glad_glColor4dv = (PFNGLCOLOR4DVPROC)load("glColor4dv");
- glad_glColor4f = (PFNGLCOLOR4FPROC)load("glColor4f");
- glad_glColor4fv = (PFNGLCOLOR4FVPROC)load("glColor4fv");
- glad_glColor4i = (PFNGLCOLOR4IPROC)load("glColor4i");
- glad_glColor4iv = (PFNGLCOLOR4IVPROC)load("glColor4iv");
- glad_glColor4s = (PFNGLCOLOR4SPROC)load("glColor4s");
- glad_glColor4sv = (PFNGLCOLOR4SVPROC)load("glColor4sv");
- glad_glColor4ub = (PFNGLCOLOR4UBPROC)load("glColor4ub");
- glad_glColor4ubv = (PFNGLCOLOR4UBVPROC)load("glColor4ubv");
- glad_glColor4ui = (PFNGLCOLOR4UIPROC)load("glColor4ui");
- glad_glColor4uiv = (PFNGLCOLOR4UIVPROC)load("glColor4uiv");
- glad_glColor4us = (PFNGLCOLOR4USPROC)load("glColor4us");
- glad_glColor4usv = (PFNGLCOLOR4USVPROC)load("glColor4usv");
- glad_glEdgeFlag = (PFNGLEDGEFLAGPROC)load("glEdgeFlag");
- glad_glEdgeFlagv = (PFNGLEDGEFLAGVPROC)load("glEdgeFlagv");
- glad_glEnd = (PFNGLENDPROC)load("glEnd");
- glad_glIndexd = (PFNGLINDEXDPROC)load("glIndexd");
- glad_glIndexdv = (PFNGLINDEXDVPROC)load("glIndexdv");
- glad_glIndexf = (PFNGLINDEXFPROC)load("glIndexf");
- glad_glIndexfv = (PFNGLINDEXFVPROC)load("glIndexfv");
- glad_glIndexi = (PFNGLINDEXIPROC)load("glIndexi");
- glad_glIndexiv = (PFNGLINDEXIVPROC)load("glIndexiv");
- glad_glIndexs = (PFNGLINDEXSPROC)load("glIndexs");
- glad_glIndexsv = (PFNGLINDEXSVPROC)load("glIndexsv");
- glad_glNormal3b = (PFNGLNORMAL3BPROC)load("glNormal3b");
- glad_glNormal3bv = (PFNGLNORMAL3BVPROC)load("glNormal3bv");
- glad_glNormal3d = (PFNGLNORMAL3DPROC)load("glNormal3d");
- glad_glNormal3dv = (PFNGLNORMAL3DVPROC)load("glNormal3dv");
- glad_glNormal3f = (PFNGLNORMAL3FPROC)load("glNormal3f");
- glad_glNormal3fv = (PFNGLNORMAL3FVPROC)load("glNormal3fv");
- glad_glNormal3i = (PFNGLNORMAL3IPROC)load("glNormal3i");
- glad_glNormal3iv = (PFNGLNORMAL3IVPROC)load("glNormal3iv");
- glad_glNormal3s = (PFNGLNORMAL3SPROC)load("glNormal3s");
- glad_glNormal3sv = (PFNGLNORMAL3SVPROC)load("glNormal3sv");
- glad_glRasterPos2d = (PFNGLRASTERPOS2DPROC)load("glRasterPos2d");
- glad_glRasterPos2dv = (PFNGLRASTERPOS2DVPROC)load("glRasterPos2dv");
- glad_glRasterPos2f = (PFNGLRASTERPOS2FPROC)load("glRasterPos2f");
- glad_glRasterPos2fv = (PFNGLRASTERPOS2FVPROC)load("glRasterPos2fv");
- glad_glRasterPos2i = (PFNGLRASTERPOS2IPROC)load("glRasterPos2i");
- glad_glRasterPos2iv = (PFNGLRASTERPOS2IVPROC)load("glRasterPos2iv");
- glad_glRasterPos2s = (PFNGLRASTERPOS2SPROC)load("glRasterPos2s");
- glad_glRasterPos2sv = (PFNGLRASTERPOS2SVPROC)load("glRasterPos2sv");
- glad_glRasterPos3d = (PFNGLRASTERPOS3DPROC)load("glRasterPos3d");
- glad_glRasterPos3dv = (PFNGLRASTERPOS3DVPROC)load("glRasterPos3dv");
- glad_glRasterPos3f = (PFNGLRASTERPOS3FPROC)load("glRasterPos3f");
- glad_glRasterPos3fv = (PFNGLRASTERPOS3FVPROC)load("glRasterPos3fv");
- glad_glRasterPos3i = (PFNGLRASTERPOS3IPROC)load("glRasterPos3i");
- glad_glRasterPos3iv = (PFNGLRASTERPOS3IVPROC)load("glRasterPos3iv");
- glad_glRasterPos3s = (PFNGLRASTERPOS3SPROC)load("glRasterPos3s");
- glad_glRasterPos3sv = (PFNGLRASTERPOS3SVPROC)load("glRasterPos3sv");
- glad_glRasterPos4d = (PFNGLRASTERPOS4DPROC)load("glRasterPos4d");
- glad_glRasterPos4dv = (PFNGLRASTERPOS4DVPROC)load("glRasterPos4dv");
- glad_glRasterPos4f = (PFNGLRASTERPOS4FPROC)load("glRasterPos4f");
- glad_glRasterPos4fv = (PFNGLRASTERPOS4FVPROC)load("glRasterPos4fv");
- glad_glRasterPos4i = (PFNGLRASTERPOS4IPROC)load("glRasterPos4i");
- glad_glRasterPos4iv = (PFNGLRASTERPOS4IVPROC)load("glRasterPos4iv");
- glad_glRasterPos4s = (PFNGLRASTERPOS4SPROC)load("glRasterPos4s");
- glad_glRasterPos4sv = (PFNGLRASTERPOS4SVPROC)load("glRasterPos4sv");
- glad_glRectd = (PFNGLRECTDPROC)load("glRectd");
- glad_glRectdv = (PFNGLRECTDVPROC)load("glRectdv");
- glad_glRectf = (PFNGLRECTFPROC)load("glRectf");
- glad_glRectfv = (PFNGLRECTFVPROC)load("glRectfv");
- glad_glRecti = (PFNGLRECTIPROC)load("glRecti");
- glad_glRectiv = (PFNGLRECTIVPROC)load("glRectiv");
- glad_glRects = (PFNGLRECTSPROC)load("glRects");
- glad_glRectsv = (PFNGLRECTSVPROC)load("glRectsv");
- glad_glTexCoord1d = (PFNGLTEXCOORD1DPROC)load("glTexCoord1d");
- glad_glTexCoord1dv = (PFNGLTEXCOORD1DVPROC)load("glTexCoord1dv");
- glad_glTexCoord1f = (PFNGLTEXCOORD1FPROC)load("glTexCoord1f");
- glad_glTexCoord1fv = (PFNGLTEXCOORD1FVPROC)load("glTexCoord1fv");
- glad_glTexCoord1i = (PFNGLTEXCOORD1IPROC)load("glTexCoord1i");
- glad_glTexCoord1iv = (PFNGLTEXCOORD1IVPROC)load("glTexCoord1iv");
- glad_glTexCoord1s = (PFNGLTEXCOORD1SPROC)load("glTexCoord1s");
- glad_glTexCoord1sv = (PFNGLTEXCOORD1SVPROC)load("glTexCoord1sv");
- glad_glTexCoord2d = (PFNGLTEXCOORD2DPROC)load("glTexCoord2d");
- glad_glTexCoord2dv = (PFNGLTEXCOORD2DVPROC)load("glTexCoord2dv");
- glad_glTexCoord2f = (PFNGLTEXCOORD2FPROC)load("glTexCoord2f");
- glad_glTexCoord2fv = (PFNGLTEXCOORD2FVPROC)load("glTexCoord2fv");
- glad_glTexCoord2i = (PFNGLTEXCOORD2IPROC)load("glTexCoord2i");
- glad_glTexCoord2iv = (PFNGLTEXCOORD2IVPROC)load("glTexCoord2iv");
- glad_glTexCoord2s = (PFNGLTEXCOORD2SPROC)load("glTexCoord2s");
- glad_glTexCoord2sv = (PFNGLTEXCOORD2SVPROC)load("glTexCoord2sv");
- glad_glTexCoord3d = (PFNGLTEXCOORD3DPROC)load("glTexCoord3d");
- glad_glTexCoord3dv = (PFNGLTEXCOORD3DVPROC)load("glTexCoord3dv");
- glad_glTexCoord3f = (PFNGLTEXCOORD3FPROC)load("glTexCoord3f");
- glad_glTexCoord3fv = (PFNGLTEXCOORD3FVPROC)load("glTexCoord3fv");
- glad_glTexCoord3i = (PFNGLTEXCOORD3IPROC)load("glTexCoord3i");
- glad_glTexCoord3iv = (PFNGLTEXCOORD3IVPROC)load("glTexCoord3iv");
- glad_glTexCoord3s = (PFNGLTEXCOORD3SPROC)load("glTexCoord3s");
- glad_glTexCoord3sv = (PFNGLTEXCOORD3SVPROC)load("glTexCoord3sv");
- glad_glTexCoord4d = (PFNGLTEXCOORD4DPROC)load("glTexCoord4d");
- glad_glTexCoord4dv = (PFNGLTEXCOORD4DVPROC)load("glTexCoord4dv");
- glad_glTexCoord4f = (PFNGLTEXCOORD4FPROC)load("glTexCoord4f");
- glad_glTexCoord4fv = (PFNGLTEXCOORD4FVPROC)load("glTexCoord4fv");
- glad_glTexCoord4i = (PFNGLTEXCOORD4IPROC)load("glTexCoord4i");
- glad_glTexCoord4iv = (PFNGLTEXCOORD4IVPROC)load("glTexCoord4iv");
- glad_glTexCoord4s = (PFNGLTEXCOORD4SPROC)load("glTexCoord4s");
- glad_glTexCoord4sv = (PFNGLTEXCOORD4SVPROC)load("glTexCoord4sv");
- glad_glVertex2d = (PFNGLVERTEX2DPROC)load("glVertex2d");
- glad_glVertex2dv = (PFNGLVERTEX2DVPROC)load("glVertex2dv");
- glad_glVertex2f = (PFNGLVERTEX2FPROC)load("glVertex2f");
- glad_glVertex2fv = (PFNGLVERTEX2FVPROC)load("glVertex2fv");
- glad_glVertex2i = (PFNGLVERTEX2IPROC)load("glVertex2i");
- glad_glVertex2iv = (PFNGLVERTEX2IVPROC)load("glVertex2iv");
- glad_glVertex2s = (PFNGLVERTEX2SPROC)load("glVertex2s");
- glad_glVertex2sv = (PFNGLVERTEX2SVPROC)load("glVertex2sv");
- glad_glVertex3d = (PFNGLVERTEX3DPROC)load("glVertex3d");
- glad_glVertex3dv = (PFNGLVERTEX3DVPROC)load("glVertex3dv");
- glad_glVertex3f = (PFNGLVERTEX3FPROC)load("glVertex3f");
- glad_glVertex3fv = (PFNGLVERTEX3FVPROC)load("glVertex3fv");
- glad_glVertex3i = (PFNGLVERTEX3IPROC)load("glVertex3i");
- glad_glVertex3iv = (PFNGLVERTEX3IVPROC)load("glVertex3iv");
- glad_glVertex3s = (PFNGLVERTEX3SPROC)load("glVertex3s");
- glad_glVertex3sv = (PFNGLVERTEX3SVPROC)load("glVertex3sv");
- glad_glVertex4d = (PFNGLVERTEX4DPROC)load("glVertex4d");
- glad_glVertex4dv = (PFNGLVERTEX4DVPROC)load("glVertex4dv");
- glad_glVertex4f = (PFNGLVERTEX4FPROC)load("glVertex4f");
- glad_glVertex4fv = (PFNGLVERTEX4FVPROC)load("glVertex4fv");
- glad_glVertex4i = (PFNGLVERTEX4IPROC)load("glVertex4i");
- glad_glVertex4iv = (PFNGLVERTEX4IVPROC)load("glVertex4iv");
- glad_glVertex4s = (PFNGLVERTEX4SPROC)load("glVertex4s");
- glad_glVertex4sv = (PFNGLVERTEX4SVPROC)load("glVertex4sv");
- glad_glClipPlane = (PFNGLCLIPPLANEPROC)load("glClipPlane");
- glad_glColorMaterial = (PFNGLCOLORMATERIALPROC)load("glColorMaterial");
- glad_glFogf = (PFNGLFOGFPROC)load("glFogf");
- glad_glFogfv = (PFNGLFOGFVPROC)load("glFogfv");
- glad_glFogi = (PFNGLFOGIPROC)load("glFogi");
- glad_glFogiv = (PFNGLFOGIVPROC)load("glFogiv");
- glad_glLightf = (PFNGLLIGHTFPROC)load("glLightf");
- glad_glLightfv = (PFNGLLIGHTFVPROC)load("glLightfv");
- glad_glLighti = (PFNGLLIGHTIPROC)load("glLighti");
- glad_glLightiv = (PFNGLLIGHTIVPROC)load("glLightiv");
- glad_glLightModelf = (PFNGLLIGHTMODELFPROC)load("glLightModelf");
- glad_glLightModelfv = (PFNGLLIGHTMODELFVPROC)load("glLightModelfv");
- glad_glLightModeli = (PFNGLLIGHTMODELIPROC)load("glLightModeli");
- glad_glLightModeliv = (PFNGLLIGHTMODELIVPROC)load("glLightModeliv");
- glad_glLineStipple = (PFNGLLINESTIPPLEPROC)load("glLineStipple");
- glad_glMaterialf = (PFNGLMATERIALFPROC)load("glMaterialf");
- glad_glMaterialfv = (PFNGLMATERIALFVPROC)load("glMaterialfv");
- glad_glMateriali = (PFNGLMATERIALIPROC)load("glMateriali");
- glad_glMaterialiv = (PFNGLMATERIALIVPROC)load("glMaterialiv");
- glad_glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC)load("glPolygonStipple");
- glad_glShadeModel = (PFNGLSHADEMODELPROC)load("glShadeModel");
- glad_glTexEnvf = (PFNGLTEXENVFPROC)load("glTexEnvf");
- glad_glTexEnvfv = (PFNGLTEXENVFVPROC)load("glTexEnvfv");
- glad_glTexEnvi = (PFNGLTEXENVIPROC)load("glTexEnvi");
- glad_glTexEnviv = (PFNGLTEXENVIVPROC)load("glTexEnviv");
- glad_glTexGend = (PFNGLTEXGENDPROC)load("glTexGend");
- glad_glTexGendv = (PFNGLTEXGENDVPROC)load("glTexGendv");
- glad_glTexGenf = (PFNGLTEXGENFPROC)load("glTexGenf");
- glad_glTexGenfv = (PFNGLTEXGENFVPROC)load("glTexGenfv");
- glad_glTexGeni = (PFNGLTEXGENIPROC)load("glTexGeni");
- glad_glTexGeniv = (PFNGLTEXGENIVPROC)load("glTexGeniv");
- glad_glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC)load("glFeedbackBuffer");
- glad_glSelectBuffer = (PFNGLSELECTBUFFERPROC)load("glSelectBuffer");
- glad_glRenderMode = (PFNGLRENDERMODEPROC)load("glRenderMode");
- glad_glInitNames = (PFNGLINITNAMESPROC)load("glInitNames");
- glad_glLoadName = (PFNGLLOADNAMEPROC)load("glLoadName");
- glad_glPassThrough = (PFNGLPASSTHROUGHPROC)load("glPassThrough");
- glad_glPopName = (PFNGLPOPNAMEPROC)load("glPopName");
- glad_glPushName = (PFNGLPUSHNAMEPROC)load("glPushName");
- glad_glClearAccum = (PFNGLCLEARACCUMPROC)load("glClearAccum");
- glad_glClearIndex = (PFNGLCLEARINDEXPROC)load("glClearIndex");
- glad_glIndexMask = (PFNGLINDEXMASKPROC)load("glIndexMask");
- glad_glAccum = (PFNGLACCUMPROC)load("glAccum");
- glad_glPopAttrib = (PFNGLPOPATTRIBPROC)load("glPopAttrib");
- glad_glPushAttrib = (PFNGLPUSHATTRIBPROC)load("glPushAttrib");
- glad_glMap1d = (PFNGLMAP1DPROC)load("glMap1d");
- glad_glMap1f = (PFNGLMAP1FPROC)load("glMap1f");
- glad_glMap2d = (PFNGLMAP2DPROC)load("glMap2d");
- glad_glMap2f = (PFNGLMAP2FPROC)load("glMap2f");
- glad_glMapGrid1d = (PFNGLMAPGRID1DPROC)load("glMapGrid1d");
- glad_glMapGrid1f = (PFNGLMAPGRID1FPROC)load("glMapGrid1f");
- glad_glMapGrid2d = (PFNGLMAPGRID2DPROC)load("glMapGrid2d");
- glad_glMapGrid2f = (PFNGLMAPGRID2FPROC)load("glMapGrid2f");
- glad_glEvalCoord1d = (PFNGLEVALCOORD1DPROC)load("glEvalCoord1d");
- glad_glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC)load("glEvalCoord1dv");
- glad_glEvalCoord1f = (PFNGLEVALCOORD1FPROC)load("glEvalCoord1f");
- glad_glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC)load("glEvalCoord1fv");
- glad_glEvalCoord2d = (PFNGLEVALCOORD2DPROC)load("glEvalCoord2d");
- glad_glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC)load("glEvalCoord2dv");
- glad_glEvalCoord2f = (PFNGLEVALCOORD2FPROC)load("glEvalCoord2f");
- glad_glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC)load("glEvalCoord2fv");
- glad_glEvalMesh1 = (PFNGLEVALMESH1PROC)load("glEvalMesh1");
- glad_glEvalPoint1 = (PFNGLEVALPOINT1PROC)load("glEvalPoint1");
- glad_glEvalMesh2 = (PFNGLEVALMESH2PROC)load("glEvalMesh2");
- glad_glEvalPoint2 = (PFNGLEVALPOINT2PROC)load("glEvalPoint2");
- glad_glAlphaFunc = (PFNGLALPHAFUNCPROC)load("glAlphaFunc");
- glad_glPixelZoom = (PFNGLPIXELZOOMPROC)load("glPixelZoom");
- glad_glPixelTransferf = (PFNGLPIXELTRANSFERFPROC)load("glPixelTransferf");
- glad_glPixelTransferi = (PFNGLPIXELTRANSFERIPROC)load("glPixelTransferi");
- glad_glPixelMapfv = (PFNGLPIXELMAPFVPROC)load("glPixelMapfv");
- glad_glPixelMapuiv = (PFNGLPIXELMAPUIVPROC)load("glPixelMapuiv");
- glad_glPixelMapusv = (PFNGLPIXELMAPUSVPROC)load("glPixelMapusv");
- glad_glCopyPixels = (PFNGLCOPYPIXELSPROC)load("glCopyPixels");
- glad_glDrawPixels = (PFNGLDRAWPIXELSPROC)load("glDrawPixels");
- glad_glGetClipPlane = (PFNGLGETCLIPPLANEPROC)load("glGetClipPlane");
- glad_glGetLightfv = (PFNGLGETLIGHTFVPROC)load("glGetLightfv");
- glad_glGetLightiv = (PFNGLGETLIGHTIVPROC)load("glGetLightiv");
- glad_glGetMapdv = (PFNGLGETMAPDVPROC)load("glGetMapdv");
- glad_glGetMapfv = (PFNGLGETMAPFVPROC)load("glGetMapfv");
- glad_glGetMapiv = (PFNGLGETMAPIVPROC)load("glGetMapiv");
- glad_glGetMaterialfv = (PFNGLGETMATERIALFVPROC)load("glGetMaterialfv");
- glad_glGetMaterialiv = (PFNGLGETMATERIALIVPROC)load("glGetMaterialiv");
- glad_glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC)load("glGetPixelMapfv");
- glad_glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC)load("glGetPixelMapuiv");
- glad_glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC)load("glGetPixelMapusv");
- glad_glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC)load("glGetPolygonStipple");
- glad_glGetTexEnvfv = (PFNGLGETTEXENVFVPROC)load("glGetTexEnvfv");
- glad_glGetTexEnviv = (PFNGLGETTEXENVIVPROC)load("glGetTexEnviv");
- glad_glGetTexGendv = (PFNGLGETTEXGENDVPROC)load("glGetTexGendv");
- glad_glGetTexGenfv = (PFNGLGETTEXGENFVPROC)load("glGetTexGenfv");
- glad_glGetTexGeniv = (PFNGLGETTEXGENIVPROC)load("glGetTexGeniv");
- glad_glIsList = (PFNGLISLISTPROC)load("glIsList");
- glad_glFrustum = (PFNGLFRUSTUMPROC)load("glFrustum");
- glad_glLoadIdentity = (PFNGLLOADIDENTITYPROC)load("glLoadIdentity");
- glad_glLoadMatrixf = (PFNGLLOADMATRIXFPROC)load("glLoadMatrixf");
- glad_glLoadMatrixd = (PFNGLLOADMATRIXDPROC)load("glLoadMatrixd");
- glad_glMatrixMode = (PFNGLMATRIXMODEPROC)load("glMatrixMode");
- glad_glMultMatrixf = (PFNGLMULTMATRIXFPROC)load("glMultMatrixf");
- glad_glMultMatrixd = (PFNGLMULTMATRIXDPROC)load("glMultMatrixd");
- glad_glOrtho = (PFNGLORTHOPROC)load("glOrtho");
- glad_glPopMatrix = (PFNGLPOPMATRIXPROC)load("glPopMatrix");
- glad_glPushMatrix = (PFNGLPUSHMATRIXPROC)load("glPushMatrix");
- glad_glRotated = (PFNGLROTATEDPROC)load("glRotated");
- glad_glRotatef = (PFNGLROTATEFPROC)load("glRotatef");
- glad_glScaled = (PFNGLSCALEDPROC)load("glScaled");
- glad_glScalef = (PFNGLSCALEFPROC)load("glScalef");
- glad_glTranslated = (PFNGLTRANSLATEDPROC)load("glTranslated");
- glad_glTranslatef = (PFNGLTRANSLATEFPROC)load("glTranslatef");
-}
-static void load_GL_VERSION_1_1(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_1) return;
- glad_glDrawArrays = (PFNGLDRAWARRAYSPROC)load("glDrawArrays");
- glad_glDrawElements = (PFNGLDRAWELEMENTSPROC)load("glDrawElements");
- glad_glGetPointerv = (PFNGLGETPOINTERVPROC)load("glGetPointerv");
- glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC)load("glPolygonOffset");
- glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC)load("glCopyTexImage1D");
- glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC)load("glCopyTexImage2D");
- glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC)load("glCopyTexSubImage1D");
- glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC)load("glCopyTexSubImage2D");
- glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC)load("glTexSubImage1D");
- glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)load("glTexSubImage2D");
- glad_glBindTexture = (PFNGLBINDTEXTUREPROC)load("glBindTexture");
- glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC)load("glDeleteTextures");
- glad_glGenTextures = (PFNGLGENTEXTURESPROC)load("glGenTextures");
- glad_glIsTexture = (PFNGLISTEXTUREPROC)load("glIsTexture");
- glad_glArrayElement = (PFNGLARRAYELEMENTPROC)load("glArrayElement");
- glad_glColorPointer = (PFNGLCOLORPOINTERPROC)load("glColorPointer");
- glad_glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC)load("glDisableClientState");
- glad_glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC)load("glEdgeFlagPointer");
- glad_glEnableClientState = (PFNGLENABLECLIENTSTATEPROC)load("glEnableClientState");
- glad_glIndexPointer = (PFNGLINDEXPOINTERPROC)load("glIndexPointer");
- glad_glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC)load("glInterleavedArrays");
- glad_glNormalPointer = (PFNGLNORMALPOINTERPROC)load("glNormalPointer");
- glad_glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC)load("glTexCoordPointer");
- glad_glVertexPointer = (PFNGLVERTEXPOINTERPROC)load("glVertexPointer");
- glad_glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC)load("glAreTexturesResident");
- glad_glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC)load("glPrioritizeTextures");
- glad_glIndexub = (PFNGLINDEXUBPROC)load("glIndexub");
- glad_glIndexubv = (PFNGLINDEXUBVPROC)load("glIndexubv");
- glad_glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC)load("glPopClientAttrib");
- glad_glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC)load("glPushClientAttrib");
-}
-static void load_GL_VERSION_1_2(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_2) return;
- glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)load("glDrawRangeElements");
- glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC)load("glTexImage3D");
- glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)load("glTexSubImage3D");
- glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)load("glCopyTexSubImage3D");
-}
-static void load_GL_VERSION_1_3(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_3) return;
- glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC)load("glActiveTexture");
- glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)load("glSampleCoverage");
- glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)load("glCompressedTexImage3D");
- glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)load("glCompressedTexImage2D");
- glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)load("glCompressedTexImage1D");
- glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)load("glCompressedTexSubImage3D");
- glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)load("glCompressedTexSubImage2D");
- glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)load("glCompressedTexSubImage1D");
- glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)load("glGetCompressedTexImage");
- glad_glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)load("glClientActiveTexture");
- glad_glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)load("glMultiTexCoord1d");
- glad_glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)load("glMultiTexCoord1dv");
- glad_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)load("glMultiTexCoord1f");
- glad_glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)load("glMultiTexCoord1fv");
- glad_glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)load("glMultiTexCoord1i");
- glad_glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)load("glMultiTexCoord1iv");
- glad_glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)load("glMultiTexCoord1s");
- glad_glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)load("glMultiTexCoord1sv");
- glad_glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)load("glMultiTexCoord2d");
- glad_glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)load("glMultiTexCoord2dv");
- glad_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)load("glMultiTexCoord2f");
- glad_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)load("glMultiTexCoord2fv");
- glad_glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)load("glMultiTexCoord2i");
- glad_glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)load("glMultiTexCoord2iv");
- glad_glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)load("glMultiTexCoord2s");
- glad_glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)load("glMultiTexCoord2sv");
- glad_glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)load("glMultiTexCoord3d");
- glad_glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)load("glMultiTexCoord3dv");
- glad_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)load("glMultiTexCoord3f");
- glad_glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)load("glMultiTexCoord3fv");
- glad_glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)load("glMultiTexCoord3i");
- glad_glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)load("glMultiTexCoord3iv");
- glad_glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)load("glMultiTexCoord3s");
- glad_glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)load("glMultiTexCoord3sv");
- glad_glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)load("glMultiTexCoord4d");
- glad_glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)load("glMultiTexCoord4dv");
- glad_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)load("glMultiTexCoord4f");
- glad_glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)load("glMultiTexCoord4fv");
- glad_glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)load("glMultiTexCoord4i");
- glad_glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)load("glMultiTexCoord4iv");
- glad_glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)load("glMultiTexCoord4s");
- glad_glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)load("glMultiTexCoord4sv");
- glad_glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)load("glLoadTransposeMatrixf");
- glad_glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)load("glLoadTransposeMatrixd");
- glad_glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)load("glMultTransposeMatrixf");
- glad_glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)load("glMultTransposeMatrixd");
-}
-static void load_GL_VERSION_1_4(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_4) return;
- glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)load("glBlendFuncSeparate");
- glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)load("glMultiDrawArrays");
- glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)load("glMultiDrawElements");
- glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC)load("glPointParameterf");
- glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)load("glPointParameterfv");
- glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC)load("glPointParameteri");
- glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)load("glPointParameteriv");
- glad_glFogCoordf = (PFNGLFOGCOORDFPROC)load("glFogCoordf");
- glad_glFogCoordfv = (PFNGLFOGCOORDFVPROC)load("glFogCoordfv");
- glad_glFogCoordd = (PFNGLFOGCOORDDPROC)load("glFogCoordd");
- glad_glFogCoorddv = (PFNGLFOGCOORDDVPROC)load("glFogCoorddv");
- glad_glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)load("glFogCoordPointer");
- glad_glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)load("glSecondaryColor3b");
- glad_glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)load("glSecondaryColor3bv");
- glad_glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)load("glSecondaryColor3d");
- glad_glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)load("glSecondaryColor3dv");
- glad_glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)load("glSecondaryColor3f");
- glad_glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)load("glSecondaryColor3fv");
- glad_glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)load("glSecondaryColor3i");
- glad_glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)load("glSecondaryColor3iv");
- glad_glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)load("glSecondaryColor3s");
- glad_glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)load("glSecondaryColor3sv");
- glad_glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)load("glSecondaryColor3ub");
- glad_glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)load("glSecondaryColor3ubv");
- glad_glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)load("glSecondaryColor3ui");
- glad_glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)load("glSecondaryColor3uiv");
- glad_glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)load("glSecondaryColor3us");
- glad_glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)load("glSecondaryColor3usv");
- glad_glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)load("glSecondaryColorPointer");
- glad_glWindowPos2d = (PFNGLWINDOWPOS2DPROC)load("glWindowPos2d");
- glad_glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)load("glWindowPos2dv");
- glad_glWindowPos2f = (PFNGLWINDOWPOS2FPROC)load("glWindowPos2f");
- glad_glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)load("glWindowPos2fv");
- glad_glWindowPos2i = (PFNGLWINDOWPOS2IPROC)load("glWindowPos2i");
- glad_glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)load("glWindowPos2iv");
- glad_glWindowPos2s = (PFNGLWINDOWPOS2SPROC)load("glWindowPos2s");
- glad_glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)load("glWindowPos2sv");
- glad_glWindowPos3d = (PFNGLWINDOWPOS3DPROC)load("glWindowPos3d");
- glad_glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)load("glWindowPos3dv");
- glad_glWindowPos3f = (PFNGLWINDOWPOS3FPROC)load("glWindowPos3f");
- glad_glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)load("glWindowPos3fv");
- glad_glWindowPos3i = (PFNGLWINDOWPOS3IPROC)load("glWindowPos3i");
- glad_glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)load("glWindowPos3iv");
- glad_glWindowPos3s = (PFNGLWINDOWPOS3SPROC)load("glWindowPos3s");
- glad_glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)load("glWindowPos3sv");
- glad_glBlendColor = (PFNGLBLENDCOLORPROC)load("glBlendColor");
- glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC)load("glBlendEquation");
-}
-static void load_GL_VERSION_1_5(GLADloadproc load) {
- if(!GLAD_GL_VERSION_1_5) return;
- glad_glGenQueries = (PFNGLGENQUERIESPROC)load("glGenQueries");
- glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC)load("glDeleteQueries");
- glad_glIsQuery = (PFNGLISQUERYPROC)load("glIsQuery");
- glad_glBeginQuery = (PFNGLBEGINQUERYPROC)load("glBeginQuery");
- glad_glEndQuery = (PFNGLENDQUERYPROC)load("glEndQuery");
- glad_glGetQueryiv = (PFNGLGETQUERYIVPROC)load("glGetQueryiv");
- glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)load("glGetQueryObjectiv");
- glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)load("glGetQueryObjectuiv");
- glad_glBindBuffer = (PFNGLBINDBUFFERPROC)load("glBindBuffer");
- glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)load("glDeleteBuffers");
- glad_glGenBuffers = (PFNGLGENBUFFERSPROC)load("glGenBuffers");
- glad_glIsBuffer = (PFNGLISBUFFERPROC)load("glIsBuffer");
- glad_glBufferData = (PFNGLBUFFERDATAPROC)load("glBufferData");
- glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC)load("glBufferSubData");
- glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)load("glGetBufferSubData");
- glad_glMapBuffer = (PFNGLMAPBUFFERPROC)load("glMapBuffer");
- glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)load("glUnmapBuffer");
- glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv");
- glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)load("glGetBufferPointerv");
-}
-static void load_GL_VERSION_2_0(GLADloadproc load) {
- if(!GLAD_GL_VERSION_2_0) return;
- glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)load("glBlendEquationSeparate");
- glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)load("glDrawBuffers");
- glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)load("glStencilOpSeparate");
- glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)load("glStencilFuncSeparate");
- glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)load("glStencilMaskSeparate");
- glad_glAttachShader = (PFNGLATTACHSHADERPROC)load("glAttachShader");
- glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)load("glBindAttribLocation");
- glad_glCompileShader = (PFNGLCOMPILESHADERPROC)load("glCompileShader");
- glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC)load("glCreateProgram");
- glad_glCreateShader = (PFNGLCREATESHADERPROC)load("glCreateShader");
- glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC)load("glDeleteProgram");
- glad_glDeleteShader = (PFNGLDELETESHADERPROC)load("glDeleteShader");
- glad_glDetachShader = (PFNGLDETACHSHADERPROC)load("glDetachShader");
- glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)load("glDisableVertexAttribArray");
- glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)load("glEnableVertexAttribArray");
- glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)load("glGetActiveAttrib");
- glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)load("glGetActiveUniform");
- glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)load("glGetAttachedShaders");
- glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)load("glGetAttribLocation");
- glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC)load("glGetProgramiv");
- glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)load("glGetProgramInfoLog");
- glad_glGetShaderiv = (PFNGLGETSHADERIVPROC)load("glGetShaderiv");
- glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)load("glGetShaderInfoLog");
- glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)load("glGetShaderSource");
- glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)load("glGetUniformLocation");
- glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC)load("glGetUniformfv");
- glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC)load("glGetUniformiv");
- glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)load("glGetVertexAttribdv");
- glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)load("glGetVertexAttribfv");
- glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)load("glGetVertexAttribiv");
- glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)load("glGetVertexAttribPointerv");
- glad_glIsProgram = (PFNGLISPROGRAMPROC)load("glIsProgram");
- glad_glIsShader = (PFNGLISSHADERPROC)load("glIsShader");
- glad_glLinkProgram = (PFNGLLINKPROGRAMPROC)load("glLinkProgram");
- glad_glShaderSource = (PFNGLSHADERSOURCEPROC)load("glShaderSource");
- glad_glUseProgram = (PFNGLUSEPROGRAMPROC)load("glUseProgram");
- glad_glUniform1f = (PFNGLUNIFORM1FPROC)load("glUniform1f");
- glad_glUniform2f = (PFNGLUNIFORM2FPROC)load("glUniform2f");
- glad_glUniform3f = (PFNGLUNIFORM3FPROC)load("glUniform3f");
- glad_glUniform4f = (PFNGLUNIFORM4FPROC)load("glUniform4f");
- glad_glUniform1i = (PFNGLUNIFORM1IPROC)load("glUniform1i");
- glad_glUniform2i = (PFNGLUNIFORM2IPROC)load("glUniform2i");
- glad_glUniform3i = (PFNGLUNIFORM3IPROC)load("glUniform3i");
- glad_glUniform4i = (PFNGLUNIFORM4IPROC)load("glUniform4i");
- glad_glUniform1fv = (PFNGLUNIFORM1FVPROC)load("glUniform1fv");
- glad_glUniform2fv = (PFNGLUNIFORM2FVPROC)load("glUniform2fv");
- glad_glUniform3fv = (PFNGLUNIFORM3FVPROC)load("glUniform3fv");
- glad_glUniform4fv = (PFNGLUNIFORM4FVPROC)load("glUniform4fv");
- glad_glUniform1iv = (PFNGLUNIFORM1IVPROC)load("glUniform1iv");
- glad_glUniform2iv = (PFNGLUNIFORM2IVPROC)load("glUniform2iv");
- glad_glUniform3iv = (PFNGLUNIFORM3IVPROC)load("glUniform3iv");
- glad_glUniform4iv = (PFNGLUNIFORM4IVPROC)load("glUniform4iv");
- glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)load("glUniformMatrix2fv");
- glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)load("glUniformMatrix3fv");
- glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)load("glUniformMatrix4fv");
- glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)load("glValidateProgram");
- glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)load("glVertexAttrib1d");
- glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)load("glVertexAttrib1dv");
- glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)load("glVertexAttrib1f");
- glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)load("glVertexAttrib1fv");
- glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)load("glVertexAttrib1s");
- glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)load("glVertexAttrib1sv");
- glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)load("glVertexAttrib2d");
- glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)load("glVertexAttrib2dv");
- glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)load("glVertexAttrib2f");
- glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)load("glVertexAttrib2fv");
- glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)load("glVertexAttrib2s");
- glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)load("glVertexAttrib2sv");
- glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)load("glVertexAttrib3d");
- glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)load("glVertexAttrib3dv");
- glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)load("glVertexAttrib3f");
- glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)load("glVertexAttrib3fv");
- glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)load("glVertexAttrib3s");
- glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)load("glVertexAttrib3sv");
- glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)load("glVertexAttrib4Nbv");
- glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)load("glVertexAttrib4Niv");
- glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)load("glVertexAttrib4Nsv");
- glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)load("glVertexAttrib4Nub");
- glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)load("glVertexAttrib4Nubv");
- glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)load("glVertexAttrib4Nuiv");
- glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)load("glVertexAttrib4Nusv");
- glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)load("glVertexAttrib4bv");
- glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)load("glVertexAttrib4d");
- glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)load("glVertexAttrib4dv");
- glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)load("glVertexAttrib4f");
- glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)load("glVertexAttrib4fv");
- glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)load("glVertexAttrib4iv");
- glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)load("glVertexAttrib4s");
- glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)load("glVertexAttrib4sv");
- glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)load("glVertexAttrib4ubv");
- glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)load("glVertexAttrib4uiv");
- glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)load("glVertexAttrib4usv");
- glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)load("glVertexAttribPointer");
-}
-static void load_GL_VERSION_2_1(GLADloadproc load) {
- if(!GLAD_GL_VERSION_2_1) return;
- glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)load("glUniformMatrix2x3fv");
- glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)load("glUniformMatrix3x2fv");
- glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)load("glUniformMatrix2x4fv");
- glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)load("glUniformMatrix4x2fv");
- glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)load("glUniformMatrix3x4fv");
- glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)load("glUniformMatrix4x3fv");
-}
-static void load_GL_VERSION_3_0(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_0) return;
- glad_glColorMaski = (PFNGLCOLORMASKIPROC)load("glColorMaski");
- glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)load("glGetBooleani_v");
- glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v");
- glad_glEnablei = (PFNGLENABLEIPROC)load("glEnablei");
- glad_glDisablei = (PFNGLDISABLEIPROC)load("glDisablei");
- glad_glIsEnabledi = (PFNGLISENABLEDIPROC)load("glIsEnabledi");
- glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)load("glBeginTransformFeedback");
- glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)load("glEndTransformFeedback");
- glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange");
- glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase");
- glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)load("glTransformFeedbackVaryings");
- glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)load("glGetTransformFeedbackVarying");
- glad_glClampColor = (PFNGLCLAMPCOLORPROC)load("glClampColor");
- glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)load("glBeginConditionalRender");
- glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)load("glEndConditionalRender");
- glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)load("glVertexAttribIPointer");
- glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)load("glGetVertexAttribIiv");
- glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)load("glGetVertexAttribIuiv");
- glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)load("glVertexAttribI1i");
- glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)load("glVertexAttribI2i");
- glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)load("glVertexAttribI3i");
- glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)load("glVertexAttribI4i");
- glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)load("glVertexAttribI1ui");
- glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)load("glVertexAttribI2ui");
- glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)load("glVertexAttribI3ui");
- glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)load("glVertexAttribI4ui");
- glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)load("glVertexAttribI1iv");
- glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)load("glVertexAttribI2iv");
- glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)load("glVertexAttribI3iv");
- glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)load("glVertexAttribI4iv");
- glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)load("glVertexAttribI1uiv");
- glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)load("glVertexAttribI2uiv");
- glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)load("glVertexAttribI3uiv");
- glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)load("glVertexAttribI4uiv");
- glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)load("glVertexAttribI4bv");
- glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)load("glVertexAttribI4sv");
- glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)load("glVertexAttribI4ubv");
- glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)load("glVertexAttribI4usv");
- glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)load("glGetUniformuiv");
- glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)load("glBindFragDataLocation");
- glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)load("glGetFragDataLocation");
- glad_glUniform1ui = (PFNGLUNIFORM1UIPROC)load("glUniform1ui");
- glad_glUniform2ui = (PFNGLUNIFORM2UIPROC)load("glUniform2ui");
- glad_glUniform3ui = (PFNGLUNIFORM3UIPROC)load("glUniform3ui");
- glad_glUniform4ui = (PFNGLUNIFORM4UIPROC)load("glUniform4ui");
- glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC)load("glUniform1uiv");
- glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC)load("glUniform2uiv");
- glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC)load("glUniform3uiv");
- glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC)load("glUniform4uiv");
- glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)load("glTexParameterIiv");
- glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)load("glTexParameterIuiv");
- glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)load("glGetTexParameterIiv");
- glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)load("glGetTexParameterIuiv");
- glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)load("glClearBufferiv");
- glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)load("glClearBufferuiv");
- glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)load("glClearBufferfv");
- glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)load("glClearBufferfi");
- glad_glGetStringi = (PFNGLGETSTRINGIPROC)load("glGetStringi");
- glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer");
- glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer");
- glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers");
- glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers");
- glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage");
- glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv");
- glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer");
- glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer");
- glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers");
- glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers");
- glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus");
- glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)load("glFramebufferTexture1D");
- glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D");
- glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)load("glFramebufferTexture3D");
- glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer");
- glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv");
- glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap");
- glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer");
- glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample");
- glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer");
- glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)load("glMapBufferRange");
- glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)load("glFlushMappedBufferRange");
- glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)load("glBindVertexArray");
- glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)load("glDeleteVertexArrays");
- glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)load("glGenVertexArrays");
- glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC)load("glIsVertexArray");
-}
-static void load_GL_VERSION_3_1(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_1) return;
- glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)load("glDrawArraysInstanced");
- glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)load("glDrawElementsInstanced");
- glad_glTexBuffer = (PFNGLTEXBUFFERPROC)load("glTexBuffer");
- glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)load("glPrimitiveRestartIndex");
- glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)load("glCopyBufferSubData");
- glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)load("glGetUniformIndices");
- glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)load("glGetActiveUniformsiv");
- glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)load("glGetActiveUniformName");
- glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)load("glGetUniformBlockIndex");
- glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)load("glGetActiveUniformBlockiv");
- glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)load("glGetActiveUniformBlockName");
- glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)load("glUniformBlockBinding");
- glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange");
- glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase");
- glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v");
-}
-static void load_GL_VERSION_3_2(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_2) return;
- glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)load("glDrawElementsBaseVertex");
- glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)load("glDrawRangeElementsBaseVertex");
- glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)load("glDrawElementsInstancedBaseVertex");
- glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)load("glMultiDrawElementsBaseVertex");
- glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)load("glProvokingVertex");
- glad_glFenceSync = (PFNGLFENCESYNCPROC)load("glFenceSync");
- glad_glIsSync = (PFNGLISSYNCPROC)load("glIsSync");
- glad_glDeleteSync = (PFNGLDELETESYNCPROC)load("glDeleteSync");
- glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)load("glClientWaitSync");
- glad_glWaitSync = (PFNGLWAITSYNCPROC)load("glWaitSync");
- glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC)load("glGetInteger64v");
- glad_glGetSynciv = (PFNGLGETSYNCIVPROC)load("glGetSynciv");
- glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)load("glGetInteger64i_v");
- glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)load("glGetBufferParameteri64v");
- glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)load("glFramebufferTexture");
- glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)load("glTexImage2DMultisample");
- glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC)load("glTexImage3DMultisample");
- glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)load("glGetMultisamplefv");
- glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC)load("glSampleMaski");
-}
-static void load_GL_VERSION_3_3(GLADloadproc load) {
- if(!GLAD_GL_VERSION_3_3) return;
- glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)load("glBindFragDataLocationIndexed");
- glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)load("glGetFragDataIndex");
- glad_glGenSamplers = (PFNGLGENSAMPLERSPROC)load("glGenSamplers");
- glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)load("glDeleteSamplers");
- glad_glIsSampler = (PFNGLISSAMPLERPROC)load("glIsSampler");
- glad_glBindSampler = (PFNGLBINDSAMPLERPROC)load("glBindSampler");
- glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)load("glSamplerParameteri");
- glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)load("glSamplerParameteriv");
- glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)load("glSamplerParameterf");
- glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)load("glSamplerParameterfv");
- glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)load("glSamplerParameterIiv");
- glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)load("glSamplerParameterIuiv");
- glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)load("glGetSamplerParameteriv");
- glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)load("glGetSamplerParameterIiv");
- glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)load("glGetSamplerParameterfv");
- glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)load("glGetSamplerParameterIuiv");
- glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC)load("glQueryCounter");
- glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)load("glGetQueryObjecti64v");
- glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)load("glGetQueryObjectui64v");
- glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)load("glVertexAttribDivisor");
- glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)load("glVertexAttribP1ui");
- glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)load("glVertexAttribP1uiv");
- glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)load("glVertexAttribP2ui");
- glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)load("glVertexAttribP2uiv");
- glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)load("glVertexAttribP3ui");
- glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)load("glVertexAttribP3uiv");
- glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)load("glVertexAttribP4ui");
- glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)load("glVertexAttribP4uiv");
- glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC)load("glVertexP2ui");
- glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)load("glVertexP2uiv");
- glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC)load("glVertexP3ui");
- glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)load("glVertexP3uiv");
- glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC)load("glVertexP4ui");
- glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)load("glVertexP4uiv");
- glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)load("glTexCoordP1ui");
- glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)load("glTexCoordP1uiv");
- glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)load("glTexCoordP2ui");
- glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)load("glTexCoordP2uiv");
- glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)load("glTexCoordP3ui");
- glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)load("glTexCoordP3uiv");
- glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)load("glTexCoordP4ui");
- glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)load("glTexCoordP4uiv");
- glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)load("glMultiTexCoordP1ui");
- glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)load("glMultiTexCoordP1uiv");
- glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)load("glMultiTexCoordP2ui");
- glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)load("glMultiTexCoordP2uiv");
- glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)load("glMultiTexCoordP3ui");
- glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)load("glMultiTexCoordP3uiv");
- glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)load("glMultiTexCoordP4ui");
- glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)load("glMultiTexCoordP4uiv");
- glad_glNormalP3ui = (PFNGLNORMALP3UIPROC)load("glNormalP3ui");
- glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC)load("glNormalP3uiv");
- glad_glColorP3ui = (PFNGLCOLORP3UIPROC)load("glColorP3ui");
- glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC)load("glColorP3uiv");
- glad_glColorP4ui = (PFNGLCOLORP4UIPROC)load("glColorP4ui");
- glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC)load("glColorP4uiv");
- glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)load("glSecondaryColorP3ui");
- glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)load("glSecondaryColorP3uiv");
-}
-static void load_GL_ARB_debug_output(GLADloadproc load) {
- if(!GLAD_GL_ARB_debug_output) return;
- glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC)load("glDebugMessageControlARB");
- glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC)load("glDebugMessageInsertARB");
- glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)load("glDebugMessageCallbackARB");
- glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)load("glGetDebugMessageLogARB");
-}
-static void load_GL_ARB_framebuffer_object(GLADloadproc load) {
- if(!GLAD_GL_ARB_framebuffer_object) return;
- glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer");
- glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer");
- glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers");
- glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers");
- glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage");
- glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv");
- glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer");
- glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer");
- glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers");
- glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers");
- glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus");
- glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)load("glFramebufferTexture1D");
- glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D");
- glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)load("glFramebufferTexture3D");
- glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer");
- glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv");
- glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap");
- glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer");
- glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample");
- glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer");
-}
-static void load_GL_EXT_framebuffer_blit(GLADloadproc load) {
- if(!GLAD_GL_EXT_framebuffer_blit) return;
- glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)load("glBlitFramebufferEXT");
-}
-static void load_GL_EXT_framebuffer_multisample(GLADloadproc load) {
- if(!GLAD_GL_EXT_framebuffer_multisample) return;
- glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)load("glRenderbufferStorageMultisampleEXT");
-}
-static void load_GL_EXT_framebuffer_object(GLADloadproc load) {
- if(!GLAD_GL_EXT_framebuffer_object) return;
- glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)load("glIsRenderbufferEXT");
- glad_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)load("glBindRenderbufferEXT");
- glad_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)load("glDeleteRenderbuffersEXT");
- glad_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)load("glGenRenderbuffersEXT");
- glad_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)load("glRenderbufferStorageEXT");
- glad_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)load("glGetRenderbufferParameterivEXT");
- glad_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)load("glIsFramebufferEXT");
- glad_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)load("glBindFramebufferEXT");
- glad_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)load("glDeleteFramebuffersEXT");
- glad_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)load("glGenFramebuffersEXT");
- glad_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)load("glCheckFramebufferStatusEXT");
- glad_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)load("glFramebufferTexture1DEXT");
- glad_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)load("glFramebufferTexture2DEXT");
- glad_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)load("glFramebufferTexture3DEXT");
- glad_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)load("glFramebufferRenderbufferEXT");
- glad_glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)load("glGetFramebufferAttachmentParameterivEXT");
- glad_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)load("glGenerateMipmapEXT");
-}
-static void load_GL_OVR_multiview(GLADloadproc load) {
- if(!GLAD_GL_OVR_multiview) return;
- glad_glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)load("glFramebufferTextureMultiviewOVR");
-}
-static int find_extensionsGL(void) {
- if (!get_exts()) return 0;
- GLAD_GL_ARB_debug_output = has_ext("GL_ARB_debug_output");
- GLAD_GL_ARB_framebuffer_object = has_ext("GL_ARB_framebuffer_object");
- GLAD_GL_EXT_framebuffer_blit = has_ext("GL_EXT_framebuffer_blit");
- GLAD_GL_EXT_framebuffer_multisample = has_ext("GL_EXT_framebuffer_multisample");
- GLAD_GL_EXT_framebuffer_object = has_ext("GL_EXT_framebuffer_object");
- GLAD_GL_OVR_multiview = has_ext("GL_OVR_multiview");
- GLAD_GL_OVR_multiview2 = has_ext("GL_OVR_multiview2");
- free_exts();
- return 1;
-}
-
-static void find_coreGL(void) {
-
- /* Thank you @elmindreda
- * https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176
- * https://github.com/glfw/glfw/blob/master/src/context.c#L36
- */
- int i, major, minor;
-
- const char* version;
- const char* prefixes[] = {
- "OpenGL ES-CM ",
- "OpenGL ES-CL ",
- "OpenGL ES ",
- NULL
- };
-
- version = (const char*) glGetString(GL_VERSION);
- if (!version) return;
-
- for (i = 0; prefixes[i]; i++) {
- const size_t length = strlen(prefixes[i]);
- if (strncmp(version, prefixes[i], length) == 0) {
- version += length;
- break;
- }
- }
-
-/* PR #18 */
-#ifdef _MSC_VER
- sscanf_s(version, "%d.%d", &major, &minor);
-#else
- sscanf(version, "%d.%d", &major, &minor);
-#endif
-
- GLVersion.major = major; GLVersion.minor = minor;
- max_loaded_major = major; max_loaded_minor = minor;
- GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
- GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
- GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
- GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
- GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
- GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
- GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
- GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
- GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
- GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
- GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
- GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
- if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 3)) {
- max_loaded_major = 3;
- max_loaded_minor = 3;
- }
-}
-
-int gladLoadGLLoader(GLADloadproc load) {
- GLVersion.major = 0; GLVersion.minor = 0;
- glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
- if(glGetString == NULL) return 0;
- if(glGetString(GL_VERSION) == NULL) return 0;
- find_coreGL();
- load_GL_VERSION_1_0(load);
- load_GL_VERSION_1_1(load);
- load_GL_VERSION_1_2(load);
- load_GL_VERSION_1_3(load);
- load_GL_VERSION_1_4(load);
- load_GL_VERSION_1_5(load);
- load_GL_VERSION_2_0(load);
- load_GL_VERSION_2_1(load);
- load_GL_VERSION_3_0(load);
- load_GL_VERSION_3_1(load);
- load_GL_VERSION_3_2(load);
- load_GL_VERSION_3_3(load);
-
- if (!find_extensionsGL()) return 0;
- load_GL_ARB_debug_output(load);
- load_GL_ARB_framebuffer_object(load);
- load_GL_EXT_framebuffer_blit(load);
- load_GL_EXT_framebuffer_multisample(load);
- load_GL_EXT_framebuffer_object(load);
- load_GL_OVR_multiview(load);
- return GLVersion.major != 0 || GLVersion.minor != 0;
-}
-
diff --git a/thirdparty/glad/glad/gl.h b/thirdparty/glad/glad/gl.h
new file mode 100644
index 0000000000..9836296226
--- /dev/null
+++ b/thirdparty/glad/glad/gl.h
@@ -0,0 +1,3884 @@
+/**
+ * Loader generated by glad 2.0.2 on Mon Nov 7 12:17:15 2022
+ *
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ *
+ * Generator: C/C++
+ * Specification: gl
+ * Extensions: 7
+ *
+ * APIs:
+ * - gl:compatibility=3.3
+ *
+ * Options:
+ * - ALIAS = False
+ * - DEBUG = False
+ * - HEADER_ONLY = False
+ * - LOADER = True
+ * - MX = False
+ * - ON_DEMAND = False
+ *
+ * Commandline:
+ * --api='gl:compatibility=3.3' --extensions='GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_OVR_multiview,GL_OVR_multiview2' c --loader
+ *
+ * Online:
+ * http://glad.sh/#api=gl%3Acompatibility%3D3.3&extensions=GL_ARB_debug_output%2CGL_ARB_framebuffer_object%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_multisample%2CGL_EXT_framebuffer_object%2CGL_OVR_multiview%2CGL_OVR_multiview2&generator=c&options=LOADER
+ *
+ */
+
+#ifndef GLAD_GL_H_
+#define GLAD_GL_H_
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreserved-id-macro"
+#endif
+#ifdef __gl_h_
+ #error OpenGL (gl.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl_h_ 1
+#ifdef __gl3_h_
+ #error OpenGL (gl3.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl3_h_ 1
+#ifdef __glext_h_
+ #error OpenGL (glext.h) header already included (API: gl), remove previous include!
+#endif
+#define __glext_h_ 1
+#ifdef __gl3ext_h_
+ #error OpenGL (gl3ext.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl3ext_h_ 1
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#define GLAD_GL
+#define GLAD_OPTION_GL_LOADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+ #define GLAD_PLATFORM_WIN32 1
+ #else
+ #define GLAD_PLATFORM_WIN32 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+ #ifdef __APPLE__
+ #define GLAD_PLATFORM_APPLE 1
+ #else
+ #define GLAD_PLATFORM_APPLE 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+ #ifdef __EMSCRIPTEN__
+ #define GLAD_PLATFORM_EMSCRIPTEN 1
+ #else
+ #define GLAD_PLATFORM_EMSCRIPTEN 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+ #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+ #ifdef __has_include
+ #if __has_include(<winapifamily.h>)
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #endif
+
+ #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+ #include <winapifamily.h>
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define GLAD_PLATFORM_UWP 1
+ #endif
+ #endif
+
+ #ifndef GLAD_PLATFORM_UWP
+ #define GLAD_PLATFORM_UWP 0
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define GLAD_GNUC_EXTENSION __extension__
+#else
+ #define GLAD_GNUC_EXTENSION
+#endif
+
+#define GLAD_UNUSED(x) (void)(x)
+
+#ifndef GLAD_API_CALL
+ #if defined(GLAD_API_CALL_EXPORT)
+ #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+ #if defined(GLAD_API_CALL_EXPORT_BUILD)
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllexport) extern
+ #endif
+ #else
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllimport) extern
+ #endif
+ #endif
+ #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+ #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+#endif
+
+#ifdef APIENTRY
+ #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+ #define GLAD_API_PTR __stdcall
+#else
+ #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.2"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GL_2D 0x0600
+#define GL_2_BYTES 0x1407
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_3_BYTES 0x1408
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_4_BYTES 0x1409
+#define GL_ACCUM 0x0100
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ADD 0x0104
+#define GL_ADD_SIGNED 0x8574
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_ALPHA 0x1906
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_ALPHA_BITS 0x0D55
+#define GL_ALPHA_INTEGER 0x8D97
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_ALWAYS 0x0207
+#define GL_AMBIENT 0x1200
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_AND 0x1501
+#define GL_AND_INVERTED 0x1504
+#define GL_AND_REVERSE 0x1502
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_BACK 0x0405
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BITMAP 0x1A00
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLUE 0x1905
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_BLUE_BITS 0x0D54
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BYTE 0x1400
+#define GL_C3F_V3F 0x2A24
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_CCW 0x0901
+#define GL_CLAMP 0x2900
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLEAR 0x1500
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_COEFF 0x0A00
+#define GL_COLOR 0x1800
+#define GL_COLOR_ARRAY 0x8076
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_INDEX 0x1900
+#define GL_COLOR_INDEXES 0x1603
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_SUM 0x8458
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG 0x8226
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_CONSTANT 0x8576
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_COORD_REPLACE 0x8862
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CURRENT_BIT 0x00000001
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_CW 0x0900
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DECAL 0x2101
+#define GL_DECR 0x1E03
+#define GL_DECR_WRAP 0x8508
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DEPTH 0x1801
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_DEPTH_BITS 0x0D56
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DIFFUSE 0x1201
+#define GL_DITHER 0x0BD0
+#define GL_DOMAIN 0x0A02
+#define GL_DONT_CARE 0x1100
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_EDGE_FLAG 0x0B43
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_EMISSION 0x1600
+#define GL_ENABLE_BIT 0x00002000
+#define GL_EQUAL 0x0202
+#define GL_EQUIV 0x1509
+#define GL_EVAL_BIT 0x00010000
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+#define GL_EXTENSIONS 0x1F03
+#define GL_EYE_LINEAR 0x2400
+#define GL_EYE_PLANE 0x2502
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FEEDBACK 0x1C01
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_FILL 0x1B02
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_FIXED_ONLY 0x891D
+#define GL_FLAT 0x1D00
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FOG 0x0B60
+#define GL_FOG_BIT 0x00000080
+#define GL_FOG_COLOR 0x0B66
+#define GL_FOG_COORD 0x8451
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_END 0x0B64
+#define GL_FOG_HINT 0x0C54
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_START 0x0B63
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEQUAL 0x0206
+#define GL_GREATER 0x0204
+#define GL_GREEN 0x1904
+#define GL_GREEN_BIAS 0x0D19
+#define GL_GREEN_BITS 0x0D53
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_GREEN_SCALE 0x0D18
+#define GL_HALF_FLOAT 0x140B
+#define GL_HINT_BIT 0x00008000
+#define GL_INCR 0x1E02
+#define GL_INCR_WRAP 0x8507
+#define GL_INDEX 0x8222
+#define GL_INDEX_ARRAY 0x8077
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_BITS 0x0D51
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_INDEX_MODE 0x0C30
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INT 0x1404
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_INTERPOLATE 0x8575
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_INVALID_INDEX 0xFFFFFFFF
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_KEEP 0x1E00
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_LEFT 0x0406
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LINE 0x1B01
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINES 0x0001
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_BIT 0x00000004
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_LINE_TOKEN 0x0702
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINK_STATUS 0x8B82
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_BIT 0x00020000
+#define GL_LIST_INDEX 0x0B33
+#define GL_LIST_MODE 0x0B30
+#define GL_LOAD 0x0101
+#define GL_LOGIC_OP 0x0BF1
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_STENCIL 0x0D11
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_MAX 0x8008
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_VIEWS_OVR 0x9631
+#define GL_MIN 0x8007
+#define GL_MINOR_VERSION 0x821C
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MODELVIEW 0x1700
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_MODULATE 0x2100
+#define GL_MULT 0x0103
+#define GL_MULTISAMPLE 0x809D
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_N3F_V3F 0x2A25
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_NAND 0x150E
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOOP 0x1505
+#define GL_NOR 0x1508
+#define GL_NORMALIZE 0x0BA1
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_MAP 0x8511
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_OBJECT_PLANE 0x2501
+#define GL_OBJECT_TYPE 0x9112
+#define GL_ONE 1
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OR 0x1507
+#define GL_ORDER 0x0A01
+#define GL_OR_INVERTED 0x150D
+#define GL_OR_REVERSE 0x150B
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_POINT 0x1B00
+#define GL_POINTS 0x0000
+#define GL_POINT_BIT 0x00000002
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_POINT_SPRITE 0x8861
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_POINT_TOKEN 0x0701
+#define GL_POLYGON 0x0009
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_POSITION 0x1203
+#define GL_PREVIOUS 0x8578
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_PROJECTION 0x1701
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_Q 0x2003
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_QUADS 0x0007
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_QUAD_STRIP 0x0008
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_QUERY_WAIT 0x8E13
+#define GL_R 0x2002
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_R16 0x822A
+#define GL_R16F 0x822D
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R16_SNORM 0x8F98
+#define GL_R32F 0x822E
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_R3_G3_B2 0x2A10
+#define GL_R8 0x8229
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R8_SNORM 0x8F94
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_READ_BUFFER 0x0C02
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_READ_ONLY 0x88B8
+#define GL_READ_WRITE 0x88BA
+#define GL_RED 0x1903
+#define GL_RED_BIAS 0x0D15
+#define GL_RED_BITS 0x0D52
+#define GL_RED_INTEGER 0x8D94
+#define GL_RED_SCALE 0x0D14
+#define GL_REFLECTION_MAP 0x8512
+#define GL_RENDER 0x1C00
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERER 0x1F01
+#define GL_RENDER_MODE 0x0C40
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_RETURN 0x0102
+#define GL_RG 0x8227
+#define GL_RG16 0x822C
+#define GL_RG16F 0x822F
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG32F 0x8230
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_RG8 0x822B
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB 0x1907
+#define GL_RGB10 0x8052
+#define GL_RGB10_A2 0x8059
+#define GL_RGB10_A2UI 0x906F
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGB16F 0x881B
+#define GL_RGB16I 0x8D89
+#define GL_RGB16UI 0x8D77
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGB32F 0x8815
+#define GL_RGB32I 0x8D83
+#define GL_RGB32UI 0x8D71
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB5_A1 0x8057
+#define GL_RGB8 0x8051
+#define GL_RGB8I 0x8D8F
+#define GL_RGB8UI 0x8D7D
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGB9_E5 0x8C3D
+#define GL_RGBA 0x1908
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16I 0x8D88
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA2 0x8055
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32I 0x8D82
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA4 0x8056
+#define GL_RGBA8 0x8058
+#define GL_RGBA8I 0x8D8E
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_RGBA_MODE 0x0C31
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGB_SCALE 0x8573
+#define GL_RG_INTEGER 0x8228
+#define GL_RIGHT 0x0407
+#define GL_S 0x2000
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SELECT 0x1C02
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_SET 0x150F
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADE_MODEL 0x0B54
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_SHININESS 0x1601
+#define GL_SHORT 0x1402
+#define GL_SIGNALED 0x9119
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SMOOTH 0x1D01
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SPECULAR 0x1202
+#define GL_SPHERE_MAP 0x2402
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_ALPHA 0x8589
+#define GL_SRC1_COLOR 0x88F9
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_ALPHA 0x858A
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_STATIC_COPY 0x88E6
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_STENCIL_BITS 0x0D57
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STEREO 0x0C33
+#define GL_STREAM_COPY 0x88E2
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_SUBTRACT 0x84E7
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_SYNC_STATUS 0x9114
+#define GL_T 0x2001
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+#define GL_T4F_V4F 0x2A28
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_ENV 0x2300
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+#define GL_TIMESTAMP 0x8E28
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_TRUE 1
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNSIGNALED 0x9118
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_VIEWPORT 0x0BA2
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_WAIT_FAILED 0x911D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_WRITE_ONLY 0x88B9
+#define GL_XOR 0x1506
+#define GL_ZERO 0
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+
+
+#include <KHR/khrplatform.h>
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptr;
+#else
+typedef khronos_intptr_t GLintptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptrARB;
+#else
+typedef khronos_intptr_t GLintptrARB;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptr;
+#else
+typedef khronos_ssize_t GLsizeiptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptrARB;
+#else
+typedef khronos_ssize_t GLsizeiptrARB;
+#endif
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void);
+
+
+#define GL_VERSION_1_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_0;
+#define GL_VERSION_1_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_1;
+#define GL_VERSION_1_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_2;
+#define GL_VERSION_1_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_3;
+#define GL_VERSION_1_4 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_4;
+#define GL_VERSION_1_5 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_5;
+#define GL_VERSION_2_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_0;
+#define GL_VERSION_2_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_1;
+#define GL_VERSION_3_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_0;
+#define GL_VERSION_3_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_1;
+#define GL_VERSION_3_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_2;
+#define GL_VERSION_3_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_3;
+#define GL_ARB_debug_output 1
+GLAD_API_CALL int GLAD_GL_ARB_debug_output;
+#define GL_ARB_framebuffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_framebuffer_object;
+#define GL_EXT_framebuffer_blit 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_blit;
+#define GL_EXT_framebuffer_multisample 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_multisample;
+#define GL_EXT_framebuffer_object 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_object;
+#define GL_OVR_multiview 1
+GLAD_API_CALL int GLAD_GL_OVR_multiview;
+#define GL_OVR_multiview2 1
+GLAD_API_CALL int GLAD_GL_OVR_multiview2;
+
+
+typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum op, GLfloat value);
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture);
+typedef void (GLAD_API_PTR *PFNGLALPHAFUNCPROC)(GLenum func, GLfloat ref);
+typedef GLboolean (GLAD_API_PTR *PFNGLARETEXTURESRESIDENTPROC)(GLsizei n, const GLuint * textures, GLboolean * residences);
+typedef void (GLAD_API_PTR *PFNGLARRAYELEMENTPROC)(GLint i);
+typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLBEGINPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLBITMAPPROC)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCALLLISTPROC)(GLuint list);
+typedef void (GLAD_API_PTR *PFNGLCALLLISTSPROC)(GLsizei n, GLenum type, const void * lists);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
+typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLCLEARACCUMPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble depth);
+typedef void (GLAD_API_PTR *PFNGLCLEARINDEXPROC)(GLfloat c);
+typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s);
+typedef void (GLAD_API_PTR *PFNGLCLIENTACTIVETEXTUREPROC)(GLenum texture);
+typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAD_API_PTR *PFNGLCLIPPLANEPROC)(GLenum plane, const GLdouble * equation);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3IPROC)(GLint red, GLint green, GLint blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UBVPROC)(const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UIVPROC)(const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3USVPROC)(const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4BPROC)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4DPROC)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4FPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4IPROC)(GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4SPROC)(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UBPROC)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UBVPROC)(const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UIPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UIVPROC)(const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4USPROC)(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4USVPROC)(const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOLORMATERIALPROC)(GLenum face, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLCOLORP3UIPROC)(GLenum type, GLuint color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint * color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP4UIPROC)(GLenum type, GLuint color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint * color);
+typedef void (GLAD_API_PTR *PFNGLCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLCOPYPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type);
+typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void * userParam);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETELISTSPROC)(GLuint list, GLsizei range);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync sync);
+typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func);
+typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f);
+typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEPROC)(GLenum array);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum buf);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWPIXELSPROC)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPOINTERPROC)(GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGVPROC)(const GLboolean * flag);
+typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEPROC)(GLenum array);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENDPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDLISTPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DPROC)(GLdouble u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DVPROC)(const GLdouble * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FPROC)(GLfloat u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FVPROC)(const GLfloat * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DPROC)(GLdouble u, GLdouble v);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DVPROC)(const GLdouble * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FPROC)(GLfloat u, GLfloat v);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FVPROC)(const GLfloat * u);
+typedef void (GLAD_API_PTR *PFNGLEVALMESH1PROC)(GLenum mode, GLint i1, GLint i2);
+typedef void (GLAD_API_PTR *PFNGLEVALMESH2PROC)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+typedef void (GLAD_API_PTR *PFNGLEVALPOINT1PROC)(GLint i);
+typedef void (GLAD_API_PTR *PFNGLEVALPOINT2PROC)(GLint i, GLint j);
+typedef void (GLAD_API_PTR *PFNGLFEEDBACKBUFFERPROC)(GLsizei size, GLenum type, GLfloat * buffer);
+typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDPROC)(GLdouble coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDVPROC)(const GLdouble * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFPROC)(GLfloat coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFVPROC)(const GLfloat * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLFOGFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLFOGIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLFOGIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLFRUSTUMPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint * framebuffers);
+typedef GLuint (GLAD_API_PTR *PFNGLGENLISTSPROC)(GLsizei range);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPEXTPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void * data);
+typedef void (GLAD_API_PTR *PFNGLGETCLIPPLANEPROC)(GLenum plane, GLdouble * equation);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void * img);
+typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog);
+typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble * data);
+typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETLIGHTFVPROC)(GLenum light, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETLIGHTIVPROC)(GLenum light, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETMAPDVPROC)(GLenum target, GLenum query, GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLGETMAPFVPROC)(GLenum target, GLenum query, GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLGETMAPIVPROC)(GLenum target, GLenum query, GLint * v);
+typedef void (GLAD_API_PTR *PFNGLGETMATERIALFVPROC)(GLenum face, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETMATERIALIVPROC)(GLenum face, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPFVPROC)(GLenum map, GLfloat * values);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUIVPROC)(GLenum map, GLuint * values);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUSVPROC)(GLenum map, GLushort * values);
+typedef void (GLAD_API_PTR *PFNGLGETPOINTERVPROC)(GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte * mask);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values);
+typedef void (GLAD_API_PTR *PFNGLGETTEXENVFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXENVIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENDVPROC)(GLenum coord, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENFVPROC)(GLenum coord, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENIVPROC)(GLenum coord, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name);
+typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLINDEXMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLINDEXPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLINDEXDPROC)(GLdouble c);
+typedef void (GLAD_API_PTR *PFNGLINDEXDVPROC)(const GLdouble * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXFPROC)(GLfloat c);
+typedef void (GLAD_API_PTR *PFNGLINDEXFVPROC)(const GLfloat * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXIPROC)(GLint c);
+typedef void (GLAD_API_PTR *PFNGLINDEXIVPROC)(const GLint * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXSPROC)(GLshort c);
+typedef void (GLAD_API_PTR *PFNGLINDEXSVPROC)(const GLshort * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXUBPROC)(GLubyte c);
+typedef void (GLAD_API_PTR *PFNGLINDEXUBVPROC)(const GLubyte * c);
+typedef void (GLAD_API_PTR *PFNGLINITNAMESPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLINTERLEAVEDARRAYSPROC)(GLenum format, GLsizei stride, const void * pointer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISLISTPROC)(GLuint list);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint sampler);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync sync);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture);
+typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTFPROC)(GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTFVPROC)(GLenum light, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTIPROC)(GLenum light, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTIVPROC)(GLenum light, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLLINESTIPPLEPROC)(GLint factor, GLushort pattern);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLLISTBASEPROC)(GLuint base);
+typedef void (GLAD_API_PTR *PFNGLLOADIDENTITYPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLLOADMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLLOADMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLLOADNAMEPROC)(GLuint name);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum opcode);
+typedef void (GLAD_API_PTR *PFNGLMAP1DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble * points);
+typedef void (GLAD_API_PTR *PFNGLMAP1FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points);
+typedef void (GLAD_API_PTR *PFNGLMAP2DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble * points);
+typedef void (GLAD_API_PTR *PFNGLMAP2FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat * points);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID1DPROC)(GLint un, GLdouble u1, GLdouble u2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID1FPROC)(GLint un, GLfloat u1, GLfloat u2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID2DPROC)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID2FPROC)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLMATERIALFPROC)(GLenum face, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLMATERIALFVPROC)(GLenum face, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLMATERIALIPROC)(GLenum face, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLMATERIALIVPROC)(GLenum face, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLMATRIXMODEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLMULTMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLMULTMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXDPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXFPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DPROC)(GLenum target, GLdouble s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FPROC)(GLenum target, GLfloat s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IPROC)(GLenum target, GLint s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SPROC)(GLenum target, GLshort s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DPROC)(GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FPROC)(GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IPROC)(GLenum target, GLint s, GLint t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SPROC)(GLenum target, GLshort s, GLshort t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IPROC)(GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SPROC)(GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DVPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FVPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IVPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SVPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLNEWLISTPROC)(GLuint list, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3BPROC)(GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3DPROC)(GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3FPROC)(GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3IPROC)(GLint nx, GLint ny, GLint nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3SPROC)(GLshort nx, GLshort ny, GLshort nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLNORMALPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLORTHOPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (GLAD_API_PTR *PFNGLPASSTHROUGHPROC)(GLfloat token);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPFVPROC)(GLenum map, GLsizei mapsize, const GLfloat * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPUIVPROC)(GLenum map, GLsizei mapsize, const GLuint * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPUSVPROC)(GLenum map, GLsizei mapsize, const GLushort * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPIXELZOOMPROC)(GLfloat xfactor, GLfloat yfactor);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat size);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONSTIPPLEPROC)(const GLubyte * mask);
+typedef void (GLAD_API_PTR *PFNGLPOPATTRIBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPCLIENTATTRIBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPMATRIXPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPNAMEPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLPRIORITIZETEXTURESPROC)(GLsizei n, const GLuint * textures, const GLfloat * priorities);
+typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLPUSHATTRIBPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLPUSHMATRIXPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPUSHNAMEPROC)(GLuint name);
+typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DPROC)(GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FPROC)(GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IPROC)(GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SPROC)(GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IPROC)(GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SPROC)(GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IPROC)(GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum src);
+typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLRECTDPROC)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+typedef void (GLAD_API_PTR *PFNGLRECTDVPROC)(const GLdouble * v1, const GLdouble * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTFPROC)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+typedef void (GLAD_API_PTR *PFNGLRECTFVPROC)(const GLfloat * v1, const GLfloat * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTIPROC)(GLint x1, GLint y1, GLint x2, GLint y2);
+typedef void (GLAD_API_PTR *PFNGLRECTIVPROC)(const GLint * v1, const GLint * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTSPROC)(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+typedef void (GLAD_API_PTR *PFNGLRECTSVPROC)(const GLshort * v1, const GLshort * v2);
+typedef GLint (GLAD_API_PTR *PFNGLRENDERMODEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLROTATEDPROC)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLROTATEFPROC)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSCALEDPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLSCALEFPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BVPROC)(const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IPROC)(GLint red, GLint green, GLint blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBVPROC)(const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIVPROC)(const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USVPROC)(const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint * color);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLSELECTBUFFERPROC)(GLsizei size, GLuint * buffer);
+typedef void (GLAD_API_PTR *PFNGLSHADEMODELPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DPROC)(GLdouble s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FPROC)(GLfloat s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IPROC)(GLint s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SPROC)(GLshort s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DPROC)(GLdouble s, GLdouble t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FPROC)(GLfloat s, GLfloat t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IPROC)(GLint s, GLint t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SPROC)(GLshort s, GLshort t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DPROC)(GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FPROC)(GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IPROC)(GLint s, GLint t, GLint r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SPROC)(GLshort s, GLshort t, GLshort r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DPROC)(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FPROC)(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IPROC)(GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SPROC)(GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLTEXENVFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXENVFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXENVIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXENVIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENDPROC)(GLenum coord, GLenum pname, GLdouble param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENDVPROC)(GLenum coord, GLenum pname, const GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENFPROC)(GLenum coord, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENFVPROC)(GLenum coord, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENIPROC)(GLenum coord, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENIVPROC)(GLenum coord, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode);
+typedef void (GLAD_API_PTR *PFNGLTRANSLATEDPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLTRANSLATEFPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2DPROC)(GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2FPROC)(GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2IPROC)(GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2SPROC)(GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3IPROC)(GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3SPROC)(GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4IPROC)(GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DPROC)(GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FPROC)(GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IPROC)(GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SPROC)(GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SVPROC)(const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DVPROC)(const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FVPROC)(const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IPROC)(GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IVPROC)(const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SPROC)(GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SVPROC)(const GLshort * v);
+
+GLAD_API_CALL PFNGLACCUMPROC glad_glAccum;
+#define glAccum glad_glAccum
+GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+GLAD_API_CALL PFNGLALPHAFUNCPROC glad_glAlphaFunc;
+#define glAlphaFunc glad_glAlphaFunc
+GLAD_API_CALL PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
+#define glAreTexturesResident glad_glAreTexturesResident
+GLAD_API_CALL PFNGLARRAYELEMENTPROC glad_glArrayElement;
+#define glArrayElement glad_glArrayElement
+GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+GLAD_API_CALL PFNGLBEGINPROC glad_glBegin;
+#define glBegin glad_glBegin
+GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
+#define glBeginConditionalRender glad_glBeginConditionalRender
+GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery;
+#define glBeginQuery glad_glBeginQuery
+GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
+#define glBeginTransformFeedback glad_glBeginTransformFeedback
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
+#define glBindBufferBase glad_glBindBufferBase
+GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
+#define glBindBufferRange glad_glBindBufferRange
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
+#define glBindFragDataLocation glad_glBindFragDataLocation
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
+#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
+GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+GLAD_API_CALL PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT;
+#define glBindFramebufferEXT glad_glBindFramebufferEXT
+GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+GLAD_API_CALL PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT;
+#define glBindRenderbufferEXT glad_glBindRenderbufferEXT
+GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler;
+#define glBindSampler glad_glBindSampler
+GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
+#define glBindVertexArray glad_glBindVertexArray
+GLAD_API_CALL PFNGLBITMAPPROC glad_glBitmap;
+#define glBitmap glad_glBitmap
+GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
+#define glBlitFramebuffer glad_glBlitFramebuffer
+GLAD_API_CALL PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT;
+#define glBlitFramebufferEXT glad_glBlitFramebufferEXT
+GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+GLAD_API_CALL PFNGLCALLLISTPROC glad_glCallList;
+#define glCallList glad_glCallList
+GLAD_API_CALL PFNGLCALLLISTSPROC glad_glCallLists;
+#define glCallLists glad_glCallLists
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT;
+#define glCheckFramebufferStatusEXT glad_glCheckFramebufferStatusEXT
+GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor;
+#define glClampColor glad_glClampColor
+GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+GLAD_API_CALL PFNGLCLEARACCUMPROC glad_glClearAccum;
+#define glClearAccum glad_glClearAccum
+GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
+#define glClearBufferfi glad_glClearBufferfi
+GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
+#define glClearBufferfv glad_glClearBufferfv
+GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
+#define glClearBufferiv glad_glClearBufferiv
+GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
+#define glClearBufferuiv glad_glClearBufferuiv
+GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+GLAD_API_CALL PFNGLCLEARDEPTHPROC glad_glClearDepth;
+#define glClearDepth glad_glClearDepth
+GLAD_API_CALL PFNGLCLEARINDEXPROC glad_glClearIndex;
+#define glClearIndex glad_glClearIndex
+GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+GLAD_API_CALL PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
+#define glClientActiveTexture glad_glClientActiveTexture
+GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
+#define glClientWaitSync glad_glClientWaitSync
+GLAD_API_CALL PFNGLCLIPPLANEPROC glad_glClipPlane;
+#define glClipPlane glad_glClipPlane
+GLAD_API_CALL PFNGLCOLOR3BPROC glad_glColor3b;
+#define glColor3b glad_glColor3b
+GLAD_API_CALL PFNGLCOLOR3BVPROC glad_glColor3bv;
+#define glColor3bv glad_glColor3bv
+GLAD_API_CALL PFNGLCOLOR3DPROC glad_glColor3d;
+#define glColor3d glad_glColor3d
+GLAD_API_CALL PFNGLCOLOR3DVPROC glad_glColor3dv;
+#define glColor3dv glad_glColor3dv
+GLAD_API_CALL PFNGLCOLOR3FPROC glad_glColor3f;
+#define glColor3f glad_glColor3f
+GLAD_API_CALL PFNGLCOLOR3FVPROC glad_glColor3fv;
+#define glColor3fv glad_glColor3fv
+GLAD_API_CALL PFNGLCOLOR3IPROC glad_glColor3i;
+#define glColor3i glad_glColor3i
+GLAD_API_CALL PFNGLCOLOR3IVPROC glad_glColor3iv;
+#define glColor3iv glad_glColor3iv
+GLAD_API_CALL PFNGLCOLOR3SPROC glad_glColor3s;
+#define glColor3s glad_glColor3s
+GLAD_API_CALL PFNGLCOLOR3SVPROC glad_glColor3sv;
+#define glColor3sv glad_glColor3sv
+GLAD_API_CALL PFNGLCOLOR3UBPROC glad_glColor3ub;
+#define glColor3ub glad_glColor3ub
+GLAD_API_CALL PFNGLCOLOR3UBVPROC glad_glColor3ubv;
+#define glColor3ubv glad_glColor3ubv
+GLAD_API_CALL PFNGLCOLOR3UIPROC glad_glColor3ui;
+#define glColor3ui glad_glColor3ui
+GLAD_API_CALL PFNGLCOLOR3UIVPROC glad_glColor3uiv;
+#define glColor3uiv glad_glColor3uiv
+GLAD_API_CALL PFNGLCOLOR3USPROC glad_glColor3us;
+#define glColor3us glad_glColor3us
+GLAD_API_CALL PFNGLCOLOR3USVPROC glad_glColor3usv;
+#define glColor3usv glad_glColor3usv
+GLAD_API_CALL PFNGLCOLOR4BPROC glad_glColor4b;
+#define glColor4b glad_glColor4b
+GLAD_API_CALL PFNGLCOLOR4BVPROC glad_glColor4bv;
+#define glColor4bv glad_glColor4bv
+GLAD_API_CALL PFNGLCOLOR4DPROC glad_glColor4d;
+#define glColor4d glad_glColor4d
+GLAD_API_CALL PFNGLCOLOR4DVPROC glad_glColor4dv;
+#define glColor4dv glad_glColor4dv
+GLAD_API_CALL PFNGLCOLOR4FPROC glad_glColor4f;
+#define glColor4f glad_glColor4f
+GLAD_API_CALL PFNGLCOLOR4FVPROC glad_glColor4fv;
+#define glColor4fv glad_glColor4fv
+GLAD_API_CALL PFNGLCOLOR4IPROC glad_glColor4i;
+#define glColor4i glad_glColor4i
+GLAD_API_CALL PFNGLCOLOR4IVPROC glad_glColor4iv;
+#define glColor4iv glad_glColor4iv
+GLAD_API_CALL PFNGLCOLOR4SPROC glad_glColor4s;
+#define glColor4s glad_glColor4s
+GLAD_API_CALL PFNGLCOLOR4SVPROC glad_glColor4sv;
+#define glColor4sv glad_glColor4sv
+GLAD_API_CALL PFNGLCOLOR4UBPROC glad_glColor4ub;
+#define glColor4ub glad_glColor4ub
+GLAD_API_CALL PFNGLCOLOR4UBVPROC glad_glColor4ubv;
+#define glColor4ubv glad_glColor4ubv
+GLAD_API_CALL PFNGLCOLOR4UIPROC glad_glColor4ui;
+#define glColor4ui glad_glColor4ui
+GLAD_API_CALL PFNGLCOLOR4UIVPROC glad_glColor4uiv;
+#define glColor4uiv glad_glColor4uiv
+GLAD_API_CALL PFNGLCOLOR4USPROC glad_glColor4us;
+#define glColor4us glad_glColor4us
+GLAD_API_CALL PFNGLCOLOR4USVPROC glad_glColor4usv;
+#define glColor4usv glad_glColor4usv
+GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski;
+#define glColorMaski glad_glColorMaski
+GLAD_API_CALL PFNGLCOLORMATERIALPROC glad_glColorMaterial;
+#define glColorMaterial glad_glColorMaterial
+GLAD_API_CALL PFNGLCOLORP3UIPROC glad_glColorP3ui;
+#define glColorP3ui glad_glColorP3ui
+GLAD_API_CALL PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
+#define glColorP3uiv glad_glColorP3uiv
+GLAD_API_CALL PFNGLCOLORP4UIPROC glad_glColorP4ui;
+#define glColorP4ui glad_glColorP4ui
+GLAD_API_CALL PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
+#define glColorP4uiv glad_glColorP4uiv
+GLAD_API_CALL PFNGLCOLORPOINTERPROC glad_glColorPointer;
+#define glColorPointer glad_glColorPointer
+GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
+#define glCompressedTexImage1D glad_glCompressedTexImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
+#define glCompressedTexImage3D glad_glCompressedTexImage3D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
+#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
+#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
+GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
+#define glCopyBufferSubData glad_glCopyBufferSubData
+GLAD_API_CALL PFNGLCOPYPIXELSPROC glad_glCopyPixels;
+#define glCopyPixels glad_glCopyPixels
+GLAD_API_CALL PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
+#define glCopyTexImage1D glad_glCopyTexImage1D
+GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
+#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
+#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
+GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB;
+#define glDebugMessageCallbackARB glad_glDebugMessageCallbackARB
+GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB;
+#define glDebugMessageControlARB glad_glDebugMessageControlARB
+GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB;
+#define glDebugMessageInsertARB glad_glDebugMessageInsertARB
+GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT;
+#define glDeleteFramebuffersEXT glad_glDeleteFramebuffersEXT
+GLAD_API_CALL PFNGLDELETELISTSPROC glad_glDeleteLists;
+#define glDeleteLists glad_glDeleteLists
+GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
+#define glDeleteQueries glad_glDeleteQueries
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT;
+#define glDeleteRenderbuffersEXT glad_glDeleteRenderbuffersEXT
+GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
+#define glDeleteSamplers glad_glDeleteSamplers
+GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync;
+#define glDeleteSync glad_glDeleteSync
+GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
+#define glDeleteVertexArrays glad_glDeleteVertexArrays
+GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+GLAD_API_CALL PFNGLDEPTHRANGEPROC glad_glDepthRange;
+#define glDepthRange glad_glDepthRange
+GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+GLAD_API_CALL PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
+#define glDisableClientState glad_glDisableClientState
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei;
+#define glDisablei glad_glDisablei
+GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
+#define glDrawArraysInstanced glad_glDrawArraysInstanced
+GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
+#define glDrawBuffer glad_glDrawBuffer
+GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
+#define glDrawBuffers glad_glDrawBuffers
+GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
+#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
+#define glDrawElementsInstanced glad_glDrawElementsInstanced
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
+#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
+GLAD_API_CALL PFNGLDRAWPIXELSPROC glad_glDrawPixels;
+#define glDrawPixels glad_glDrawPixels
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
+#define glDrawRangeElements glad_glDrawRangeElements
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
+#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
+GLAD_API_CALL PFNGLEDGEFLAGPROC glad_glEdgeFlag;
+#define glEdgeFlag glad_glEdgeFlag
+GLAD_API_CALL PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
+#define glEdgeFlagPointer glad_glEdgeFlagPointer
+GLAD_API_CALL PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
+#define glEdgeFlagv glad_glEdgeFlagv
+GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+GLAD_API_CALL PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
+#define glEnableClientState glad_glEnableClientState
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei;
+#define glEnablei glad_glEnablei
+GLAD_API_CALL PFNGLENDPROC glad_glEnd;
+#define glEnd glad_glEnd
+GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
+#define glEndConditionalRender glad_glEndConditionalRender
+GLAD_API_CALL PFNGLENDLISTPROC glad_glEndList;
+#define glEndList glad_glEndList
+GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery;
+#define glEndQuery glad_glEndQuery
+GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
+#define glEndTransformFeedback glad_glEndTransformFeedback
+GLAD_API_CALL PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
+#define glEvalCoord1d glad_glEvalCoord1d
+GLAD_API_CALL PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
+#define glEvalCoord1dv glad_glEvalCoord1dv
+GLAD_API_CALL PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
+#define glEvalCoord1f glad_glEvalCoord1f
+GLAD_API_CALL PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
+#define glEvalCoord1fv glad_glEvalCoord1fv
+GLAD_API_CALL PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
+#define glEvalCoord2d glad_glEvalCoord2d
+GLAD_API_CALL PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
+#define glEvalCoord2dv glad_glEvalCoord2dv
+GLAD_API_CALL PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
+#define glEvalCoord2f glad_glEvalCoord2f
+GLAD_API_CALL PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
+#define glEvalCoord2fv glad_glEvalCoord2fv
+GLAD_API_CALL PFNGLEVALMESH1PROC glad_glEvalMesh1;
+#define glEvalMesh1 glad_glEvalMesh1
+GLAD_API_CALL PFNGLEVALMESH2PROC glad_glEvalMesh2;
+#define glEvalMesh2 glad_glEvalMesh2
+GLAD_API_CALL PFNGLEVALPOINT1PROC glad_glEvalPoint1;
+#define glEvalPoint1 glad_glEvalPoint1
+GLAD_API_CALL PFNGLEVALPOINT2PROC glad_glEvalPoint2;
+#define glEvalPoint2 glad_glEvalPoint2
+GLAD_API_CALL PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
+#define glFeedbackBuffer glad_glFeedbackBuffer
+GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync;
+#define glFenceSync glad_glFenceSync
+GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
+#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
+GLAD_API_CALL PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
+#define glFogCoordPointer glad_glFogCoordPointer
+GLAD_API_CALL PFNGLFOGCOORDDPROC glad_glFogCoordd;
+#define glFogCoordd glad_glFogCoordd
+GLAD_API_CALL PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
+#define glFogCoorddv glad_glFogCoorddv
+GLAD_API_CALL PFNGLFOGCOORDFPROC glad_glFogCoordf;
+#define glFogCoordf glad_glFogCoordf
+GLAD_API_CALL PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
+#define glFogCoordfv glad_glFogCoordfv
+GLAD_API_CALL PFNGLFOGFPROC glad_glFogf;
+#define glFogf glad_glFogf
+GLAD_API_CALL PFNGLFOGFVPROC glad_glFogfv;
+#define glFogfv glad_glFogfv
+GLAD_API_CALL PFNGLFOGIPROC glad_glFogi;
+#define glFogi glad_glFogi
+GLAD_API_CALL PFNGLFOGIVPROC glad_glFogiv;
+#define glFogiv glad_glFogiv
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT;
+#define glFramebufferRenderbufferEXT glad_glFramebufferRenderbufferEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
+#define glFramebufferTexture glad_glFramebufferTexture
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
+#define glFramebufferTexture1D glad_glFramebufferTexture1D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT;
+#define glFramebufferTexture1DEXT glad_glFramebufferTexture1DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT;
+#define glFramebufferTexture2DEXT glad_glFramebufferTexture2DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
+#define glFramebufferTexture3D glad_glFramebufferTexture3D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT;
+#define glFramebufferTexture3DEXT glad_glFramebufferTexture3DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
+#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR;
+#define glFramebufferTextureMultiviewOVR glad_glFramebufferTextureMultiviewOVR
+GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+GLAD_API_CALL PFNGLFRUSTUMPROC glad_glFrustum;
+#define glFrustum glad_glFrustum
+GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT;
+#define glGenFramebuffersEXT glad_glGenFramebuffersEXT
+GLAD_API_CALL PFNGLGENLISTSPROC glad_glGenLists;
+#define glGenLists glad_glGenLists
+GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries;
+#define glGenQueries glad_glGenQueries
+GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+GLAD_API_CALL PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT;
+#define glGenRenderbuffersEXT glad_glGenRenderbuffersEXT
+GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers;
+#define glGenSamplers glad_glGenSamplers
+GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
+#define glGenVertexArrays glad_glGenVertexArrays
+GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+GLAD_API_CALL PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT;
+#define glGenerateMipmapEXT glad_glGenerateMipmapEXT
+GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
+#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
+#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
+#define glGetActiveUniformName glad_glGetActiveUniformName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
+#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
+GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
+#define glGetBooleani_v glad_glGetBooleani_v
+GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
+#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
+#define glGetBufferPointerv glad_glGetBufferPointerv
+GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
+#define glGetBufferSubData glad_glGetBufferSubData
+GLAD_API_CALL PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
+#define glGetClipPlane glad_glGetClipPlane
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
+#define glGetCompressedTexImage glad_glGetCompressedTexImage
+GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
+#define glGetDebugMessageLogARB glad_glGetDebugMessageLogARB
+GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev;
+#define glGetDoublev glad_glGetDoublev
+GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+GLAD_API_CALL PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
+#define glGetFragDataIndex glad_glGetFragDataIndex
+GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
+#define glGetFragDataLocation glad_glGetFragDataLocation
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT;
+#define glGetFramebufferAttachmentParameterivEXT glad_glGetFramebufferAttachmentParameterivEXT
+GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
+#define glGetInteger64i_v glad_glGetInteger64i_v
+GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
+#define glGetInteger64v glad_glGetInteger64v
+GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
+#define glGetIntegeri_v glad_glGetIntegeri_v
+GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+GLAD_API_CALL PFNGLGETLIGHTFVPROC glad_glGetLightfv;
+#define glGetLightfv glad_glGetLightfv
+GLAD_API_CALL PFNGLGETLIGHTIVPROC glad_glGetLightiv;
+#define glGetLightiv glad_glGetLightiv
+GLAD_API_CALL PFNGLGETMAPDVPROC glad_glGetMapdv;
+#define glGetMapdv glad_glGetMapdv
+GLAD_API_CALL PFNGLGETMAPFVPROC glad_glGetMapfv;
+#define glGetMapfv glad_glGetMapfv
+GLAD_API_CALL PFNGLGETMAPIVPROC glad_glGetMapiv;
+#define glGetMapiv glad_glGetMapiv
+GLAD_API_CALL PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
+#define glGetMaterialfv glad_glGetMaterialfv
+GLAD_API_CALL PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
+#define glGetMaterialiv glad_glGetMaterialiv
+GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
+#define glGetMultisamplefv glad_glGetMultisamplefv
+GLAD_API_CALL PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
+#define glGetPixelMapfv glad_glGetPixelMapfv
+GLAD_API_CALL PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
+#define glGetPixelMapuiv glad_glGetPixelMapuiv
+GLAD_API_CALL PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
+#define glGetPixelMapusv glad_glGetPixelMapusv
+GLAD_API_CALL PFNGLGETPOINTERVPROC glad_glGetPointerv;
+#define glGetPointerv glad_glGetPointerv
+GLAD_API_CALL PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
+#define glGetPolygonStipple glad_glGetPolygonStipple
+GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
+#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
+#define glGetQueryObjectiv glad_glGetQueryObjectiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
+#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
+#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
+GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv;
+#define glGetQueryiv glad_glGetQueryiv
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT;
+#define glGetRenderbufferParameterivEXT glad_glGetRenderbufferParameterivEXT
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
+#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
+#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
+#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
+#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
+GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi;
+#define glGetStringi glad_glGetStringi
+GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv;
+#define glGetSynciv glad_glGetSynciv
+GLAD_API_CALL PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
+#define glGetTexEnvfv glad_glGetTexEnvfv
+GLAD_API_CALL PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
+#define glGetTexEnviv glad_glGetTexEnviv
+GLAD_API_CALL PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
+#define glGetTexGendv glad_glGetTexGendv
+GLAD_API_CALL PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
+#define glGetTexGenfv glad_glGetTexGenfv
+GLAD_API_CALL PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
+#define glGetTexGeniv glad_glGetTexGeniv
+GLAD_API_CALL PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
+#define glGetTexImage glad_glGetTexImage
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
+#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
+#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
+#define glGetTexParameterIiv glad_glGetTexParameterIiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
+#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
+#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
+GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
+#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
+GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
+#define glGetUniformIndices glad_glGetUniformIndices
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
+#define glGetUniformuiv glad_glGetUniformuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
+#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
+#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
+#define glGetVertexAttribdv glad_glGetVertexAttribdv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+GLAD_API_CALL PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+GLAD_API_CALL PFNGLINDEXMASKPROC glad_glIndexMask;
+#define glIndexMask glad_glIndexMask
+GLAD_API_CALL PFNGLINDEXPOINTERPROC glad_glIndexPointer;
+#define glIndexPointer glad_glIndexPointer
+GLAD_API_CALL PFNGLINDEXDPROC glad_glIndexd;
+#define glIndexd glad_glIndexd
+GLAD_API_CALL PFNGLINDEXDVPROC glad_glIndexdv;
+#define glIndexdv glad_glIndexdv
+GLAD_API_CALL PFNGLINDEXFPROC glad_glIndexf;
+#define glIndexf glad_glIndexf
+GLAD_API_CALL PFNGLINDEXFVPROC glad_glIndexfv;
+#define glIndexfv glad_glIndexfv
+GLAD_API_CALL PFNGLINDEXIPROC glad_glIndexi;
+#define glIndexi glad_glIndexi
+GLAD_API_CALL PFNGLINDEXIVPROC glad_glIndexiv;
+#define glIndexiv glad_glIndexiv
+GLAD_API_CALL PFNGLINDEXSPROC glad_glIndexs;
+#define glIndexs glad_glIndexs
+GLAD_API_CALL PFNGLINDEXSVPROC glad_glIndexsv;
+#define glIndexsv glad_glIndexsv
+GLAD_API_CALL PFNGLINDEXUBPROC glad_glIndexub;
+#define glIndexub glad_glIndexub
+GLAD_API_CALL PFNGLINDEXUBVPROC glad_glIndexubv;
+#define glIndexubv glad_glIndexubv
+GLAD_API_CALL PFNGLINITNAMESPROC glad_glInitNames;
+#define glInitNames glad_glInitNames
+GLAD_API_CALL PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
+#define glInterleavedArrays glad_glInterleavedArrays
+GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi;
+#define glIsEnabledi glad_glIsEnabledi
+GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+GLAD_API_CALL PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT;
+#define glIsFramebufferEXT glad_glIsFramebufferEXT
+GLAD_API_CALL PFNGLISLISTPROC glad_glIsList;
+#define glIsList glad_glIsList
+GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery;
+#define glIsQuery glad_glIsQuery
+GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+GLAD_API_CALL PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT;
+#define glIsRenderbufferEXT glad_glIsRenderbufferEXT
+GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler;
+#define glIsSampler glad_glIsSampler
+GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync;
+#define glIsSync glad_glIsSync
+GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
+#define glIsVertexArray glad_glIsVertexArray
+GLAD_API_CALL PFNGLLIGHTMODELFPROC glad_glLightModelf;
+#define glLightModelf glad_glLightModelf
+GLAD_API_CALL PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
+#define glLightModelfv glad_glLightModelfv
+GLAD_API_CALL PFNGLLIGHTMODELIPROC glad_glLightModeli;
+#define glLightModeli glad_glLightModeli
+GLAD_API_CALL PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
+#define glLightModeliv glad_glLightModeliv
+GLAD_API_CALL PFNGLLIGHTFPROC glad_glLightf;
+#define glLightf glad_glLightf
+GLAD_API_CALL PFNGLLIGHTFVPROC glad_glLightfv;
+#define glLightfv glad_glLightfv
+GLAD_API_CALL PFNGLLIGHTIPROC glad_glLighti;
+#define glLighti glad_glLighti
+GLAD_API_CALL PFNGLLIGHTIVPROC glad_glLightiv;
+#define glLightiv glad_glLightiv
+GLAD_API_CALL PFNGLLINESTIPPLEPROC glad_glLineStipple;
+#define glLineStipple glad_glLineStipple
+GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+GLAD_API_CALL PFNGLLISTBASEPROC glad_glListBase;
+#define glListBase glad_glListBase
+GLAD_API_CALL PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
+#define glLoadIdentity glad_glLoadIdentity
+GLAD_API_CALL PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
+#define glLoadMatrixd glad_glLoadMatrixd
+GLAD_API_CALL PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
+#define glLoadMatrixf glad_glLoadMatrixf
+GLAD_API_CALL PFNGLLOADNAMEPROC glad_glLoadName;
+#define glLoadName glad_glLoadName
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
+#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
+#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf
+GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp;
+#define glLogicOp glad_glLogicOp
+GLAD_API_CALL PFNGLMAP1DPROC glad_glMap1d;
+#define glMap1d glad_glMap1d
+GLAD_API_CALL PFNGLMAP1FPROC glad_glMap1f;
+#define glMap1f glad_glMap1f
+GLAD_API_CALL PFNGLMAP2DPROC glad_glMap2d;
+#define glMap2d glad_glMap2d
+GLAD_API_CALL PFNGLMAP2FPROC glad_glMap2f;
+#define glMap2f glad_glMap2f
+GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer;
+#define glMapBuffer glad_glMapBuffer
+GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
+#define glMapBufferRange glad_glMapBufferRange
+GLAD_API_CALL PFNGLMAPGRID1DPROC glad_glMapGrid1d;
+#define glMapGrid1d glad_glMapGrid1d
+GLAD_API_CALL PFNGLMAPGRID1FPROC glad_glMapGrid1f;
+#define glMapGrid1f glad_glMapGrid1f
+GLAD_API_CALL PFNGLMAPGRID2DPROC glad_glMapGrid2d;
+#define glMapGrid2d glad_glMapGrid2d
+GLAD_API_CALL PFNGLMAPGRID2FPROC glad_glMapGrid2f;
+#define glMapGrid2f glad_glMapGrid2f
+GLAD_API_CALL PFNGLMATERIALFPROC glad_glMaterialf;
+#define glMaterialf glad_glMaterialf
+GLAD_API_CALL PFNGLMATERIALFVPROC glad_glMaterialfv;
+#define glMaterialfv glad_glMaterialfv
+GLAD_API_CALL PFNGLMATERIALIPROC glad_glMateriali;
+#define glMateriali glad_glMateriali
+GLAD_API_CALL PFNGLMATERIALIVPROC glad_glMaterialiv;
+#define glMaterialiv glad_glMaterialiv
+GLAD_API_CALL PFNGLMATRIXMODEPROC glad_glMatrixMode;
+#define glMatrixMode glad_glMatrixMode
+GLAD_API_CALL PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
+#define glMultMatrixd glad_glMultMatrixd
+GLAD_API_CALL PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
+#define glMultMatrixf glad_glMultMatrixf
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
+#define glMultTransposeMatrixd glad_glMultTransposeMatrixd
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
+#define glMultTransposeMatrixf glad_glMultTransposeMatrixf
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
+#define glMultiDrawArrays glad_glMultiDrawArrays
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
+#define glMultiDrawElements glad_glMultiDrawElements
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
+#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
+GLAD_API_CALL PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
+#define glMultiTexCoord1d glad_glMultiTexCoord1d
+GLAD_API_CALL PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
+#define glMultiTexCoord1dv glad_glMultiTexCoord1dv
+GLAD_API_CALL PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
+#define glMultiTexCoord1f glad_glMultiTexCoord1f
+GLAD_API_CALL PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
+#define glMultiTexCoord1fv glad_glMultiTexCoord1fv
+GLAD_API_CALL PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
+#define glMultiTexCoord1i glad_glMultiTexCoord1i
+GLAD_API_CALL PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
+#define glMultiTexCoord1iv glad_glMultiTexCoord1iv
+GLAD_API_CALL PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
+#define glMultiTexCoord1s glad_glMultiTexCoord1s
+GLAD_API_CALL PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
+#define glMultiTexCoord1sv glad_glMultiTexCoord1sv
+GLAD_API_CALL PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
+#define glMultiTexCoord2d glad_glMultiTexCoord2d
+GLAD_API_CALL PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
+#define glMultiTexCoord2dv glad_glMultiTexCoord2dv
+GLAD_API_CALL PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
+#define glMultiTexCoord2f glad_glMultiTexCoord2f
+GLAD_API_CALL PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
+#define glMultiTexCoord2fv glad_glMultiTexCoord2fv
+GLAD_API_CALL PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
+#define glMultiTexCoord2i glad_glMultiTexCoord2i
+GLAD_API_CALL PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
+#define glMultiTexCoord2iv glad_glMultiTexCoord2iv
+GLAD_API_CALL PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
+#define glMultiTexCoord2s glad_glMultiTexCoord2s
+GLAD_API_CALL PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
+#define glMultiTexCoord2sv glad_glMultiTexCoord2sv
+GLAD_API_CALL PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
+#define glMultiTexCoord3d glad_glMultiTexCoord3d
+GLAD_API_CALL PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
+#define glMultiTexCoord3dv glad_glMultiTexCoord3dv
+GLAD_API_CALL PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
+#define glMultiTexCoord3f glad_glMultiTexCoord3f
+GLAD_API_CALL PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
+#define glMultiTexCoord3fv glad_glMultiTexCoord3fv
+GLAD_API_CALL PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
+#define glMultiTexCoord3i glad_glMultiTexCoord3i
+GLAD_API_CALL PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
+#define glMultiTexCoord3iv glad_glMultiTexCoord3iv
+GLAD_API_CALL PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
+#define glMultiTexCoord3s glad_glMultiTexCoord3s
+GLAD_API_CALL PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
+#define glMultiTexCoord3sv glad_glMultiTexCoord3sv
+GLAD_API_CALL PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
+#define glMultiTexCoord4d glad_glMultiTexCoord4d
+GLAD_API_CALL PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
+#define glMultiTexCoord4dv glad_glMultiTexCoord4dv
+GLAD_API_CALL PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
+#define glMultiTexCoord4f glad_glMultiTexCoord4f
+GLAD_API_CALL PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
+#define glMultiTexCoord4fv glad_glMultiTexCoord4fv
+GLAD_API_CALL PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
+#define glMultiTexCoord4i glad_glMultiTexCoord4i
+GLAD_API_CALL PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
+#define glMultiTexCoord4iv glad_glMultiTexCoord4iv
+GLAD_API_CALL PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
+#define glMultiTexCoord4s glad_glMultiTexCoord4s
+GLAD_API_CALL PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
+#define glMultiTexCoord4sv glad_glMultiTexCoord4sv
+GLAD_API_CALL PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
+#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
+#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
+#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
+#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
+#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
+#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
+#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
+#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
+GLAD_API_CALL PFNGLNEWLISTPROC glad_glNewList;
+#define glNewList glad_glNewList
+GLAD_API_CALL PFNGLNORMAL3BPROC glad_glNormal3b;
+#define glNormal3b glad_glNormal3b
+GLAD_API_CALL PFNGLNORMAL3BVPROC glad_glNormal3bv;
+#define glNormal3bv glad_glNormal3bv
+GLAD_API_CALL PFNGLNORMAL3DPROC glad_glNormal3d;
+#define glNormal3d glad_glNormal3d
+GLAD_API_CALL PFNGLNORMAL3DVPROC glad_glNormal3dv;
+#define glNormal3dv glad_glNormal3dv
+GLAD_API_CALL PFNGLNORMAL3FPROC glad_glNormal3f;
+#define glNormal3f glad_glNormal3f
+GLAD_API_CALL PFNGLNORMAL3FVPROC glad_glNormal3fv;
+#define glNormal3fv glad_glNormal3fv
+GLAD_API_CALL PFNGLNORMAL3IPROC glad_glNormal3i;
+#define glNormal3i glad_glNormal3i
+GLAD_API_CALL PFNGLNORMAL3IVPROC glad_glNormal3iv;
+#define glNormal3iv glad_glNormal3iv
+GLAD_API_CALL PFNGLNORMAL3SPROC glad_glNormal3s;
+#define glNormal3s glad_glNormal3s
+GLAD_API_CALL PFNGLNORMAL3SVPROC glad_glNormal3sv;
+#define glNormal3sv glad_glNormal3sv
+GLAD_API_CALL PFNGLNORMALP3UIPROC glad_glNormalP3ui;
+#define glNormalP3ui glad_glNormalP3ui
+GLAD_API_CALL PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
+#define glNormalP3uiv glad_glNormalP3uiv
+GLAD_API_CALL PFNGLNORMALPOINTERPROC glad_glNormalPointer;
+#define glNormalPointer glad_glNormalPointer
+GLAD_API_CALL PFNGLORTHOPROC glad_glOrtho;
+#define glOrtho glad_glOrtho
+GLAD_API_CALL PFNGLPASSTHROUGHPROC glad_glPassThrough;
+#define glPassThrough glad_glPassThrough
+GLAD_API_CALL PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
+#define glPixelMapfv glad_glPixelMapfv
+GLAD_API_CALL PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
+#define glPixelMapuiv glad_glPixelMapuiv
+GLAD_API_CALL PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
+#define glPixelMapusv glad_glPixelMapusv
+GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref;
+#define glPixelStoref glad_glPixelStoref
+GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+GLAD_API_CALL PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
+#define glPixelTransferf glad_glPixelTransferf
+GLAD_API_CALL PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
+#define glPixelTransferi glad_glPixelTransferi
+GLAD_API_CALL PFNGLPIXELZOOMPROC glad_glPixelZoom;
+#define glPixelZoom glad_glPixelZoom
+GLAD_API_CALL PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
+#define glPointParameterf glad_glPointParameterf
+GLAD_API_CALL PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
+#define glPointParameterfv glad_glPointParameterfv
+GLAD_API_CALL PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
+#define glPointParameteri glad_glPointParameteri
+GLAD_API_CALL PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
+#define glPointParameteriv glad_glPointParameteriv
+GLAD_API_CALL PFNGLPOINTSIZEPROC glad_glPointSize;
+#define glPointSize glad_glPointSize
+GLAD_API_CALL PFNGLPOLYGONMODEPROC glad_glPolygonMode;
+#define glPolygonMode glad_glPolygonMode
+GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+GLAD_API_CALL PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
+#define glPolygonStipple glad_glPolygonStipple
+GLAD_API_CALL PFNGLPOPATTRIBPROC glad_glPopAttrib;
+#define glPopAttrib glad_glPopAttrib
+GLAD_API_CALL PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
+#define glPopClientAttrib glad_glPopClientAttrib
+GLAD_API_CALL PFNGLPOPMATRIXPROC glad_glPopMatrix;
+#define glPopMatrix glad_glPopMatrix
+GLAD_API_CALL PFNGLPOPNAMEPROC glad_glPopName;
+#define glPopName glad_glPopName
+GLAD_API_CALL PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
+#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
+GLAD_API_CALL PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
+#define glPrioritizeTextures glad_glPrioritizeTextures
+GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
+#define glProvokingVertex glad_glProvokingVertex
+GLAD_API_CALL PFNGLPUSHATTRIBPROC glad_glPushAttrib;
+#define glPushAttrib glad_glPushAttrib
+GLAD_API_CALL PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
+#define glPushClientAttrib glad_glPushClientAttrib
+GLAD_API_CALL PFNGLPUSHMATRIXPROC glad_glPushMatrix;
+#define glPushMatrix glad_glPushMatrix
+GLAD_API_CALL PFNGLPUSHNAMEPROC glad_glPushName;
+#define glPushName glad_glPushName
+GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
+#define glQueryCounter glad_glQueryCounter
+GLAD_API_CALL PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
+#define glRasterPos2d glad_glRasterPos2d
+GLAD_API_CALL PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
+#define glRasterPos2dv glad_glRasterPos2dv
+GLAD_API_CALL PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
+#define glRasterPos2f glad_glRasterPos2f
+GLAD_API_CALL PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
+#define glRasterPos2fv glad_glRasterPos2fv
+GLAD_API_CALL PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
+#define glRasterPos2i glad_glRasterPos2i
+GLAD_API_CALL PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
+#define glRasterPos2iv glad_glRasterPos2iv
+GLAD_API_CALL PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
+#define glRasterPos2s glad_glRasterPos2s
+GLAD_API_CALL PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
+#define glRasterPos2sv glad_glRasterPos2sv
+GLAD_API_CALL PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
+#define glRasterPos3d glad_glRasterPos3d
+GLAD_API_CALL PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
+#define glRasterPos3dv glad_glRasterPos3dv
+GLAD_API_CALL PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
+#define glRasterPos3f glad_glRasterPos3f
+GLAD_API_CALL PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
+#define glRasterPos3fv glad_glRasterPos3fv
+GLAD_API_CALL PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
+#define glRasterPos3i glad_glRasterPos3i
+GLAD_API_CALL PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
+#define glRasterPos3iv glad_glRasterPos3iv
+GLAD_API_CALL PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
+#define glRasterPos3s glad_glRasterPos3s
+GLAD_API_CALL PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
+#define glRasterPos3sv glad_glRasterPos3sv
+GLAD_API_CALL PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
+#define glRasterPos4d glad_glRasterPos4d
+GLAD_API_CALL PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
+#define glRasterPos4dv glad_glRasterPos4dv
+GLAD_API_CALL PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
+#define glRasterPos4f glad_glRasterPos4f
+GLAD_API_CALL PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
+#define glRasterPos4fv glad_glRasterPos4fv
+GLAD_API_CALL PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
+#define glRasterPos4i glad_glRasterPos4i
+GLAD_API_CALL PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
+#define glRasterPos4iv glad_glRasterPos4iv
+GLAD_API_CALL PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
+#define glRasterPos4s glad_glRasterPos4s
+GLAD_API_CALL PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
+#define glRasterPos4sv glad_glRasterPos4sv
+GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer;
+#define glReadBuffer glad_glReadBuffer
+GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+GLAD_API_CALL PFNGLRECTDPROC glad_glRectd;
+#define glRectd glad_glRectd
+GLAD_API_CALL PFNGLRECTDVPROC glad_glRectdv;
+#define glRectdv glad_glRectdv
+GLAD_API_CALL PFNGLRECTFPROC glad_glRectf;
+#define glRectf glad_glRectf
+GLAD_API_CALL PFNGLRECTFVPROC glad_glRectfv;
+#define glRectfv glad_glRectfv
+GLAD_API_CALL PFNGLRECTIPROC glad_glRecti;
+#define glRecti glad_glRecti
+GLAD_API_CALL PFNGLRECTIVPROC glad_glRectiv;
+#define glRectiv glad_glRectiv
+GLAD_API_CALL PFNGLRECTSPROC glad_glRects;
+#define glRects glad_glRects
+GLAD_API_CALL PFNGLRECTSVPROC glad_glRectsv;
+#define glRectsv glad_glRectsv
+GLAD_API_CALL PFNGLRENDERMODEPROC glad_glRenderMode;
+#define glRenderMode glad_glRenderMode
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT;
+#define glRenderbufferStorageEXT glad_glRenderbufferStorageEXT
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
+#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
+#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
+GLAD_API_CALL PFNGLROTATEDPROC glad_glRotated;
+#define glRotated glad_glRotated
+GLAD_API_CALL PFNGLROTATEFPROC glad_glRotatef;
+#define glRotatef glad_glRotatef
+GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
+#define glSampleMaski glad_glSampleMaski
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
+#define glSamplerParameterIiv glad_glSamplerParameterIiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
+#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
+#define glSamplerParameterf glad_glSamplerParameterf
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
+#define glSamplerParameterfv glad_glSamplerParameterfv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
+#define glSamplerParameteri glad_glSamplerParameteri
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
+#define glSamplerParameteriv glad_glSamplerParameteriv
+GLAD_API_CALL PFNGLSCALEDPROC glad_glScaled;
+#define glScaled glad_glScaled
+GLAD_API_CALL PFNGLSCALEFPROC glad_glScalef;
+#define glScalef glad_glScalef
+GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+GLAD_API_CALL PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
+#define glSecondaryColor3b glad_glSecondaryColor3b
+GLAD_API_CALL PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
+#define glSecondaryColor3bv glad_glSecondaryColor3bv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
+#define glSecondaryColor3d glad_glSecondaryColor3d
+GLAD_API_CALL PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
+#define glSecondaryColor3dv glad_glSecondaryColor3dv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
+#define glSecondaryColor3f glad_glSecondaryColor3f
+GLAD_API_CALL PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
+#define glSecondaryColor3fv glad_glSecondaryColor3fv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
+#define glSecondaryColor3i glad_glSecondaryColor3i
+GLAD_API_CALL PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
+#define glSecondaryColor3iv glad_glSecondaryColor3iv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
+#define glSecondaryColor3s glad_glSecondaryColor3s
+GLAD_API_CALL PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
+#define glSecondaryColor3sv glad_glSecondaryColor3sv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
+#define glSecondaryColor3ub glad_glSecondaryColor3ub
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
+#define glSecondaryColor3ubv glad_glSecondaryColor3ubv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
+#define glSecondaryColor3ui glad_glSecondaryColor3ui
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
+#define glSecondaryColor3uiv glad_glSecondaryColor3uiv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
+#define glSecondaryColor3us glad_glSecondaryColor3us
+GLAD_API_CALL PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
+#define glSecondaryColor3usv glad_glSecondaryColor3usv
+GLAD_API_CALL PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
+#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
+GLAD_API_CALL PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
+#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
+GLAD_API_CALL PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
+#define glSecondaryColorPointer glad_glSecondaryColorPointer
+GLAD_API_CALL PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
+#define glSelectBuffer glad_glSelectBuffer
+GLAD_API_CALL PFNGLSHADEMODELPROC glad_glShadeModel;
+#define glShadeModel glad_glShadeModel
+GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer;
+#define glTexBuffer glad_glTexBuffer
+GLAD_API_CALL PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
+#define glTexCoord1d glad_glTexCoord1d
+GLAD_API_CALL PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
+#define glTexCoord1dv glad_glTexCoord1dv
+GLAD_API_CALL PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
+#define glTexCoord1f glad_glTexCoord1f
+GLAD_API_CALL PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
+#define glTexCoord1fv glad_glTexCoord1fv
+GLAD_API_CALL PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
+#define glTexCoord1i glad_glTexCoord1i
+GLAD_API_CALL PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
+#define glTexCoord1iv glad_glTexCoord1iv
+GLAD_API_CALL PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
+#define glTexCoord1s glad_glTexCoord1s
+GLAD_API_CALL PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
+#define glTexCoord1sv glad_glTexCoord1sv
+GLAD_API_CALL PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
+#define glTexCoord2d glad_glTexCoord2d
+GLAD_API_CALL PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
+#define glTexCoord2dv glad_glTexCoord2dv
+GLAD_API_CALL PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
+#define glTexCoord2f glad_glTexCoord2f
+GLAD_API_CALL PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
+#define glTexCoord2fv glad_glTexCoord2fv
+GLAD_API_CALL PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
+#define glTexCoord2i glad_glTexCoord2i
+GLAD_API_CALL PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
+#define glTexCoord2iv glad_glTexCoord2iv
+GLAD_API_CALL PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
+#define glTexCoord2s glad_glTexCoord2s
+GLAD_API_CALL PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
+#define glTexCoord2sv glad_glTexCoord2sv
+GLAD_API_CALL PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
+#define glTexCoord3d glad_glTexCoord3d
+GLAD_API_CALL PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
+#define glTexCoord3dv glad_glTexCoord3dv
+GLAD_API_CALL PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
+#define glTexCoord3f glad_glTexCoord3f
+GLAD_API_CALL PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
+#define glTexCoord3fv glad_glTexCoord3fv
+GLAD_API_CALL PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
+#define glTexCoord3i glad_glTexCoord3i
+GLAD_API_CALL PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
+#define glTexCoord3iv glad_glTexCoord3iv
+GLAD_API_CALL PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
+#define glTexCoord3s glad_glTexCoord3s
+GLAD_API_CALL PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
+#define glTexCoord3sv glad_glTexCoord3sv
+GLAD_API_CALL PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
+#define glTexCoord4d glad_glTexCoord4d
+GLAD_API_CALL PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
+#define glTexCoord4dv glad_glTexCoord4dv
+GLAD_API_CALL PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
+#define glTexCoord4f glad_glTexCoord4f
+GLAD_API_CALL PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
+#define glTexCoord4fv glad_glTexCoord4fv
+GLAD_API_CALL PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
+#define glTexCoord4i glad_glTexCoord4i
+GLAD_API_CALL PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
+#define glTexCoord4iv glad_glTexCoord4iv
+GLAD_API_CALL PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
+#define glTexCoord4s glad_glTexCoord4s
+GLAD_API_CALL PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
+#define glTexCoord4sv glad_glTexCoord4sv
+GLAD_API_CALL PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
+#define glTexCoordP1ui glad_glTexCoordP1ui
+GLAD_API_CALL PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
+#define glTexCoordP1uiv glad_glTexCoordP1uiv
+GLAD_API_CALL PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
+#define glTexCoordP2ui glad_glTexCoordP2ui
+GLAD_API_CALL PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
+#define glTexCoordP2uiv glad_glTexCoordP2uiv
+GLAD_API_CALL PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
+#define glTexCoordP3ui glad_glTexCoordP3ui
+GLAD_API_CALL PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
+#define glTexCoordP3uiv glad_glTexCoordP3uiv
+GLAD_API_CALL PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
+#define glTexCoordP4ui glad_glTexCoordP4ui
+GLAD_API_CALL PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
+#define glTexCoordP4uiv glad_glTexCoordP4uiv
+GLAD_API_CALL PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
+#define glTexCoordPointer glad_glTexCoordPointer
+GLAD_API_CALL PFNGLTEXENVFPROC glad_glTexEnvf;
+#define glTexEnvf glad_glTexEnvf
+GLAD_API_CALL PFNGLTEXENVFVPROC glad_glTexEnvfv;
+#define glTexEnvfv glad_glTexEnvfv
+GLAD_API_CALL PFNGLTEXENVIPROC glad_glTexEnvi;
+#define glTexEnvi glad_glTexEnvi
+GLAD_API_CALL PFNGLTEXENVIVPROC glad_glTexEnviv;
+#define glTexEnviv glad_glTexEnviv
+GLAD_API_CALL PFNGLTEXGENDPROC glad_glTexGend;
+#define glTexGend glad_glTexGend
+GLAD_API_CALL PFNGLTEXGENDVPROC glad_glTexGendv;
+#define glTexGendv glad_glTexGendv
+GLAD_API_CALL PFNGLTEXGENFPROC glad_glTexGenf;
+#define glTexGenf glad_glTexGenf
+GLAD_API_CALL PFNGLTEXGENFVPROC glad_glTexGenfv;
+#define glTexGenfv glad_glTexGenfv
+GLAD_API_CALL PFNGLTEXGENIPROC glad_glTexGeni;
+#define glTexGeni glad_glTexGeni
+GLAD_API_CALL PFNGLTEXGENIVPROC glad_glTexGeniv;
+#define glTexGeniv glad_glTexGeniv
+GLAD_API_CALL PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
+#define glTexImage1D glad_glTexImage1D
+GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+GLAD_API_CALL PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
+#define glTexImage2DMultisample glad_glTexImage2DMultisample
+GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
+#define glTexImage3D glad_glTexImage3D
+GLAD_API_CALL PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
+#define glTexImage3DMultisample glad_glTexImage3DMultisample
+GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
+#define glTexParameterIiv glad_glTexParameterIiv
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
+#define glTexParameterIuiv glad_glTexParameterIuiv
+GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+GLAD_API_CALL PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
+#define glTexSubImage1D glad_glTexSubImage1D
+GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
+#define glTexSubImage3D glad_glTexSubImage3D
+GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
+#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
+GLAD_API_CALL PFNGLTRANSLATEDPROC glad_glTranslated;
+#define glTranslated glad_glTranslated
+GLAD_API_CALL PFNGLTRANSLATEFPROC glad_glTranslatef;
+#define glTranslatef glad_glTranslatef
+GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui;
+#define glUniform1ui glad_glUniform1ui
+GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
+#define glUniform1uiv glad_glUniform1uiv
+GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui;
+#define glUniform2ui glad_glUniform2ui
+GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
+#define glUniform2uiv glad_glUniform2uiv
+GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui;
+#define glUniform3ui glad_glUniform3ui
+GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
+#define glUniform3uiv glad_glUniform3uiv
+GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui;
+#define glUniform4ui glad_glUniform4ui
+GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
+#define glUniform4uiv glad_glUniform4uiv
+GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
+#define glUniformBlockBinding glad_glUniformBlockBinding
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
+#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
+#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
+#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
+#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
+#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
+#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
+GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
+#define glUnmapBuffer glad_glUnmapBuffer
+GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+GLAD_API_CALL PFNGLVERTEX2DPROC glad_glVertex2d;
+#define glVertex2d glad_glVertex2d
+GLAD_API_CALL PFNGLVERTEX2DVPROC glad_glVertex2dv;
+#define glVertex2dv glad_glVertex2dv
+GLAD_API_CALL PFNGLVERTEX2FPROC glad_glVertex2f;
+#define glVertex2f glad_glVertex2f
+GLAD_API_CALL PFNGLVERTEX2FVPROC glad_glVertex2fv;
+#define glVertex2fv glad_glVertex2fv
+GLAD_API_CALL PFNGLVERTEX2IPROC glad_glVertex2i;
+#define glVertex2i glad_glVertex2i
+GLAD_API_CALL PFNGLVERTEX2IVPROC glad_glVertex2iv;
+#define glVertex2iv glad_glVertex2iv
+GLAD_API_CALL PFNGLVERTEX2SPROC glad_glVertex2s;
+#define glVertex2s glad_glVertex2s
+GLAD_API_CALL PFNGLVERTEX2SVPROC glad_glVertex2sv;
+#define glVertex2sv glad_glVertex2sv
+GLAD_API_CALL PFNGLVERTEX3DPROC glad_glVertex3d;
+#define glVertex3d glad_glVertex3d
+GLAD_API_CALL PFNGLVERTEX3DVPROC glad_glVertex3dv;
+#define glVertex3dv glad_glVertex3dv
+GLAD_API_CALL PFNGLVERTEX3FPROC glad_glVertex3f;
+#define glVertex3f glad_glVertex3f
+GLAD_API_CALL PFNGLVERTEX3FVPROC glad_glVertex3fv;
+#define glVertex3fv glad_glVertex3fv
+GLAD_API_CALL PFNGLVERTEX3IPROC glad_glVertex3i;
+#define glVertex3i glad_glVertex3i
+GLAD_API_CALL PFNGLVERTEX3IVPROC glad_glVertex3iv;
+#define glVertex3iv glad_glVertex3iv
+GLAD_API_CALL PFNGLVERTEX3SPROC glad_glVertex3s;
+#define glVertex3s glad_glVertex3s
+GLAD_API_CALL PFNGLVERTEX3SVPROC glad_glVertex3sv;
+#define glVertex3sv glad_glVertex3sv
+GLAD_API_CALL PFNGLVERTEX4DPROC glad_glVertex4d;
+#define glVertex4d glad_glVertex4d
+GLAD_API_CALL PFNGLVERTEX4DVPROC glad_glVertex4dv;
+#define glVertex4dv glad_glVertex4dv
+GLAD_API_CALL PFNGLVERTEX4FPROC glad_glVertex4f;
+#define glVertex4f glad_glVertex4f
+GLAD_API_CALL PFNGLVERTEX4FVPROC glad_glVertex4fv;
+#define glVertex4fv glad_glVertex4fv
+GLAD_API_CALL PFNGLVERTEX4IPROC glad_glVertex4i;
+#define glVertex4i glad_glVertex4i
+GLAD_API_CALL PFNGLVERTEX4IVPROC glad_glVertex4iv;
+#define glVertex4iv glad_glVertex4iv
+GLAD_API_CALL PFNGLVERTEX4SPROC glad_glVertex4s;
+#define glVertex4s glad_glVertex4s
+GLAD_API_CALL PFNGLVERTEX4SVPROC glad_glVertex4sv;
+#define glVertex4sv glad_glVertex4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
+#define glVertexAttrib1d glad_glVertexAttrib1d
+GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
+#define glVertexAttrib1dv glad_glVertexAttrib1dv
+GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
+#define glVertexAttrib1s glad_glVertexAttrib1s
+GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
+#define glVertexAttrib1sv glad_glVertexAttrib1sv
+GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
+#define glVertexAttrib2d glad_glVertexAttrib2d
+GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
+#define glVertexAttrib2dv glad_glVertexAttrib2dv
+GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
+#define glVertexAttrib2s glad_glVertexAttrib2s
+GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
+#define glVertexAttrib2sv glad_glVertexAttrib2sv
+GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
+#define glVertexAttrib3d glad_glVertexAttrib3d
+GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
+#define glVertexAttrib3dv glad_glVertexAttrib3dv
+GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
+#define glVertexAttrib3s glad_glVertexAttrib3s
+GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
+#define glVertexAttrib3sv glad_glVertexAttrib3sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
+#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
+#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
+#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
+#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
+#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
+#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
+#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
+GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
+#define glVertexAttrib4bv glad_glVertexAttrib4bv
+GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
+#define glVertexAttrib4d glad_glVertexAttrib4d
+GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
+#define glVertexAttrib4dv glad_glVertexAttrib4dv
+GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
+#define glVertexAttrib4iv glad_glVertexAttrib4iv
+GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
+#define glVertexAttrib4s glad_glVertexAttrib4s
+GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
+#define glVertexAttrib4sv glad_glVertexAttrib4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
+#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
+#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
+#define glVertexAttrib4usv glad_glVertexAttrib4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
+#define glVertexAttribDivisor glad_glVertexAttribDivisor
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
+#define glVertexAttribI1i glad_glVertexAttribI1i
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
+#define glVertexAttribI1iv glad_glVertexAttribI1iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
+#define glVertexAttribI1ui glad_glVertexAttribI1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
+#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
+#define glVertexAttribI2i glad_glVertexAttribI2i
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
+#define glVertexAttribI2iv glad_glVertexAttribI2iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
+#define glVertexAttribI2ui glad_glVertexAttribI2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
+#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
+#define glVertexAttribI3i glad_glVertexAttribI3i
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
+#define glVertexAttribI3iv glad_glVertexAttribI3iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
+#define glVertexAttribI3ui glad_glVertexAttribI3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
+#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
+#define glVertexAttribI4bv glad_glVertexAttribI4bv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
+#define glVertexAttribI4i glad_glVertexAttribI4i
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
+#define glVertexAttribI4iv glad_glVertexAttribI4iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
+#define glVertexAttribI4sv glad_glVertexAttribI4sv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
+#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
+#define glVertexAttribI4ui glad_glVertexAttribI4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
+#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
+#define glVertexAttribI4usv glad_glVertexAttribI4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
+#define glVertexAttribIPointer glad_glVertexAttribIPointer
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
+#define glVertexAttribP1ui glad_glVertexAttribP1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
+#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
+#define glVertexAttribP2ui glad_glVertexAttribP2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
+#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
+#define glVertexAttribP3ui glad_glVertexAttribP3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
+#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
+#define glVertexAttribP4ui glad_glVertexAttribP4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
+#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+GLAD_API_CALL PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
+#define glVertexP2ui glad_glVertexP2ui
+GLAD_API_CALL PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
+#define glVertexP2uiv glad_glVertexP2uiv
+GLAD_API_CALL PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
+#define glVertexP3ui glad_glVertexP3ui
+GLAD_API_CALL PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
+#define glVertexP3uiv glad_glVertexP3uiv
+GLAD_API_CALL PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
+#define glVertexP4ui glad_glVertexP4ui
+GLAD_API_CALL PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
+#define glVertexP4uiv glad_glVertexP4uiv
+GLAD_API_CALL PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
+#define glVertexPointer glad_glVertexPointer
+GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync;
+#define glWaitSync glad_glWaitSync
+GLAD_API_CALL PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
+#define glWindowPos2d glad_glWindowPos2d
+GLAD_API_CALL PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
+#define glWindowPos2dv glad_glWindowPos2dv
+GLAD_API_CALL PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
+#define glWindowPos2f glad_glWindowPos2f
+GLAD_API_CALL PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
+#define glWindowPos2fv glad_glWindowPos2fv
+GLAD_API_CALL PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
+#define glWindowPos2i glad_glWindowPos2i
+GLAD_API_CALL PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
+#define glWindowPos2iv glad_glWindowPos2iv
+GLAD_API_CALL PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
+#define glWindowPos2s glad_glWindowPos2s
+GLAD_API_CALL PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
+#define glWindowPos2sv glad_glWindowPos2sv
+GLAD_API_CALL PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
+#define glWindowPos3d glad_glWindowPos3d
+GLAD_API_CALL PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
+#define glWindowPos3dv glad_glWindowPos3dv
+GLAD_API_CALL PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
+#define glWindowPos3f glad_glWindowPos3f
+GLAD_API_CALL PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
+#define glWindowPos3fv glad_glWindowPos3fv
+GLAD_API_CALL PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
+#define glWindowPos3i glad_glWindowPos3i
+GLAD_API_CALL PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
+#define glWindowPos3iv glad_glWindowPos3iv
+GLAD_API_CALL PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
+#define glWindowPos3s glad_glWindowPos3s
+GLAD_API_CALL PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
+#define glWindowPos3sv glad_glWindowPos3sv
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGL( GLADloadfunc load);
+
+
+#ifdef GLAD_GL
+
+GLAD_API_CALL int gladLoaderLoadGL(void);
+GLAD_API_CALL void gladLoaderUnloadGL(void);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h
deleted file mode 100644
index 37d12e4ee2..0000000000
--- a/thirdparty/glad/glad/glad.h
+++ /dev/null
@@ -1,3801 +0,0 @@
-/*
-
- OpenGL loader generated by glad 0.1.36 on Sun Sep 4 15:50:32 2022.
-
- Language/Generator: C/C++
- Specification: gl
- APIs: gl=3.3
- Profile: compatibility
- Extensions:
- GL_ARB_debug_output,
- GL_ARB_framebuffer_object,
- GL_EXT_framebuffer_blit,
- GL_EXT_framebuffer_multisample,
- GL_EXT_framebuffer_object,
- GL_OVR_multiview,
- GL_OVR_multiview2
- Loader: True
- Local files: False
- Omit khrplatform: False
- Reproducible: False
-
- Commandline:
- --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_OVR_multiview,GL_OVR_multiview2"
- Online:
- https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object&extensions=GL_OVR_multiview&extensions=GL_OVR_multiview2
-*/
-
-
-#ifndef __glad_h_
-#define __glad_h_
-
-#ifdef __gl_h_
-#error OpenGL header already included, remove this include, glad already provides it
-#endif
-#define __gl_h_
-
-#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
-#define APIENTRY __stdcall
-#endif
-
-#ifndef APIENTRY
-#define APIENTRY
-#endif
-#ifndef APIENTRYP
-#define APIENTRYP APIENTRY *
-#endif
-
-#ifndef GLAPIENTRY
-#define GLAPIENTRY APIENTRY
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct gladGLversionStruct {
- int major;
- int minor;
-};
-
-typedef void* (* GLADloadproc)(const char *name);
-
-#ifndef GLAPI
-# if defined(GLAD_GLAPI_EXPORT)
-# if defined(_WIN32) || defined(__CYGWIN__)
-# if defined(GLAD_GLAPI_EXPORT_BUILD)
-# if defined(__GNUC__)
-# define GLAPI __attribute__ ((dllexport)) extern
-# else
-# define GLAPI __declspec(dllexport) extern
-# endif
-# else
-# if defined(__GNUC__)
-# define GLAPI __attribute__ ((dllimport)) extern
-# else
-# define GLAPI __declspec(dllimport) extern
-# endif
-# endif
-# elif defined(__GNUC__) && defined(GLAD_GLAPI_EXPORT_BUILD)
-# define GLAPI __attribute__ ((visibility ("default"))) extern
-# else
-# define GLAPI extern
-# endif
-# else
-# define GLAPI extern
-# endif
-#endif
-
-GLAPI struct gladGLversionStruct GLVersion;
-
-GLAPI int gladLoadGL(void);
-
-GLAPI int gladLoadGLLoader(GLADloadproc);
-
-#include <KHR/khrplatform.h>
-typedef unsigned int GLenum;
-typedef unsigned char GLboolean;
-typedef unsigned int GLbitfield;
-typedef void GLvoid;
-typedef khronos_int8_t GLbyte;
-typedef khronos_uint8_t GLubyte;
-typedef khronos_int16_t GLshort;
-typedef khronos_uint16_t GLushort;
-typedef int GLint;
-typedef unsigned int GLuint;
-typedef khronos_int32_t GLclampx;
-typedef int GLsizei;
-typedef khronos_float_t GLfloat;
-typedef khronos_float_t GLclampf;
-typedef double GLdouble;
-typedef double GLclampd;
-typedef void *GLeglClientBufferEXT;
-typedef void *GLeglImageOES;
-typedef char GLchar;
-typedef char GLcharARB;
-#ifdef __APPLE__
-typedef void *GLhandleARB;
-#else
-typedef unsigned int GLhandleARB;
-#endif
-typedef khronos_uint16_t GLhalf;
-typedef khronos_uint16_t GLhalfARB;
-typedef khronos_int32_t GLfixed;
-typedef khronos_intptr_t GLintptr;
-typedef khronos_intptr_t GLintptrARB;
-typedef khronos_ssize_t GLsizeiptr;
-typedef khronos_ssize_t GLsizeiptrARB;
-typedef khronos_int64_t GLint64;
-typedef khronos_int64_t GLint64EXT;
-typedef khronos_uint64_t GLuint64;
-typedef khronos_uint64_t GLuint64EXT;
-typedef struct __GLsync *GLsync;
-struct _cl_context;
-struct _cl_event;
-typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void (APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
-typedef unsigned short GLhalfNV;
-typedef GLintptr GLvdpauSurfaceNV;
-typedef void (APIENTRY *GLVULKANPROCNV)(void);
-#define GL_DEPTH_BUFFER_BIT 0x00000100
-#define GL_STENCIL_BUFFER_BIT 0x00000400
-#define GL_COLOR_BUFFER_BIT 0x00004000
-#define GL_FALSE 0
-#define GL_TRUE 1
-#define GL_POINTS 0x0000
-#define GL_LINES 0x0001
-#define GL_LINE_LOOP 0x0002
-#define GL_LINE_STRIP 0x0003
-#define GL_TRIANGLES 0x0004
-#define GL_TRIANGLE_STRIP 0x0005
-#define GL_TRIANGLE_FAN 0x0006
-#define GL_QUADS 0x0007
-#define GL_NEVER 0x0200
-#define GL_LESS 0x0201
-#define GL_EQUAL 0x0202
-#define GL_LEQUAL 0x0203
-#define GL_GREATER 0x0204
-#define GL_NOTEQUAL 0x0205
-#define GL_GEQUAL 0x0206
-#define GL_ALWAYS 0x0207
-#define GL_ZERO 0
-#define GL_ONE 1
-#define GL_SRC_COLOR 0x0300
-#define GL_ONE_MINUS_SRC_COLOR 0x0301
-#define GL_SRC_ALPHA 0x0302
-#define GL_ONE_MINUS_SRC_ALPHA 0x0303
-#define GL_DST_ALPHA 0x0304
-#define GL_ONE_MINUS_DST_ALPHA 0x0305
-#define GL_DST_COLOR 0x0306
-#define GL_ONE_MINUS_DST_COLOR 0x0307
-#define GL_SRC_ALPHA_SATURATE 0x0308
-#define GL_NONE 0
-#define GL_FRONT_LEFT 0x0400
-#define GL_FRONT_RIGHT 0x0401
-#define GL_BACK_LEFT 0x0402
-#define GL_BACK_RIGHT 0x0403
-#define GL_FRONT 0x0404
-#define GL_BACK 0x0405
-#define GL_LEFT 0x0406
-#define GL_RIGHT 0x0407
-#define GL_FRONT_AND_BACK 0x0408
-#define GL_NO_ERROR 0
-#define GL_INVALID_ENUM 0x0500
-#define GL_INVALID_VALUE 0x0501
-#define GL_INVALID_OPERATION 0x0502
-#define GL_OUT_OF_MEMORY 0x0505
-#define GL_CW 0x0900
-#define GL_CCW 0x0901
-#define GL_POINT_SIZE 0x0B11
-#define GL_POINT_SIZE_RANGE 0x0B12
-#define GL_POINT_SIZE_GRANULARITY 0x0B13
-#define GL_LINE_SMOOTH 0x0B20
-#define GL_LINE_WIDTH 0x0B21
-#define GL_LINE_WIDTH_RANGE 0x0B22
-#define GL_LINE_WIDTH_GRANULARITY 0x0B23
-#define GL_POLYGON_MODE 0x0B40
-#define GL_POLYGON_SMOOTH 0x0B41
-#define GL_CULL_FACE 0x0B44
-#define GL_CULL_FACE_MODE 0x0B45
-#define GL_FRONT_FACE 0x0B46
-#define GL_DEPTH_RANGE 0x0B70
-#define GL_DEPTH_TEST 0x0B71
-#define GL_DEPTH_WRITEMASK 0x0B72
-#define GL_DEPTH_CLEAR_VALUE 0x0B73
-#define GL_DEPTH_FUNC 0x0B74
-#define GL_STENCIL_TEST 0x0B90
-#define GL_STENCIL_CLEAR_VALUE 0x0B91
-#define GL_STENCIL_FUNC 0x0B92
-#define GL_STENCIL_VALUE_MASK 0x0B93
-#define GL_STENCIL_FAIL 0x0B94
-#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
-#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
-#define GL_STENCIL_REF 0x0B97
-#define GL_STENCIL_WRITEMASK 0x0B98
-#define GL_VIEWPORT 0x0BA2
-#define GL_DITHER 0x0BD0
-#define GL_BLEND_DST 0x0BE0
-#define GL_BLEND_SRC 0x0BE1
-#define GL_BLEND 0x0BE2
-#define GL_LOGIC_OP_MODE 0x0BF0
-#define GL_DRAW_BUFFER 0x0C01
-#define GL_READ_BUFFER 0x0C02
-#define GL_SCISSOR_BOX 0x0C10
-#define GL_SCISSOR_TEST 0x0C11
-#define GL_COLOR_CLEAR_VALUE 0x0C22
-#define GL_COLOR_WRITEMASK 0x0C23
-#define GL_DOUBLEBUFFER 0x0C32
-#define GL_STEREO 0x0C33
-#define GL_LINE_SMOOTH_HINT 0x0C52
-#define GL_POLYGON_SMOOTH_HINT 0x0C53
-#define GL_UNPACK_SWAP_BYTES 0x0CF0
-#define GL_UNPACK_LSB_FIRST 0x0CF1
-#define GL_UNPACK_ROW_LENGTH 0x0CF2
-#define GL_UNPACK_SKIP_ROWS 0x0CF3
-#define GL_UNPACK_SKIP_PIXELS 0x0CF4
-#define GL_UNPACK_ALIGNMENT 0x0CF5
-#define GL_PACK_SWAP_BYTES 0x0D00
-#define GL_PACK_LSB_FIRST 0x0D01
-#define GL_PACK_ROW_LENGTH 0x0D02
-#define GL_PACK_SKIP_ROWS 0x0D03
-#define GL_PACK_SKIP_PIXELS 0x0D04
-#define GL_PACK_ALIGNMENT 0x0D05
-#define GL_MAX_TEXTURE_SIZE 0x0D33
-#define GL_MAX_VIEWPORT_DIMS 0x0D3A
-#define GL_SUBPIXEL_BITS 0x0D50
-#define GL_TEXTURE_1D 0x0DE0
-#define GL_TEXTURE_2D 0x0DE1
-#define GL_TEXTURE_WIDTH 0x1000
-#define GL_TEXTURE_HEIGHT 0x1001
-#define GL_TEXTURE_BORDER_COLOR 0x1004
-#define GL_DONT_CARE 0x1100
-#define GL_FASTEST 0x1101
-#define GL_NICEST 0x1102
-#define GL_BYTE 0x1400
-#define GL_UNSIGNED_BYTE 0x1401
-#define GL_SHORT 0x1402
-#define GL_UNSIGNED_SHORT 0x1403
-#define GL_INT 0x1404
-#define GL_UNSIGNED_INT 0x1405
-#define GL_FLOAT 0x1406
-#define GL_STACK_OVERFLOW 0x0503
-#define GL_STACK_UNDERFLOW 0x0504
-#define GL_CLEAR 0x1500
-#define GL_AND 0x1501
-#define GL_AND_REVERSE 0x1502
-#define GL_COPY 0x1503
-#define GL_AND_INVERTED 0x1504
-#define GL_NOOP 0x1505
-#define GL_XOR 0x1506
-#define GL_OR 0x1507
-#define GL_NOR 0x1508
-#define GL_EQUIV 0x1509
-#define GL_INVERT 0x150A
-#define GL_OR_REVERSE 0x150B
-#define GL_COPY_INVERTED 0x150C
-#define GL_OR_INVERTED 0x150D
-#define GL_NAND 0x150E
-#define GL_SET 0x150F
-#define GL_TEXTURE 0x1702
-#define GL_COLOR 0x1800
-#define GL_DEPTH 0x1801
-#define GL_STENCIL 0x1802
-#define GL_STENCIL_INDEX 0x1901
-#define GL_DEPTH_COMPONENT 0x1902
-#define GL_RED 0x1903
-#define GL_GREEN 0x1904
-#define GL_BLUE 0x1905
-#define GL_ALPHA 0x1906
-#define GL_RGB 0x1907
-#define GL_RGBA 0x1908
-#define GL_POINT 0x1B00
-#define GL_LINE 0x1B01
-#define GL_FILL 0x1B02
-#define GL_KEEP 0x1E00
-#define GL_REPLACE 0x1E01
-#define GL_INCR 0x1E02
-#define GL_DECR 0x1E03
-#define GL_VENDOR 0x1F00
-#define GL_RENDERER 0x1F01
-#define GL_VERSION 0x1F02
-#define GL_EXTENSIONS 0x1F03
-#define GL_NEAREST 0x2600
-#define GL_LINEAR 0x2601
-#define GL_NEAREST_MIPMAP_NEAREST 0x2700
-#define GL_LINEAR_MIPMAP_NEAREST 0x2701
-#define GL_NEAREST_MIPMAP_LINEAR 0x2702
-#define GL_LINEAR_MIPMAP_LINEAR 0x2703
-#define GL_TEXTURE_MAG_FILTER 0x2800
-#define GL_TEXTURE_MIN_FILTER 0x2801
-#define GL_TEXTURE_WRAP_S 0x2802
-#define GL_TEXTURE_WRAP_T 0x2803
-#define GL_REPEAT 0x2901
-#define GL_CURRENT_BIT 0x00000001
-#define GL_POINT_BIT 0x00000002
-#define GL_LINE_BIT 0x00000004
-#define GL_POLYGON_BIT 0x00000008
-#define GL_POLYGON_STIPPLE_BIT 0x00000010
-#define GL_PIXEL_MODE_BIT 0x00000020
-#define GL_LIGHTING_BIT 0x00000040
-#define GL_FOG_BIT 0x00000080
-#define GL_ACCUM_BUFFER_BIT 0x00000200
-#define GL_VIEWPORT_BIT 0x00000800
-#define GL_TRANSFORM_BIT 0x00001000
-#define GL_ENABLE_BIT 0x00002000
-#define GL_HINT_BIT 0x00008000
-#define GL_EVAL_BIT 0x00010000
-#define GL_LIST_BIT 0x00020000
-#define GL_TEXTURE_BIT 0x00040000
-#define GL_SCISSOR_BIT 0x00080000
-#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF
-#define GL_QUAD_STRIP 0x0008
-#define GL_POLYGON 0x0009
-#define GL_ACCUM 0x0100
-#define GL_LOAD 0x0101
-#define GL_RETURN 0x0102
-#define GL_MULT 0x0103
-#define GL_ADD 0x0104
-#define GL_AUX0 0x0409
-#define GL_AUX1 0x040A
-#define GL_AUX2 0x040B
-#define GL_AUX3 0x040C
-#define GL_2D 0x0600
-#define GL_3D 0x0601
-#define GL_3D_COLOR 0x0602
-#define GL_3D_COLOR_TEXTURE 0x0603
-#define GL_4D_COLOR_TEXTURE 0x0604
-#define GL_PASS_THROUGH_TOKEN 0x0700
-#define GL_POINT_TOKEN 0x0701
-#define GL_LINE_TOKEN 0x0702
-#define GL_POLYGON_TOKEN 0x0703
-#define GL_BITMAP_TOKEN 0x0704
-#define GL_DRAW_PIXEL_TOKEN 0x0705
-#define GL_COPY_PIXEL_TOKEN 0x0706
-#define GL_LINE_RESET_TOKEN 0x0707
-#define GL_EXP 0x0800
-#define GL_EXP2 0x0801
-#define GL_COEFF 0x0A00
-#define GL_ORDER 0x0A01
-#define GL_DOMAIN 0x0A02
-#define GL_PIXEL_MAP_I_TO_I 0x0C70
-#define GL_PIXEL_MAP_S_TO_S 0x0C71
-#define GL_PIXEL_MAP_I_TO_R 0x0C72
-#define GL_PIXEL_MAP_I_TO_G 0x0C73
-#define GL_PIXEL_MAP_I_TO_B 0x0C74
-#define GL_PIXEL_MAP_I_TO_A 0x0C75
-#define GL_PIXEL_MAP_R_TO_R 0x0C76
-#define GL_PIXEL_MAP_G_TO_G 0x0C77
-#define GL_PIXEL_MAP_B_TO_B 0x0C78
-#define GL_PIXEL_MAP_A_TO_A 0x0C79
-#define GL_CURRENT_COLOR 0x0B00
-#define GL_CURRENT_INDEX 0x0B01
-#define GL_CURRENT_NORMAL 0x0B02
-#define GL_CURRENT_TEXTURE_COORDS 0x0B03
-#define GL_CURRENT_RASTER_COLOR 0x0B04
-#define GL_CURRENT_RASTER_INDEX 0x0B05
-#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
-#define GL_CURRENT_RASTER_POSITION 0x0B07
-#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
-#define GL_CURRENT_RASTER_DISTANCE 0x0B09
-#define GL_POINT_SMOOTH 0x0B10
-#define GL_LINE_STIPPLE 0x0B24
-#define GL_LINE_STIPPLE_PATTERN 0x0B25
-#define GL_LINE_STIPPLE_REPEAT 0x0B26
-#define GL_LIST_MODE 0x0B30
-#define GL_MAX_LIST_NESTING 0x0B31
-#define GL_LIST_BASE 0x0B32
-#define GL_LIST_INDEX 0x0B33
-#define GL_POLYGON_STIPPLE 0x0B42
-#define GL_EDGE_FLAG 0x0B43
-#define GL_LIGHTING 0x0B50
-#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
-#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
-#define GL_LIGHT_MODEL_AMBIENT 0x0B53
-#define GL_SHADE_MODEL 0x0B54
-#define GL_COLOR_MATERIAL_FACE 0x0B55
-#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
-#define GL_COLOR_MATERIAL 0x0B57
-#define GL_FOG 0x0B60
-#define GL_FOG_INDEX 0x0B61
-#define GL_FOG_DENSITY 0x0B62
-#define GL_FOG_START 0x0B63
-#define GL_FOG_END 0x0B64
-#define GL_FOG_MODE 0x0B65
-#define GL_FOG_COLOR 0x0B66
-#define GL_ACCUM_CLEAR_VALUE 0x0B80
-#define GL_MATRIX_MODE 0x0BA0
-#define GL_NORMALIZE 0x0BA1
-#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
-#define GL_PROJECTION_STACK_DEPTH 0x0BA4
-#define GL_TEXTURE_STACK_DEPTH 0x0BA5
-#define GL_MODELVIEW_MATRIX 0x0BA6
-#define GL_PROJECTION_MATRIX 0x0BA7
-#define GL_TEXTURE_MATRIX 0x0BA8
-#define GL_ATTRIB_STACK_DEPTH 0x0BB0
-#define GL_ALPHA_TEST 0x0BC0
-#define GL_ALPHA_TEST_FUNC 0x0BC1
-#define GL_ALPHA_TEST_REF 0x0BC2
-#define GL_LOGIC_OP 0x0BF1
-#define GL_AUX_BUFFERS 0x0C00
-#define GL_INDEX_CLEAR_VALUE 0x0C20
-#define GL_INDEX_WRITEMASK 0x0C21
-#define GL_INDEX_MODE 0x0C30
-#define GL_RGBA_MODE 0x0C31
-#define GL_RENDER_MODE 0x0C40
-#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
-#define GL_POINT_SMOOTH_HINT 0x0C51
-#define GL_FOG_HINT 0x0C54
-#define GL_TEXTURE_GEN_S 0x0C60
-#define GL_TEXTURE_GEN_T 0x0C61
-#define GL_TEXTURE_GEN_R 0x0C62
-#define GL_TEXTURE_GEN_Q 0x0C63
-#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
-#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
-#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
-#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
-#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
-#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
-#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
-#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
-#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
-#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
-#define GL_MAP_COLOR 0x0D10
-#define GL_MAP_STENCIL 0x0D11
-#define GL_INDEX_SHIFT 0x0D12
-#define GL_INDEX_OFFSET 0x0D13
-#define GL_RED_SCALE 0x0D14
-#define GL_RED_BIAS 0x0D15
-#define GL_ZOOM_X 0x0D16
-#define GL_ZOOM_Y 0x0D17
-#define GL_GREEN_SCALE 0x0D18
-#define GL_GREEN_BIAS 0x0D19
-#define GL_BLUE_SCALE 0x0D1A
-#define GL_BLUE_BIAS 0x0D1B
-#define GL_ALPHA_SCALE 0x0D1C
-#define GL_ALPHA_BIAS 0x0D1D
-#define GL_DEPTH_SCALE 0x0D1E
-#define GL_DEPTH_BIAS 0x0D1F
-#define GL_MAX_EVAL_ORDER 0x0D30
-#define GL_MAX_LIGHTS 0x0D31
-#define GL_MAX_CLIP_PLANES 0x0D32
-#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
-#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
-#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
-#define GL_MAX_NAME_STACK_DEPTH 0x0D37
-#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
-#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
-#define GL_INDEX_BITS 0x0D51
-#define GL_RED_BITS 0x0D52
-#define GL_GREEN_BITS 0x0D53
-#define GL_BLUE_BITS 0x0D54
-#define GL_ALPHA_BITS 0x0D55
-#define GL_DEPTH_BITS 0x0D56
-#define GL_STENCIL_BITS 0x0D57
-#define GL_ACCUM_RED_BITS 0x0D58
-#define GL_ACCUM_GREEN_BITS 0x0D59
-#define GL_ACCUM_BLUE_BITS 0x0D5A
-#define GL_ACCUM_ALPHA_BITS 0x0D5B
-#define GL_NAME_STACK_DEPTH 0x0D70
-#define GL_AUTO_NORMAL 0x0D80
-#define GL_MAP1_COLOR_4 0x0D90
-#define GL_MAP1_INDEX 0x0D91
-#define GL_MAP1_NORMAL 0x0D92
-#define GL_MAP1_TEXTURE_COORD_1 0x0D93
-#define GL_MAP1_TEXTURE_COORD_2 0x0D94
-#define GL_MAP1_TEXTURE_COORD_3 0x0D95
-#define GL_MAP1_TEXTURE_COORD_4 0x0D96
-#define GL_MAP1_VERTEX_3 0x0D97
-#define GL_MAP1_VERTEX_4 0x0D98
-#define GL_MAP2_COLOR_4 0x0DB0
-#define GL_MAP2_INDEX 0x0DB1
-#define GL_MAP2_NORMAL 0x0DB2
-#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
-#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
-#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
-#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
-#define GL_MAP2_VERTEX_3 0x0DB7
-#define GL_MAP2_VERTEX_4 0x0DB8
-#define GL_MAP1_GRID_DOMAIN 0x0DD0
-#define GL_MAP1_GRID_SEGMENTS 0x0DD1
-#define GL_MAP2_GRID_DOMAIN 0x0DD2
-#define GL_MAP2_GRID_SEGMENTS 0x0DD3
-#define GL_TEXTURE_COMPONENTS 0x1003
-#define GL_TEXTURE_BORDER 0x1005
-#define GL_AMBIENT 0x1200
-#define GL_DIFFUSE 0x1201
-#define GL_SPECULAR 0x1202
-#define GL_POSITION 0x1203
-#define GL_SPOT_DIRECTION 0x1204
-#define GL_SPOT_EXPONENT 0x1205
-#define GL_SPOT_CUTOFF 0x1206
-#define GL_CONSTANT_ATTENUATION 0x1207
-#define GL_LINEAR_ATTENUATION 0x1208
-#define GL_QUADRATIC_ATTENUATION 0x1209
-#define GL_COMPILE 0x1300
-#define GL_COMPILE_AND_EXECUTE 0x1301
-#define GL_2_BYTES 0x1407
-#define GL_3_BYTES 0x1408
-#define GL_4_BYTES 0x1409
-#define GL_EMISSION 0x1600
-#define GL_SHININESS 0x1601
-#define GL_AMBIENT_AND_DIFFUSE 0x1602
-#define GL_COLOR_INDEXES 0x1603
-#define GL_MODELVIEW 0x1700
-#define GL_PROJECTION 0x1701
-#define GL_COLOR_INDEX 0x1900
-#define GL_LUMINANCE 0x1909
-#define GL_LUMINANCE_ALPHA 0x190A
-#define GL_BITMAP 0x1A00
-#define GL_RENDER 0x1C00
-#define GL_FEEDBACK 0x1C01
-#define GL_SELECT 0x1C02
-#define GL_FLAT 0x1D00
-#define GL_SMOOTH 0x1D01
-#define GL_S 0x2000
-#define GL_T 0x2001
-#define GL_R 0x2002
-#define GL_Q 0x2003
-#define GL_MODULATE 0x2100
-#define GL_DECAL 0x2101
-#define GL_TEXTURE_ENV_MODE 0x2200
-#define GL_TEXTURE_ENV_COLOR 0x2201
-#define GL_TEXTURE_ENV 0x2300
-#define GL_EYE_LINEAR 0x2400
-#define GL_OBJECT_LINEAR 0x2401
-#define GL_SPHERE_MAP 0x2402
-#define GL_TEXTURE_GEN_MODE 0x2500
-#define GL_OBJECT_PLANE 0x2501
-#define GL_EYE_PLANE 0x2502
-#define GL_CLAMP 0x2900
-#define GL_CLIP_PLANE0 0x3000
-#define GL_CLIP_PLANE1 0x3001
-#define GL_CLIP_PLANE2 0x3002
-#define GL_CLIP_PLANE3 0x3003
-#define GL_CLIP_PLANE4 0x3004
-#define GL_CLIP_PLANE5 0x3005
-#define GL_LIGHT0 0x4000
-#define GL_LIGHT1 0x4001
-#define GL_LIGHT2 0x4002
-#define GL_LIGHT3 0x4003
-#define GL_LIGHT4 0x4004
-#define GL_LIGHT5 0x4005
-#define GL_LIGHT6 0x4006
-#define GL_LIGHT7 0x4007
-#define GL_COLOR_LOGIC_OP 0x0BF2
-#define GL_POLYGON_OFFSET_UNITS 0x2A00
-#define GL_POLYGON_OFFSET_POINT 0x2A01
-#define GL_POLYGON_OFFSET_LINE 0x2A02
-#define GL_POLYGON_OFFSET_FILL 0x8037
-#define GL_POLYGON_OFFSET_FACTOR 0x8038
-#define GL_TEXTURE_BINDING_1D 0x8068
-#define GL_TEXTURE_BINDING_2D 0x8069
-#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
-#define GL_TEXTURE_RED_SIZE 0x805C
-#define GL_TEXTURE_GREEN_SIZE 0x805D
-#define GL_TEXTURE_BLUE_SIZE 0x805E
-#define GL_TEXTURE_ALPHA_SIZE 0x805F
-#define GL_DOUBLE 0x140A
-#define GL_PROXY_TEXTURE_1D 0x8063
-#define GL_PROXY_TEXTURE_2D 0x8064
-#define GL_R3_G3_B2 0x2A10
-#define GL_RGB4 0x804F
-#define GL_RGB5 0x8050
-#define GL_RGB8 0x8051
-#define GL_RGB10 0x8052
-#define GL_RGB12 0x8053
-#define GL_RGB16 0x8054
-#define GL_RGBA2 0x8055
-#define GL_RGBA4 0x8056
-#define GL_RGB5_A1 0x8057
-#define GL_RGBA8 0x8058
-#define GL_RGB10_A2 0x8059
-#define GL_RGBA12 0x805A
-#define GL_RGBA16 0x805B
-#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
-#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
-#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
-#define GL_VERTEX_ARRAY_POINTER 0x808E
-#define GL_NORMAL_ARRAY_POINTER 0x808F
-#define GL_COLOR_ARRAY_POINTER 0x8090
-#define GL_INDEX_ARRAY_POINTER 0x8091
-#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
-#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
-#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
-#define GL_SELECTION_BUFFER_POINTER 0x0DF3
-#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
-#define GL_INDEX_LOGIC_OP 0x0BF1
-#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
-#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
-#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
-#define GL_SELECTION_BUFFER_SIZE 0x0DF4
-#define GL_VERTEX_ARRAY 0x8074
-#define GL_NORMAL_ARRAY 0x8075
-#define GL_COLOR_ARRAY 0x8076
-#define GL_INDEX_ARRAY 0x8077
-#define GL_TEXTURE_COORD_ARRAY 0x8078
-#define GL_EDGE_FLAG_ARRAY 0x8079
-#define GL_VERTEX_ARRAY_SIZE 0x807A
-#define GL_VERTEX_ARRAY_TYPE 0x807B
-#define GL_VERTEX_ARRAY_STRIDE 0x807C
-#define GL_NORMAL_ARRAY_TYPE 0x807E
-#define GL_NORMAL_ARRAY_STRIDE 0x807F
-#define GL_COLOR_ARRAY_SIZE 0x8081
-#define GL_COLOR_ARRAY_TYPE 0x8082
-#define GL_COLOR_ARRAY_STRIDE 0x8083
-#define GL_INDEX_ARRAY_TYPE 0x8085
-#define GL_INDEX_ARRAY_STRIDE 0x8086
-#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
-#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
-#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
-#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
-#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
-#define GL_TEXTURE_INTENSITY_SIZE 0x8061
-#define GL_TEXTURE_PRIORITY 0x8066
-#define GL_TEXTURE_RESIDENT 0x8067
-#define GL_ALPHA4 0x803B
-#define GL_ALPHA8 0x803C
-#define GL_ALPHA12 0x803D
-#define GL_ALPHA16 0x803E
-#define GL_LUMINANCE4 0x803F
-#define GL_LUMINANCE8 0x8040
-#define GL_LUMINANCE12 0x8041
-#define GL_LUMINANCE16 0x8042
-#define GL_LUMINANCE4_ALPHA4 0x8043
-#define GL_LUMINANCE6_ALPHA2 0x8044
-#define GL_LUMINANCE8_ALPHA8 0x8045
-#define GL_LUMINANCE12_ALPHA4 0x8046
-#define GL_LUMINANCE12_ALPHA12 0x8047
-#define GL_LUMINANCE16_ALPHA16 0x8048
-#define GL_INTENSITY 0x8049
-#define GL_INTENSITY4 0x804A
-#define GL_INTENSITY8 0x804B
-#define GL_INTENSITY12 0x804C
-#define GL_INTENSITY16 0x804D
-#define GL_V2F 0x2A20
-#define GL_V3F 0x2A21
-#define GL_C4UB_V2F 0x2A22
-#define GL_C4UB_V3F 0x2A23
-#define GL_C3F_V3F 0x2A24
-#define GL_N3F_V3F 0x2A25
-#define GL_C4F_N3F_V3F 0x2A26
-#define GL_T2F_V3F 0x2A27
-#define GL_T4F_V4F 0x2A28
-#define GL_T2F_C4UB_V3F 0x2A29
-#define GL_T2F_C3F_V3F 0x2A2A
-#define GL_T2F_N3F_V3F 0x2A2B
-#define GL_T2F_C4F_N3F_V3F 0x2A2C
-#define GL_T4F_C4F_N3F_V4F 0x2A2D
-#define GL_UNSIGNED_BYTE_3_3_2 0x8032
-#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
-#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
-#define GL_UNSIGNED_INT_8_8_8_8 0x8035
-#define GL_UNSIGNED_INT_10_10_10_2 0x8036
-#define GL_TEXTURE_BINDING_3D 0x806A
-#define GL_PACK_SKIP_IMAGES 0x806B
-#define GL_PACK_IMAGE_HEIGHT 0x806C
-#define GL_UNPACK_SKIP_IMAGES 0x806D
-#define GL_UNPACK_IMAGE_HEIGHT 0x806E
-#define GL_TEXTURE_3D 0x806F
-#define GL_PROXY_TEXTURE_3D 0x8070
-#define GL_TEXTURE_DEPTH 0x8071
-#define GL_TEXTURE_WRAP_R 0x8072
-#define GL_MAX_3D_TEXTURE_SIZE 0x8073
-#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
-#define GL_UNSIGNED_SHORT_5_6_5 0x8363
-#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
-#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
-#define GL_BGR 0x80E0
-#define GL_BGRA 0x80E1
-#define GL_MAX_ELEMENTS_VERTICES 0x80E8
-#define GL_MAX_ELEMENTS_INDICES 0x80E9
-#define GL_CLAMP_TO_EDGE 0x812F
-#define GL_TEXTURE_MIN_LOD 0x813A
-#define GL_TEXTURE_MAX_LOD 0x813B
-#define GL_TEXTURE_BASE_LEVEL 0x813C
-#define GL_TEXTURE_MAX_LEVEL 0x813D
-#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
-#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
-#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
-#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
-#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
-#define GL_RESCALE_NORMAL 0x803A
-#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
-#define GL_SINGLE_COLOR 0x81F9
-#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
-#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
-#define GL_TEXTURE0 0x84C0
-#define GL_TEXTURE1 0x84C1
-#define GL_TEXTURE2 0x84C2
-#define GL_TEXTURE3 0x84C3
-#define GL_TEXTURE4 0x84C4
-#define GL_TEXTURE5 0x84C5
-#define GL_TEXTURE6 0x84C6
-#define GL_TEXTURE7 0x84C7
-#define GL_TEXTURE8 0x84C8
-#define GL_TEXTURE9 0x84C9
-#define GL_TEXTURE10 0x84CA
-#define GL_TEXTURE11 0x84CB
-#define GL_TEXTURE12 0x84CC
-#define GL_TEXTURE13 0x84CD
-#define GL_TEXTURE14 0x84CE
-#define GL_TEXTURE15 0x84CF
-#define GL_TEXTURE16 0x84D0
-#define GL_TEXTURE17 0x84D1
-#define GL_TEXTURE18 0x84D2
-#define GL_TEXTURE19 0x84D3
-#define GL_TEXTURE20 0x84D4
-#define GL_TEXTURE21 0x84D5
-#define GL_TEXTURE22 0x84D6
-#define GL_TEXTURE23 0x84D7
-#define GL_TEXTURE24 0x84D8
-#define GL_TEXTURE25 0x84D9
-#define GL_TEXTURE26 0x84DA
-#define GL_TEXTURE27 0x84DB
-#define GL_TEXTURE28 0x84DC
-#define GL_TEXTURE29 0x84DD
-#define GL_TEXTURE30 0x84DE
-#define GL_TEXTURE31 0x84DF
-#define GL_ACTIVE_TEXTURE 0x84E0
-#define GL_MULTISAMPLE 0x809D
-#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
-#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
-#define GL_SAMPLE_COVERAGE 0x80A0
-#define GL_SAMPLE_BUFFERS 0x80A8
-#define GL_SAMPLES 0x80A9
-#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
-#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
-#define GL_TEXTURE_CUBE_MAP 0x8513
-#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
-#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
-#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
-#define GL_COMPRESSED_RGB 0x84ED
-#define GL_COMPRESSED_RGBA 0x84EE
-#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
-#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
-#define GL_TEXTURE_COMPRESSED 0x86A1
-#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
-#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
-#define GL_CLAMP_TO_BORDER 0x812D
-#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
-#define GL_MAX_TEXTURE_UNITS 0x84E2
-#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
-#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
-#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
-#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
-#define GL_MULTISAMPLE_BIT 0x20000000
-#define GL_NORMAL_MAP 0x8511
-#define GL_REFLECTION_MAP 0x8512
-#define GL_COMPRESSED_ALPHA 0x84E9
-#define GL_COMPRESSED_LUMINANCE 0x84EA
-#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
-#define GL_COMPRESSED_INTENSITY 0x84EC
-#define GL_COMBINE 0x8570
-#define GL_COMBINE_RGB 0x8571
-#define GL_COMBINE_ALPHA 0x8572
-#define GL_SOURCE0_RGB 0x8580
-#define GL_SOURCE1_RGB 0x8581
-#define GL_SOURCE2_RGB 0x8582
-#define GL_SOURCE0_ALPHA 0x8588
-#define GL_SOURCE1_ALPHA 0x8589
-#define GL_SOURCE2_ALPHA 0x858A
-#define GL_OPERAND0_RGB 0x8590
-#define GL_OPERAND1_RGB 0x8591
-#define GL_OPERAND2_RGB 0x8592
-#define GL_OPERAND0_ALPHA 0x8598
-#define GL_OPERAND1_ALPHA 0x8599
-#define GL_OPERAND2_ALPHA 0x859A
-#define GL_RGB_SCALE 0x8573
-#define GL_ADD_SIGNED 0x8574
-#define GL_INTERPOLATE 0x8575
-#define GL_SUBTRACT 0x84E7
-#define GL_CONSTANT 0x8576
-#define GL_PRIMARY_COLOR 0x8577
-#define GL_PREVIOUS 0x8578
-#define GL_DOT3_RGB 0x86AE
-#define GL_DOT3_RGBA 0x86AF
-#define GL_BLEND_DST_RGB 0x80C8
-#define GL_BLEND_SRC_RGB 0x80C9
-#define GL_BLEND_DST_ALPHA 0x80CA
-#define GL_BLEND_SRC_ALPHA 0x80CB
-#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
-#define GL_DEPTH_COMPONENT16 0x81A5
-#define GL_DEPTH_COMPONENT24 0x81A6
-#define GL_DEPTH_COMPONENT32 0x81A7
-#define GL_MIRRORED_REPEAT 0x8370
-#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
-#define GL_TEXTURE_LOD_BIAS 0x8501
-#define GL_INCR_WRAP 0x8507
-#define GL_DECR_WRAP 0x8508
-#define GL_TEXTURE_DEPTH_SIZE 0x884A
-#define GL_TEXTURE_COMPARE_MODE 0x884C
-#define GL_TEXTURE_COMPARE_FUNC 0x884D
-#define GL_POINT_SIZE_MIN 0x8126
-#define GL_POINT_SIZE_MAX 0x8127
-#define GL_POINT_DISTANCE_ATTENUATION 0x8129
-#define GL_GENERATE_MIPMAP 0x8191
-#define GL_GENERATE_MIPMAP_HINT 0x8192
-#define GL_FOG_COORDINATE_SOURCE 0x8450
-#define GL_FOG_COORDINATE 0x8451
-#define GL_FRAGMENT_DEPTH 0x8452
-#define GL_CURRENT_FOG_COORDINATE 0x8453
-#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
-#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
-#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
-#define GL_FOG_COORDINATE_ARRAY 0x8457
-#define GL_COLOR_SUM 0x8458
-#define GL_CURRENT_SECONDARY_COLOR 0x8459
-#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
-#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
-#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
-#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
-#define GL_SECONDARY_COLOR_ARRAY 0x845E
-#define GL_TEXTURE_FILTER_CONTROL 0x8500
-#define GL_DEPTH_TEXTURE_MODE 0x884B
-#define GL_COMPARE_R_TO_TEXTURE 0x884E
-#define GL_BLEND_COLOR 0x8005
-#define GL_BLEND_EQUATION 0x8009
-#define GL_CONSTANT_COLOR 0x8001
-#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
-#define GL_CONSTANT_ALPHA 0x8003
-#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
-#define GL_FUNC_ADD 0x8006
-#define GL_FUNC_REVERSE_SUBTRACT 0x800B
-#define GL_FUNC_SUBTRACT 0x800A
-#define GL_MIN 0x8007
-#define GL_MAX 0x8008
-#define GL_BUFFER_SIZE 0x8764
-#define GL_BUFFER_USAGE 0x8765
-#define GL_QUERY_COUNTER_BITS 0x8864
-#define GL_CURRENT_QUERY 0x8865
-#define GL_QUERY_RESULT 0x8866
-#define GL_QUERY_RESULT_AVAILABLE 0x8867
-#define GL_ARRAY_BUFFER 0x8892
-#define GL_ELEMENT_ARRAY_BUFFER 0x8893
-#define GL_ARRAY_BUFFER_BINDING 0x8894
-#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
-#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
-#define GL_READ_ONLY 0x88B8
-#define GL_WRITE_ONLY 0x88B9
-#define GL_READ_WRITE 0x88BA
-#define GL_BUFFER_ACCESS 0x88BB
-#define GL_BUFFER_MAPPED 0x88BC
-#define GL_BUFFER_MAP_POINTER 0x88BD
-#define GL_STREAM_DRAW 0x88E0
-#define GL_STREAM_READ 0x88E1
-#define GL_STREAM_COPY 0x88E2
-#define GL_STATIC_DRAW 0x88E4
-#define GL_STATIC_READ 0x88E5
-#define GL_STATIC_COPY 0x88E6
-#define GL_DYNAMIC_DRAW 0x88E8
-#define GL_DYNAMIC_READ 0x88E9
-#define GL_DYNAMIC_COPY 0x88EA
-#define GL_SAMPLES_PASSED 0x8914
-#define GL_SRC1_ALPHA 0x8589
-#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
-#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
-#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
-#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
-#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
-#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
-#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
-#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
-#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
-#define GL_FOG_COORD_SRC 0x8450
-#define GL_FOG_COORD 0x8451
-#define GL_CURRENT_FOG_COORD 0x8453
-#define GL_FOG_COORD_ARRAY_TYPE 0x8454
-#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
-#define GL_FOG_COORD_ARRAY_POINTER 0x8456
-#define GL_FOG_COORD_ARRAY 0x8457
-#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
-#define GL_SRC0_RGB 0x8580
-#define GL_SRC1_RGB 0x8581
-#define GL_SRC2_RGB 0x8582
-#define GL_SRC0_ALPHA 0x8588
-#define GL_SRC2_ALPHA 0x858A
-#define GL_BLEND_EQUATION_RGB 0x8009
-#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
-#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
-#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
-#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
-#define GL_CURRENT_VERTEX_ATTRIB 0x8626
-#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
-#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
-#define GL_STENCIL_BACK_FUNC 0x8800
-#define GL_STENCIL_BACK_FAIL 0x8801
-#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
-#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
-#define GL_MAX_DRAW_BUFFERS 0x8824
-#define GL_DRAW_BUFFER0 0x8825
-#define GL_DRAW_BUFFER1 0x8826
-#define GL_DRAW_BUFFER2 0x8827
-#define GL_DRAW_BUFFER3 0x8828
-#define GL_DRAW_BUFFER4 0x8829
-#define GL_DRAW_BUFFER5 0x882A
-#define GL_DRAW_BUFFER6 0x882B
-#define GL_DRAW_BUFFER7 0x882C
-#define GL_DRAW_BUFFER8 0x882D
-#define GL_DRAW_BUFFER9 0x882E
-#define GL_DRAW_BUFFER10 0x882F
-#define GL_DRAW_BUFFER11 0x8830
-#define GL_DRAW_BUFFER12 0x8831
-#define GL_DRAW_BUFFER13 0x8832
-#define GL_DRAW_BUFFER14 0x8833
-#define GL_DRAW_BUFFER15 0x8834
-#define GL_BLEND_EQUATION_ALPHA 0x883D
-#define GL_MAX_VERTEX_ATTRIBS 0x8869
-#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
-#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
-#define GL_FRAGMENT_SHADER 0x8B30
-#define GL_VERTEX_SHADER 0x8B31
-#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
-#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
-#define GL_MAX_VARYING_FLOATS 0x8B4B
-#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
-#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
-#define GL_SHADER_TYPE 0x8B4F
-#define GL_FLOAT_VEC2 0x8B50
-#define GL_FLOAT_VEC3 0x8B51
-#define GL_FLOAT_VEC4 0x8B52
-#define GL_INT_VEC2 0x8B53
-#define GL_INT_VEC3 0x8B54
-#define GL_INT_VEC4 0x8B55
-#define GL_BOOL 0x8B56
-#define GL_BOOL_VEC2 0x8B57
-#define GL_BOOL_VEC3 0x8B58
-#define GL_BOOL_VEC4 0x8B59
-#define GL_FLOAT_MAT2 0x8B5A
-#define GL_FLOAT_MAT3 0x8B5B
-#define GL_FLOAT_MAT4 0x8B5C
-#define GL_SAMPLER_1D 0x8B5D
-#define GL_SAMPLER_2D 0x8B5E
-#define GL_SAMPLER_3D 0x8B5F
-#define GL_SAMPLER_CUBE 0x8B60
-#define GL_SAMPLER_1D_SHADOW 0x8B61
-#define GL_SAMPLER_2D_SHADOW 0x8B62
-#define GL_DELETE_STATUS 0x8B80
-#define GL_COMPILE_STATUS 0x8B81
-#define GL_LINK_STATUS 0x8B82
-#define GL_VALIDATE_STATUS 0x8B83
-#define GL_INFO_LOG_LENGTH 0x8B84
-#define GL_ATTACHED_SHADERS 0x8B85
-#define GL_ACTIVE_UNIFORMS 0x8B86
-#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
-#define GL_SHADER_SOURCE_LENGTH 0x8B88
-#define GL_ACTIVE_ATTRIBUTES 0x8B89
-#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
-#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
-#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
-#define GL_CURRENT_PROGRAM 0x8B8D
-#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
-#define GL_LOWER_LEFT 0x8CA1
-#define GL_UPPER_LEFT 0x8CA2
-#define GL_STENCIL_BACK_REF 0x8CA3
-#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
-#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
-#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
-#define GL_POINT_SPRITE 0x8861
-#define GL_COORD_REPLACE 0x8862
-#define GL_MAX_TEXTURE_COORDS 0x8871
-#define GL_PIXEL_PACK_BUFFER 0x88EB
-#define GL_PIXEL_UNPACK_BUFFER 0x88EC
-#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
-#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
-#define GL_FLOAT_MAT2x3 0x8B65
-#define GL_FLOAT_MAT2x4 0x8B66
-#define GL_FLOAT_MAT3x2 0x8B67
-#define GL_FLOAT_MAT3x4 0x8B68
-#define GL_FLOAT_MAT4x2 0x8B69
-#define GL_FLOAT_MAT4x3 0x8B6A
-#define GL_SRGB 0x8C40
-#define GL_SRGB8 0x8C41
-#define GL_SRGB_ALPHA 0x8C42
-#define GL_SRGB8_ALPHA8 0x8C43
-#define GL_COMPRESSED_SRGB 0x8C48
-#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
-#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
-#define GL_SLUMINANCE_ALPHA 0x8C44
-#define GL_SLUMINANCE8_ALPHA8 0x8C45
-#define GL_SLUMINANCE 0x8C46
-#define GL_SLUMINANCE8 0x8C47
-#define GL_COMPRESSED_SLUMINANCE 0x8C4A
-#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
-#define GL_COMPARE_REF_TO_TEXTURE 0x884E
-#define GL_CLIP_DISTANCE0 0x3000
-#define GL_CLIP_DISTANCE1 0x3001
-#define GL_CLIP_DISTANCE2 0x3002
-#define GL_CLIP_DISTANCE3 0x3003
-#define GL_CLIP_DISTANCE4 0x3004
-#define GL_CLIP_DISTANCE5 0x3005
-#define GL_CLIP_DISTANCE6 0x3006
-#define GL_CLIP_DISTANCE7 0x3007
-#define GL_MAX_CLIP_DISTANCES 0x0D32
-#define GL_MAJOR_VERSION 0x821B
-#define GL_MINOR_VERSION 0x821C
-#define GL_NUM_EXTENSIONS 0x821D
-#define GL_CONTEXT_FLAGS 0x821E
-#define GL_COMPRESSED_RED 0x8225
-#define GL_COMPRESSED_RG 0x8226
-#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
-#define GL_RGBA32F 0x8814
-#define GL_RGB32F 0x8815
-#define GL_RGBA16F 0x881A
-#define GL_RGB16F 0x881B
-#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
-#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
-#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
-#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
-#define GL_CLAMP_READ_COLOR 0x891C
-#define GL_FIXED_ONLY 0x891D
-#define GL_MAX_VARYING_COMPONENTS 0x8B4B
-#define GL_TEXTURE_1D_ARRAY 0x8C18
-#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
-#define GL_TEXTURE_2D_ARRAY 0x8C1A
-#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
-#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
-#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
-#define GL_R11F_G11F_B10F 0x8C3A
-#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
-#define GL_RGB9_E5 0x8C3D
-#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
-#define GL_TEXTURE_SHARED_SIZE 0x8C3F
-#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
-#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
-#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
-#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
-#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
-#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
-#define GL_PRIMITIVES_GENERATED 0x8C87
-#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
-#define GL_RASTERIZER_DISCARD 0x8C89
-#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
-#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
-#define GL_INTERLEAVED_ATTRIBS 0x8C8C
-#define GL_SEPARATE_ATTRIBS 0x8C8D
-#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
-#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
-#define GL_RGBA32UI 0x8D70
-#define GL_RGB32UI 0x8D71
-#define GL_RGBA16UI 0x8D76
-#define GL_RGB16UI 0x8D77
-#define GL_RGBA8UI 0x8D7C
-#define GL_RGB8UI 0x8D7D
-#define GL_RGBA32I 0x8D82
-#define GL_RGB32I 0x8D83
-#define GL_RGBA16I 0x8D88
-#define GL_RGB16I 0x8D89
-#define GL_RGBA8I 0x8D8E
-#define GL_RGB8I 0x8D8F
-#define GL_RED_INTEGER 0x8D94
-#define GL_GREEN_INTEGER 0x8D95
-#define GL_BLUE_INTEGER 0x8D96
-#define GL_RGB_INTEGER 0x8D98
-#define GL_RGBA_INTEGER 0x8D99
-#define GL_BGR_INTEGER 0x8D9A
-#define GL_BGRA_INTEGER 0x8D9B
-#define GL_SAMPLER_1D_ARRAY 0x8DC0
-#define GL_SAMPLER_2D_ARRAY 0x8DC1
-#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
-#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
-#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
-#define GL_UNSIGNED_INT_VEC2 0x8DC6
-#define GL_UNSIGNED_INT_VEC3 0x8DC7
-#define GL_UNSIGNED_INT_VEC4 0x8DC8
-#define GL_INT_SAMPLER_1D 0x8DC9
-#define GL_INT_SAMPLER_2D 0x8DCA
-#define GL_INT_SAMPLER_3D 0x8DCB
-#define GL_INT_SAMPLER_CUBE 0x8DCC
-#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
-#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
-#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
-#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
-#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
-#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
-#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
-#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
-#define GL_QUERY_WAIT 0x8E13
-#define GL_QUERY_NO_WAIT 0x8E14
-#define GL_QUERY_BY_REGION_WAIT 0x8E15
-#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
-#define GL_BUFFER_ACCESS_FLAGS 0x911F
-#define GL_BUFFER_MAP_LENGTH 0x9120
-#define GL_BUFFER_MAP_OFFSET 0x9121
-#define GL_DEPTH_COMPONENT32F 0x8CAC
-#define GL_DEPTH32F_STENCIL8 0x8CAD
-#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
-#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
-#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
-#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
-#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
-#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
-#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
-#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
-#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
-#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
-#define GL_FRAMEBUFFER_DEFAULT 0x8218
-#define GL_FRAMEBUFFER_UNDEFINED 0x8219
-#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
-#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
-#define GL_DEPTH_STENCIL 0x84F9
-#define GL_UNSIGNED_INT_24_8 0x84FA
-#define GL_DEPTH24_STENCIL8 0x88F0
-#define GL_TEXTURE_STENCIL_SIZE 0x88F1
-#define GL_TEXTURE_RED_TYPE 0x8C10
-#define GL_TEXTURE_GREEN_TYPE 0x8C11
-#define GL_TEXTURE_BLUE_TYPE 0x8C12
-#define GL_TEXTURE_ALPHA_TYPE 0x8C13
-#define GL_TEXTURE_DEPTH_TYPE 0x8C16
-#define GL_UNSIGNED_NORMALIZED 0x8C17
-#define GL_FRAMEBUFFER_BINDING 0x8CA6
-#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
-#define GL_RENDERBUFFER_BINDING 0x8CA7
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
-#define GL_RENDERBUFFER_SAMPLES 0x8CAB
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
-#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
-#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
-#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
-#define GL_COLOR_ATTACHMENT0 0x8CE0
-#define GL_COLOR_ATTACHMENT1 0x8CE1
-#define GL_COLOR_ATTACHMENT2 0x8CE2
-#define GL_COLOR_ATTACHMENT3 0x8CE3
-#define GL_COLOR_ATTACHMENT4 0x8CE4
-#define GL_COLOR_ATTACHMENT5 0x8CE5
-#define GL_COLOR_ATTACHMENT6 0x8CE6
-#define GL_COLOR_ATTACHMENT7 0x8CE7
-#define GL_COLOR_ATTACHMENT8 0x8CE8
-#define GL_COLOR_ATTACHMENT9 0x8CE9
-#define GL_COLOR_ATTACHMENT10 0x8CEA
-#define GL_COLOR_ATTACHMENT11 0x8CEB
-#define GL_COLOR_ATTACHMENT12 0x8CEC
-#define GL_COLOR_ATTACHMENT13 0x8CED
-#define GL_COLOR_ATTACHMENT14 0x8CEE
-#define GL_COLOR_ATTACHMENT15 0x8CEF
-#define GL_COLOR_ATTACHMENT16 0x8CF0
-#define GL_COLOR_ATTACHMENT17 0x8CF1
-#define GL_COLOR_ATTACHMENT18 0x8CF2
-#define GL_COLOR_ATTACHMENT19 0x8CF3
-#define GL_COLOR_ATTACHMENT20 0x8CF4
-#define GL_COLOR_ATTACHMENT21 0x8CF5
-#define GL_COLOR_ATTACHMENT22 0x8CF6
-#define GL_COLOR_ATTACHMENT23 0x8CF7
-#define GL_COLOR_ATTACHMENT24 0x8CF8
-#define GL_COLOR_ATTACHMENT25 0x8CF9
-#define GL_COLOR_ATTACHMENT26 0x8CFA
-#define GL_COLOR_ATTACHMENT27 0x8CFB
-#define GL_COLOR_ATTACHMENT28 0x8CFC
-#define GL_COLOR_ATTACHMENT29 0x8CFD
-#define GL_COLOR_ATTACHMENT30 0x8CFE
-#define GL_COLOR_ATTACHMENT31 0x8CFF
-#define GL_DEPTH_ATTACHMENT 0x8D00
-#define GL_STENCIL_ATTACHMENT 0x8D20
-#define GL_FRAMEBUFFER 0x8D40
-#define GL_RENDERBUFFER 0x8D41
-#define GL_RENDERBUFFER_WIDTH 0x8D42
-#define GL_RENDERBUFFER_HEIGHT 0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
-#define GL_STENCIL_INDEX1 0x8D46
-#define GL_STENCIL_INDEX4 0x8D47
-#define GL_STENCIL_INDEX8 0x8D48
-#define GL_STENCIL_INDEX16 0x8D49
-#define GL_RENDERBUFFER_RED_SIZE 0x8D50
-#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
-#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
-#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
-#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
-#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
-#define GL_MAX_SAMPLES 0x8D57
-#define GL_INDEX 0x8222
-#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
-#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
-#define GL_FRAMEBUFFER_SRGB 0x8DB9
-#define GL_HALF_FLOAT 0x140B
-#define GL_MAP_READ_BIT 0x0001
-#define GL_MAP_WRITE_BIT 0x0002
-#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
-#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
-#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
-#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
-#define GL_COMPRESSED_RED_RGTC1 0x8DBB
-#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
-#define GL_COMPRESSED_RG_RGTC2 0x8DBD
-#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
-#define GL_RG 0x8227
-#define GL_RG_INTEGER 0x8228
-#define GL_R8 0x8229
-#define GL_R16 0x822A
-#define GL_RG8 0x822B
-#define GL_RG16 0x822C
-#define GL_R16F 0x822D
-#define GL_R32F 0x822E
-#define GL_RG16F 0x822F
-#define GL_RG32F 0x8230
-#define GL_R8I 0x8231
-#define GL_R8UI 0x8232
-#define GL_R16I 0x8233
-#define GL_R16UI 0x8234
-#define GL_R32I 0x8235
-#define GL_R32UI 0x8236
-#define GL_RG8I 0x8237
-#define GL_RG8UI 0x8238
-#define GL_RG16I 0x8239
-#define GL_RG16UI 0x823A
-#define GL_RG32I 0x823B
-#define GL_RG32UI 0x823C
-#define GL_VERTEX_ARRAY_BINDING 0x85B5
-#define GL_CLAMP_VERTEX_COLOR 0x891A
-#define GL_CLAMP_FRAGMENT_COLOR 0x891B
-#define GL_ALPHA_INTEGER 0x8D97
-#define GL_SAMPLER_2D_RECT 0x8B63
-#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
-#define GL_SAMPLER_BUFFER 0x8DC2
-#define GL_INT_SAMPLER_2D_RECT 0x8DCD
-#define GL_INT_SAMPLER_BUFFER 0x8DD0
-#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
-#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
-#define GL_TEXTURE_BUFFER 0x8C2A
-#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
-#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
-#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
-#define GL_TEXTURE_RECTANGLE 0x84F5
-#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
-#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
-#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
-#define GL_R8_SNORM 0x8F94
-#define GL_RG8_SNORM 0x8F95
-#define GL_RGB8_SNORM 0x8F96
-#define GL_RGBA8_SNORM 0x8F97
-#define GL_R16_SNORM 0x8F98
-#define GL_RG16_SNORM 0x8F99
-#define GL_RGB16_SNORM 0x8F9A
-#define GL_RGBA16_SNORM 0x8F9B
-#define GL_SIGNED_NORMALIZED 0x8F9C
-#define GL_PRIMITIVE_RESTART 0x8F9D
-#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
-#define GL_COPY_READ_BUFFER 0x8F36
-#define GL_COPY_WRITE_BUFFER 0x8F37
-#define GL_UNIFORM_BUFFER 0x8A11
-#define GL_UNIFORM_BUFFER_BINDING 0x8A28
-#define GL_UNIFORM_BUFFER_START 0x8A29
-#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
-#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
-#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
-#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
-#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
-#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
-#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
-#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
-#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
-#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
-#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
-#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
-#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
-#define GL_UNIFORM_TYPE 0x8A37
-#define GL_UNIFORM_SIZE 0x8A38
-#define GL_UNIFORM_NAME_LENGTH 0x8A39
-#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
-#define GL_UNIFORM_OFFSET 0x8A3B
-#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
-#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
-#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
-#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
-#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
-#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
-#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
-#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
-#define GL_INVALID_INDEX 0xFFFFFFFF
-#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
-#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
-#define GL_LINES_ADJACENCY 0x000A
-#define GL_LINE_STRIP_ADJACENCY 0x000B
-#define GL_TRIANGLES_ADJACENCY 0x000C
-#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
-#define GL_PROGRAM_POINT_SIZE 0x8642
-#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
-#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
-#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
-#define GL_GEOMETRY_SHADER 0x8DD9
-#define GL_GEOMETRY_VERTICES_OUT 0x8916
-#define GL_GEOMETRY_INPUT_TYPE 0x8917
-#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
-#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
-#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
-#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
-#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
-#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
-#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
-#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
-#define GL_CONTEXT_PROFILE_MASK 0x9126
-#define GL_DEPTH_CLAMP 0x864F
-#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
-#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
-#define GL_LAST_VERTEX_CONVENTION 0x8E4E
-#define GL_PROVOKING_VERTEX 0x8E4F
-#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
-#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
-#define GL_OBJECT_TYPE 0x9112
-#define GL_SYNC_CONDITION 0x9113
-#define GL_SYNC_STATUS 0x9114
-#define GL_SYNC_FLAGS 0x9115
-#define GL_SYNC_FENCE 0x9116
-#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
-#define GL_UNSIGNALED 0x9118
-#define GL_SIGNALED 0x9119
-#define GL_ALREADY_SIGNALED 0x911A
-#define GL_TIMEOUT_EXPIRED 0x911B
-#define GL_CONDITION_SATISFIED 0x911C
-#define GL_WAIT_FAILED 0x911D
-#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
-#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
-#define GL_SAMPLE_POSITION 0x8E50
-#define GL_SAMPLE_MASK 0x8E51
-#define GL_SAMPLE_MASK_VALUE 0x8E52
-#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
-#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
-#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
-#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
-#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
-#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
-#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
-#define GL_TEXTURE_SAMPLES 0x9106
-#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
-#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
-#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
-#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
-#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
-#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
-#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
-#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
-#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
-#define GL_MAX_INTEGER_SAMPLES 0x9110
-#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
-#define GL_SRC1_COLOR 0x88F9
-#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
-#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
-#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
-#define GL_ANY_SAMPLES_PASSED 0x8C2F
-#define GL_SAMPLER_BINDING 0x8919
-#define GL_RGB10_A2UI 0x906F
-#define GL_TEXTURE_SWIZZLE_R 0x8E42
-#define GL_TEXTURE_SWIZZLE_G 0x8E43
-#define GL_TEXTURE_SWIZZLE_B 0x8E44
-#define GL_TEXTURE_SWIZZLE_A 0x8E45
-#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
-#define GL_TIME_ELAPSED 0x88BF
-#define GL_TIMESTAMP 0x8E28
-#define GL_INT_2_10_10_10_REV 0x8D9F
-#ifndef GL_VERSION_1_0
-#define GL_VERSION_1_0 1
-GLAPI int GLAD_GL_VERSION_1_0;
-typedef void (APIENTRYP PFNGLCULLFACEPROC)(GLenum mode);
-GLAPI PFNGLCULLFACEPROC glad_glCullFace;
-#define glCullFace glad_glCullFace
-typedef void (APIENTRYP PFNGLFRONTFACEPROC)(GLenum mode);
-GLAPI PFNGLFRONTFACEPROC glad_glFrontFace;
-#define glFrontFace glad_glFrontFace
-typedef void (APIENTRYP PFNGLHINTPROC)(GLenum target, GLenum mode);
-GLAPI PFNGLHINTPROC glad_glHint;
-#define glHint glad_glHint
-typedef void (APIENTRYP PFNGLLINEWIDTHPROC)(GLfloat width);
-GLAPI PFNGLLINEWIDTHPROC glad_glLineWidth;
-#define glLineWidth glad_glLineWidth
-typedef void (APIENTRYP PFNGLPOINTSIZEPROC)(GLfloat size);
-GLAPI PFNGLPOINTSIZEPROC glad_glPointSize;
-#define glPointSize glad_glPointSize
-typedef void (APIENTRYP PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
-GLAPI PFNGLPOLYGONMODEPROC glad_glPolygonMode;
-#define glPolygonMode glad_glPolygonMode
-typedef void (APIENTRYP PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLSCISSORPROC glad_glScissor;
-#define glScissor glad_glScissor
-typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
-GLAPI PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
-#define glTexParameterf glad_glTexParameterf
-typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat *params);
-GLAPI PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
-#define glTexParameterfv glad_glTexParameterfv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
-GLAPI PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
-#define glTexParameteri glad_glTexParameteri
-typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
-#define glTexParameteriv glad_glTexParameteriv
-typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
-#define glTexImage1D glad_glTexImage1D
-typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
-#define glTexImage2D glad_glTexImage2D
-typedef void (APIENTRYP PFNGLDRAWBUFFERPROC)(GLenum buf);
-GLAPI PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
-#define glDrawBuffer glad_glDrawBuffer
-typedef void (APIENTRYP PFNGLCLEARPROC)(GLbitfield mask);
-GLAPI PFNGLCLEARPROC glad_glClear;
-#define glClear glad_glClear
-typedef void (APIENTRYP PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLCLEARCOLORPROC glad_glClearColor;
-#define glClearColor glad_glClearColor
-typedef void (APIENTRYP PFNGLCLEARSTENCILPROC)(GLint s);
-GLAPI PFNGLCLEARSTENCILPROC glad_glClearStencil;
-#define glClearStencil glad_glClearStencil
-typedef void (APIENTRYP PFNGLCLEARDEPTHPROC)(GLdouble depth);
-GLAPI PFNGLCLEARDEPTHPROC glad_glClearDepth;
-#define glClearDepth glad_glClearDepth
-typedef void (APIENTRYP PFNGLSTENCILMASKPROC)(GLuint mask);
-GLAPI PFNGLSTENCILMASKPROC glad_glStencilMask;
-#define glStencilMask glad_glStencilMask
-typedef void (APIENTRYP PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-GLAPI PFNGLCOLORMASKPROC glad_glColorMask;
-#define glColorMask glad_glColorMask
-typedef void (APIENTRYP PFNGLDEPTHMASKPROC)(GLboolean flag);
-GLAPI PFNGLDEPTHMASKPROC glad_glDepthMask;
-#define glDepthMask glad_glDepthMask
-typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap);
-GLAPI PFNGLDISABLEPROC glad_glDisable;
-#define glDisable glad_glDisable
-typedef void (APIENTRYP PFNGLENABLEPROC)(GLenum cap);
-GLAPI PFNGLENABLEPROC glad_glEnable;
-#define glEnable glad_glEnable
-typedef void (APIENTRYP PFNGLFINISHPROC)(void);
-GLAPI PFNGLFINISHPROC glad_glFinish;
-#define glFinish glad_glFinish
-typedef void (APIENTRYP PFNGLFLUSHPROC)(void);
-GLAPI PFNGLFLUSHPROC glad_glFlush;
-#define glFlush glad_glFlush
-typedef void (APIENTRYP PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
-GLAPI PFNGLBLENDFUNCPROC glad_glBlendFunc;
-#define glBlendFunc glad_glBlendFunc
-typedef void (APIENTRYP PFNGLLOGICOPPROC)(GLenum opcode);
-GLAPI PFNGLLOGICOPPROC glad_glLogicOp;
-#define glLogicOp glad_glLogicOp
-typedef void (APIENTRYP PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
-GLAPI PFNGLSTENCILFUNCPROC glad_glStencilFunc;
-#define glStencilFunc glad_glStencilFunc
-typedef void (APIENTRYP PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
-GLAPI PFNGLSTENCILOPPROC glad_glStencilOp;
-#define glStencilOp glad_glStencilOp
-typedef void (APIENTRYP PFNGLDEPTHFUNCPROC)(GLenum func);
-GLAPI PFNGLDEPTHFUNCPROC glad_glDepthFunc;
-#define glDepthFunc glad_glDepthFunc
-typedef void (APIENTRYP PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLPIXELSTOREFPROC glad_glPixelStoref;
-#define glPixelStoref glad_glPixelStoref
-typedef void (APIENTRYP PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLPIXELSTOREIPROC glad_glPixelStorei;
-#define glPixelStorei glad_glPixelStorei
-typedef void (APIENTRYP PFNGLREADBUFFERPROC)(GLenum src);
-GLAPI PFNGLREADBUFFERPROC glad_glReadBuffer;
-#define glReadBuffer glad_glReadBuffer
-typedef void (APIENTRYP PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
-GLAPI PFNGLREADPIXELSPROC glad_glReadPixels;
-#define glReadPixels glad_glReadPixels
-typedef void (APIENTRYP PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean *data);
-GLAPI PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
-#define glGetBooleanv glad_glGetBooleanv
-typedef void (APIENTRYP PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble *data);
-GLAPI PFNGLGETDOUBLEVPROC glad_glGetDoublev;
-#define glGetDoublev glad_glGetDoublev
-typedef GLenum (APIENTRYP PFNGLGETERRORPROC)(void);
-GLAPI PFNGLGETERRORPROC glad_glGetError;
-#define glGetError glad_glGetError
-typedef void (APIENTRYP PFNGLGETFLOATVPROC)(GLenum pname, GLfloat *data);
-GLAPI PFNGLGETFLOATVPROC glad_glGetFloatv;
-#define glGetFloatv glad_glGetFloatv
-typedef void (APIENTRYP PFNGLGETINTEGERVPROC)(GLenum pname, GLint *data);
-GLAPI PFNGLGETINTEGERVPROC glad_glGetIntegerv;
-#define glGetIntegerv glad_glGetIntegerv
-typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC)(GLenum name);
-GLAPI PFNGLGETSTRINGPROC glad_glGetString;
-#define glGetString glad_glGetString
-typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
-GLAPI PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
-#define glGetTexImage glad_glGetTexImage
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
-#define glGetTexParameterfv glad_glGetTexParameterfv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
-#define glGetTexParameteriv glad_glGetTexParameteriv
-typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
-#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
-typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
-#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
-typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC)(GLenum cap);
-GLAPI PFNGLISENABLEDPROC glad_glIsEnabled;
-#define glIsEnabled glad_glIsEnabled
-typedef void (APIENTRYP PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f);
-GLAPI PFNGLDEPTHRANGEPROC glad_glDepthRange;
-#define glDepthRange glad_glDepthRange
-typedef void (APIENTRYP PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLVIEWPORTPROC glad_glViewport;
-#define glViewport glad_glViewport
-typedef void (APIENTRYP PFNGLNEWLISTPROC)(GLuint list, GLenum mode);
-GLAPI PFNGLNEWLISTPROC glad_glNewList;
-#define glNewList glad_glNewList
-typedef void (APIENTRYP PFNGLENDLISTPROC)(void);
-GLAPI PFNGLENDLISTPROC glad_glEndList;
-#define glEndList glad_glEndList
-typedef void (APIENTRYP PFNGLCALLLISTPROC)(GLuint list);
-GLAPI PFNGLCALLLISTPROC glad_glCallList;
-#define glCallList glad_glCallList
-typedef void (APIENTRYP PFNGLCALLLISTSPROC)(GLsizei n, GLenum type, const void *lists);
-GLAPI PFNGLCALLLISTSPROC glad_glCallLists;
-#define glCallLists glad_glCallLists
-typedef void (APIENTRYP PFNGLDELETELISTSPROC)(GLuint list, GLsizei range);
-GLAPI PFNGLDELETELISTSPROC glad_glDeleteLists;
-#define glDeleteLists glad_glDeleteLists
-typedef GLuint (APIENTRYP PFNGLGENLISTSPROC)(GLsizei range);
-GLAPI PFNGLGENLISTSPROC glad_glGenLists;
-#define glGenLists glad_glGenLists
-typedef void (APIENTRYP PFNGLLISTBASEPROC)(GLuint base);
-GLAPI PFNGLLISTBASEPROC glad_glListBase;
-#define glListBase glad_glListBase
-typedef void (APIENTRYP PFNGLBEGINPROC)(GLenum mode);
-GLAPI PFNGLBEGINPROC glad_glBegin;
-#define glBegin glad_glBegin
-typedef void (APIENTRYP PFNGLBITMAPPROC)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
-GLAPI PFNGLBITMAPPROC glad_glBitmap;
-#define glBitmap glad_glBitmap
-typedef void (APIENTRYP PFNGLCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
-GLAPI PFNGLCOLOR3BPROC glad_glColor3b;
-#define glColor3b glad_glColor3b
-typedef void (APIENTRYP PFNGLCOLOR3BVPROC)(const GLbyte *v);
-GLAPI PFNGLCOLOR3BVPROC glad_glColor3bv;
-#define glColor3bv glad_glColor3bv
-typedef void (APIENTRYP PFNGLCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
-GLAPI PFNGLCOLOR3DPROC glad_glColor3d;
-#define glColor3d glad_glColor3d
-typedef void (APIENTRYP PFNGLCOLOR3DVPROC)(const GLdouble *v);
-GLAPI PFNGLCOLOR3DVPROC glad_glColor3dv;
-#define glColor3dv glad_glColor3dv
-typedef void (APIENTRYP PFNGLCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
-GLAPI PFNGLCOLOR3FPROC glad_glColor3f;
-#define glColor3f glad_glColor3f
-typedef void (APIENTRYP PFNGLCOLOR3FVPROC)(const GLfloat *v);
-GLAPI PFNGLCOLOR3FVPROC glad_glColor3fv;
-#define glColor3fv glad_glColor3fv
-typedef void (APIENTRYP PFNGLCOLOR3IPROC)(GLint red, GLint green, GLint blue);
-GLAPI PFNGLCOLOR3IPROC glad_glColor3i;
-#define glColor3i glad_glColor3i
-typedef void (APIENTRYP PFNGLCOLOR3IVPROC)(const GLint *v);
-GLAPI PFNGLCOLOR3IVPROC glad_glColor3iv;
-#define glColor3iv glad_glColor3iv
-typedef void (APIENTRYP PFNGLCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
-GLAPI PFNGLCOLOR3SPROC glad_glColor3s;
-#define glColor3s glad_glColor3s
-typedef void (APIENTRYP PFNGLCOLOR3SVPROC)(const GLshort *v);
-GLAPI PFNGLCOLOR3SVPROC glad_glColor3sv;
-#define glColor3sv glad_glColor3sv
-typedef void (APIENTRYP PFNGLCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
-GLAPI PFNGLCOLOR3UBPROC glad_glColor3ub;
-#define glColor3ub glad_glColor3ub
-typedef void (APIENTRYP PFNGLCOLOR3UBVPROC)(const GLubyte *v);
-GLAPI PFNGLCOLOR3UBVPROC glad_glColor3ubv;
-#define glColor3ubv glad_glColor3ubv
-typedef void (APIENTRYP PFNGLCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
-GLAPI PFNGLCOLOR3UIPROC glad_glColor3ui;
-#define glColor3ui glad_glColor3ui
-typedef void (APIENTRYP PFNGLCOLOR3UIVPROC)(const GLuint *v);
-GLAPI PFNGLCOLOR3UIVPROC glad_glColor3uiv;
-#define glColor3uiv glad_glColor3uiv
-typedef void (APIENTRYP PFNGLCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
-GLAPI PFNGLCOLOR3USPROC glad_glColor3us;
-#define glColor3us glad_glColor3us
-typedef void (APIENTRYP PFNGLCOLOR3USVPROC)(const GLushort *v);
-GLAPI PFNGLCOLOR3USVPROC glad_glColor3usv;
-#define glColor3usv glad_glColor3usv
-typedef void (APIENTRYP PFNGLCOLOR4BPROC)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
-GLAPI PFNGLCOLOR4BPROC glad_glColor4b;
-#define glColor4b glad_glColor4b
-typedef void (APIENTRYP PFNGLCOLOR4BVPROC)(const GLbyte *v);
-GLAPI PFNGLCOLOR4BVPROC glad_glColor4bv;
-#define glColor4bv glad_glColor4bv
-typedef void (APIENTRYP PFNGLCOLOR4DPROC)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
-GLAPI PFNGLCOLOR4DPROC glad_glColor4d;
-#define glColor4d glad_glColor4d
-typedef void (APIENTRYP PFNGLCOLOR4DVPROC)(const GLdouble *v);
-GLAPI PFNGLCOLOR4DVPROC glad_glColor4dv;
-#define glColor4dv glad_glColor4dv
-typedef void (APIENTRYP PFNGLCOLOR4FPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLCOLOR4FPROC glad_glColor4f;
-#define glColor4f glad_glColor4f
-typedef void (APIENTRYP PFNGLCOLOR4FVPROC)(const GLfloat *v);
-GLAPI PFNGLCOLOR4FVPROC glad_glColor4fv;
-#define glColor4fv glad_glColor4fv
-typedef void (APIENTRYP PFNGLCOLOR4IPROC)(GLint red, GLint green, GLint blue, GLint alpha);
-GLAPI PFNGLCOLOR4IPROC glad_glColor4i;
-#define glColor4i glad_glColor4i
-typedef void (APIENTRYP PFNGLCOLOR4IVPROC)(const GLint *v);
-GLAPI PFNGLCOLOR4IVPROC glad_glColor4iv;
-#define glColor4iv glad_glColor4iv
-typedef void (APIENTRYP PFNGLCOLOR4SPROC)(GLshort red, GLshort green, GLshort blue, GLshort alpha);
-GLAPI PFNGLCOLOR4SPROC glad_glColor4s;
-#define glColor4s glad_glColor4s
-typedef void (APIENTRYP PFNGLCOLOR4SVPROC)(const GLshort *v);
-GLAPI PFNGLCOLOR4SVPROC glad_glColor4sv;
-#define glColor4sv glad_glColor4sv
-typedef void (APIENTRYP PFNGLCOLOR4UBPROC)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
-GLAPI PFNGLCOLOR4UBPROC glad_glColor4ub;
-#define glColor4ub glad_glColor4ub
-typedef void (APIENTRYP PFNGLCOLOR4UBVPROC)(const GLubyte *v);
-GLAPI PFNGLCOLOR4UBVPROC glad_glColor4ubv;
-#define glColor4ubv glad_glColor4ubv
-typedef void (APIENTRYP PFNGLCOLOR4UIPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha);
-GLAPI PFNGLCOLOR4UIPROC glad_glColor4ui;
-#define glColor4ui glad_glColor4ui
-typedef void (APIENTRYP PFNGLCOLOR4UIVPROC)(const GLuint *v);
-GLAPI PFNGLCOLOR4UIVPROC glad_glColor4uiv;
-#define glColor4uiv glad_glColor4uiv
-typedef void (APIENTRYP PFNGLCOLOR4USPROC)(GLushort red, GLushort green, GLushort blue, GLushort alpha);
-GLAPI PFNGLCOLOR4USPROC glad_glColor4us;
-#define glColor4us glad_glColor4us
-typedef void (APIENTRYP PFNGLCOLOR4USVPROC)(const GLushort *v);
-GLAPI PFNGLCOLOR4USVPROC glad_glColor4usv;
-#define glColor4usv glad_glColor4usv
-typedef void (APIENTRYP PFNGLEDGEFLAGPROC)(GLboolean flag);
-GLAPI PFNGLEDGEFLAGPROC glad_glEdgeFlag;
-#define glEdgeFlag glad_glEdgeFlag
-typedef void (APIENTRYP PFNGLEDGEFLAGVPROC)(const GLboolean *flag);
-GLAPI PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
-#define glEdgeFlagv glad_glEdgeFlagv
-typedef void (APIENTRYP PFNGLENDPROC)(void);
-GLAPI PFNGLENDPROC glad_glEnd;
-#define glEnd glad_glEnd
-typedef void (APIENTRYP PFNGLINDEXDPROC)(GLdouble c);
-GLAPI PFNGLINDEXDPROC glad_glIndexd;
-#define glIndexd glad_glIndexd
-typedef void (APIENTRYP PFNGLINDEXDVPROC)(const GLdouble *c);
-GLAPI PFNGLINDEXDVPROC glad_glIndexdv;
-#define glIndexdv glad_glIndexdv
-typedef void (APIENTRYP PFNGLINDEXFPROC)(GLfloat c);
-GLAPI PFNGLINDEXFPROC glad_glIndexf;
-#define glIndexf glad_glIndexf
-typedef void (APIENTRYP PFNGLINDEXFVPROC)(const GLfloat *c);
-GLAPI PFNGLINDEXFVPROC glad_glIndexfv;
-#define glIndexfv glad_glIndexfv
-typedef void (APIENTRYP PFNGLINDEXIPROC)(GLint c);
-GLAPI PFNGLINDEXIPROC glad_glIndexi;
-#define glIndexi glad_glIndexi
-typedef void (APIENTRYP PFNGLINDEXIVPROC)(const GLint *c);
-GLAPI PFNGLINDEXIVPROC glad_glIndexiv;
-#define glIndexiv glad_glIndexiv
-typedef void (APIENTRYP PFNGLINDEXSPROC)(GLshort c);
-GLAPI PFNGLINDEXSPROC glad_glIndexs;
-#define glIndexs glad_glIndexs
-typedef void (APIENTRYP PFNGLINDEXSVPROC)(const GLshort *c);
-GLAPI PFNGLINDEXSVPROC glad_glIndexsv;
-#define glIndexsv glad_glIndexsv
-typedef void (APIENTRYP PFNGLNORMAL3BPROC)(GLbyte nx, GLbyte ny, GLbyte nz);
-GLAPI PFNGLNORMAL3BPROC glad_glNormal3b;
-#define glNormal3b glad_glNormal3b
-typedef void (APIENTRYP PFNGLNORMAL3BVPROC)(const GLbyte *v);
-GLAPI PFNGLNORMAL3BVPROC glad_glNormal3bv;
-#define glNormal3bv glad_glNormal3bv
-typedef void (APIENTRYP PFNGLNORMAL3DPROC)(GLdouble nx, GLdouble ny, GLdouble nz);
-GLAPI PFNGLNORMAL3DPROC glad_glNormal3d;
-#define glNormal3d glad_glNormal3d
-typedef void (APIENTRYP PFNGLNORMAL3DVPROC)(const GLdouble *v);
-GLAPI PFNGLNORMAL3DVPROC glad_glNormal3dv;
-#define glNormal3dv glad_glNormal3dv
-typedef void (APIENTRYP PFNGLNORMAL3FPROC)(GLfloat nx, GLfloat ny, GLfloat nz);
-GLAPI PFNGLNORMAL3FPROC glad_glNormal3f;
-#define glNormal3f glad_glNormal3f
-typedef void (APIENTRYP PFNGLNORMAL3FVPROC)(const GLfloat *v);
-GLAPI PFNGLNORMAL3FVPROC glad_glNormal3fv;
-#define glNormal3fv glad_glNormal3fv
-typedef void (APIENTRYP PFNGLNORMAL3IPROC)(GLint nx, GLint ny, GLint nz);
-GLAPI PFNGLNORMAL3IPROC glad_glNormal3i;
-#define glNormal3i glad_glNormal3i
-typedef void (APIENTRYP PFNGLNORMAL3IVPROC)(const GLint *v);
-GLAPI PFNGLNORMAL3IVPROC glad_glNormal3iv;
-#define glNormal3iv glad_glNormal3iv
-typedef void (APIENTRYP PFNGLNORMAL3SPROC)(GLshort nx, GLshort ny, GLshort nz);
-GLAPI PFNGLNORMAL3SPROC glad_glNormal3s;
-#define glNormal3s glad_glNormal3s
-typedef void (APIENTRYP PFNGLNORMAL3SVPROC)(const GLshort *v);
-GLAPI PFNGLNORMAL3SVPROC glad_glNormal3sv;
-#define glNormal3sv glad_glNormal3sv
-typedef void (APIENTRYP PFNGLRASTERPOS2DPROC)(GLdouble x, GLdouble y);
-GLAPI PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
-#define glRasterPos2d glad_glRasterPos2d
-typedef void (APIENTRYP PFNGLRASTERPOS2DVPROC)(const GLdouble *v);
-GLAPI PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
-#define glRasterPos2dv glad_glRasterPos2dv
-typedef void (APIENTRYP PFNGLRASTERPOS2FPROC)(GLfloat x, GLfloat y);
-GLAPI PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
-#define glRasterPos2f glad_glRasterPos2f
-typedef void (APIENTRYP PFNGLRASTERPOS2FVPROC)(const GLfloat *v);
-GLAPI PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
-#define glRasterPos2fv glad_glRasterPos2fv
-typedef void (APIENTRYP PFNGLRASTERPOS2IPROC)(GLint x, GLint y);
-GLAPI PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
-#define glRasterPos2i glad_glRasterPos2i
-typedef void (APIENTRYP PFNGLRASTERPOS2IVPROC)(const GLint *v);
-GLAPI PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
-#define glRasterPos2iv glad_glRasterPos2iv
-typedef void (APIENTRYP PFNGLRASTERPOS2SPROC)(GLshort x, GLshort y);
-GLAPI PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
-#define glRasterPos2s glad_glRasterPos2s
-typedef void (APIENTRYP PFNGLRASTERPOS2SVPROC)(const GLshort *v);
-GLAPI PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
-#define glRasterPos2sv glad_glRasterPos2sv
-typedef void (APIENTRYP PFNGLRASTERPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
-#define glRasterPos3d glad_glRasterPos3d
-typedef void (APIENTRYP PFNGLRASTERPOS3DVPROC)(const GLdouble *v);
-GLAPI PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
-#define glRasterPos3dv glad_glRasterPos3dv
-typedef void (APIENTRYP PFNGLRASTERPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
-#define glRasterPos3f glad_glRasterPos3f
-typedef void (APIENTRYP PFNGLRASTERPOS3FVPROC)(const GLfloat *v);
-GLAPI PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
-#define glRasterPos3fv glad_glRasterPos3fv
-typedef void (APIENTRYP PFNGLRASTERPOS3IPROC)(GLint x, GLint y, GLint z);
-GLAPI PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
-#define glRasterPos3i glad_glRasterPos3i
-typedef void (APIENTRYP PFNGLRASTERPOS3IVPROC)(const GLint *v);
-GLAPI PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
-#define glRasterPos3iv glad_glRasterPos3iv
-typedef void (APIENTRYP PFNGLRASTERPOS3SPROC)(GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
-#define glRasterPos3s glad_glRasterPos3s
-typedef void (APIENTRYP PFNGLRASTERPOS3SVPROC)(const GLshort *v);
-GLAPI PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
-#define glRasterPos3sv glad_glRasterPos3sv
-typedef void (APIENTRYP PFNGLRASTERPOS4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-GLAPI PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
-#define glRasterPos4d glad_glRasterPos4d
-typedef void (APIENTRYP PFNGLRASTERPOS4DVPROC)(const GLdouble *v);
-GLAPI PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
-#define glRasterPos4dv glad_glRasterPos4dv
-typedef void (APIENTRYP PFNGLRASTERPOS4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GLAPI PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
-#define glRasterPos4f glad_glRasterPos4f
-typedef void (APIENTRYP PFNGLRASTERPOS4FVPROC)(const GLfloat *v);
-GLAPI PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
-#define glRasterPos4fv glad_glRasterPos4fv
-typedef void (APIENTRYP PFNGLRASTERPOS4IPROC)(GLint x, GLint y, GLint z, GLint w);
-GLAPI PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
-#define glRasterPos4i glad_glRasterPos4i
-typedef void (APIENTRYP PFNGLRASTERPOS4IVPROC)(const GLint *v);
-GLAPI PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
-#define glRasterPos4iv glad_glRasterPos4iv
-typedef void (APIENTRYP PFNGLRASTERPOS4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
-GLAPI PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
-#define glRasterPos4s glad_glRasterPos4s
-typedef void (APIENTRYP PFNGLRASTERPOS4SVPROC)(const GLshort *v);
-GLAPI PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
-#define glRasterPos4sv glad_glRasterPos4sv
-typedef void (APIENTRYP PFNGLRECTDPROC)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
-GLAPI PFNGLRECTDPROC glad_glRectd;
-#define glRectd glad_glRectd
-typedef void (APIENTRYP PFNGLRECTDVPROC)(const GLdouble *v1, const GLdouble *v2);
-GLAPI PFNGLRECTDVPROC glad_glRectdv;
-#define glRectdv glad_glRectdv
-typedef void (APIENTRYP PFNGLRECTFPROC)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
-GLAPI PFNGLRECTFPROC glad_glRectf;
-#define glRectf glad_glRectf
-typedef void (APIENTRYP PFNGLRECTFVPROC)(const GLfloat *v1, const GLfloat *v2);
-GLAPI PFNGLRECTFVPROC glad_glRectfv;
-#define glRectfv glad_glRectfv
-typedef void (APIENTRYP PFNGLRECTIPROC)(GLint x1, GLint y1, GLint x2, GLint y2);
-GLAPI PFNGLRECTIPROC glad_glRecti;
-#define glRecti glad_glRecti
-typedef void (APIENTRYP PFNGLRECTIVPROC)(const GLint *v1, const GLint *v2);
-GLAPI PFNGLRECTIVPROC glad_glRectiv;
-#define glRectiv glad_glRectiv
-typedef void (APIENTRYP PFNGLRECTSPROC)(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
-GLAPI PFNGLRECTSPROC glad_glRects;
-#define glRects glad_glRects
-typedef void (APIENTRYP PFNGLRECTSVPROC)(const GLshort *v1, const GLshort *v2);
-GLAPI PFNGLRECTSVPROC glad_glRectsv;
-#define glRectsv glad_glRectsv
-typedef void (APIENTRYP PFNGLTEXCOORD1DPROC)(GLdouble s);
-GLAPI PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
-#define glTexCoord1d glad_glTexCoord1d
-typedef void (APIENTRYP PFNGLTEXCOORD1DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
-#define glTexCoord1dv glad_glTexCoord1dv
-typedef void (APIENTRYP PFNGLTEXCOORD1FPROC)(GLfloat s);
-GLAPI PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
-#define glTexCoord1f glad_glTexCoord1f
-typedef void (APIENTRYP PFNGLTEXCOORD1FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
-#define glTexCoord1fv glad_glTexCoord1fv
-typedef void (APIENTRYP PFNGLTEXCOORD1IPROC)(GLint s);
-GLAPI PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
-#define glTexCoord1i glad_glTexCoord1i
-typedef void (APIENTRYP PFNGLTEXCOORD1IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
-#define glTexCoord1iv glad_glTexCoord1iv
-typedef void (APIENTRYP PFNGLTEXCOORD1SPROC)(GLshort s);
-GLAPI PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
-#define glTexCoord1s glad_glTexCoord1s
-typedef void (APIENTRYP PFNGLTEXCOORD1SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
-#define glTexCoord1sv glad_glTexCoord1sv
-typedef void (APIENTRYP PFNGLTEXCOORD2DPROC)(GLdouble s, GLdouble t);
-GLAPI PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
-#define glTexCoord2d glad_glTexCoord2d
-typedef void (APIENTRYP PFNGLTEXCOORD2DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
-#define glTexCoord2dv glad_glTexCoord2dv
-typedef void (APIENTRYP PFNGLTEXCOORD2FPROC)(GLfloat s, GLfloat t);
-GLAPI PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
-#define glTexCoord2f glad_glTexCoord2f
-typedef void (APIENTRYP PFNGLTEXCOORD2FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
-#define glTexCoord2fv glad_glTexCoord2fv
-typedef void (APIENTRYP PFNGLTEXCOORD2IPROC)(GLint s, GLint t);
-GLAPI PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
-#define glTexCoord2i glad_glTexCoord2i
-typedef void (APIENTRYP PFNGLTEXCOORD2IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
-#define glTexCoord2iv glad_glTexCoord2iv
-typedef void (APIENTRYP PFNGLTEXCOORD2SPROC)(GLshort s, GLshort t);
-GLAPI PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
-#define glTexCoord2s glad_glTexCoord2s
-typedef void (APIENTRYP PFNGLTEXCOORD2SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
-#define glTexCoord2sv glad_glTexCoord2sv
-typedef void (APIENTRYP PFNGLTEXCOORD3DPROC)(GLdouble s, GLdouble t, GLdouble r);
-GLAPI PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
-#define glTexCoord3d glad_glTexCoord3d
-typedef void (APIENTRYP PFNGLTEXCOORD3DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
-#define glTexCoord3dv glad_glTexCoord3dv
-typedef void (APIENTRYP PFNGLTEXCOORD3FPROC)(GLfloat s, GLfloat t, GLfloat r);
-GLAPI PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
-#define glTexCoord3f glad_glTexCoord3f
-typedef void (APIENTRYP PFNGLTEXCOORD3FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
-#define glTexCoord3fv glad_glTexCoord3fv
-typedef void (APIENTRYP PFNGLTEXCOORD3IPROC)(GLint s, GLint t, GLint r);
-GLAPI PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
-#define glTexCoord3i glad_glTexCoord3i
-typedef void (APIENTRYP PFNGLTEXCOORD3IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
-#define glTexCoord3iv glad_glTexCoord3iv
-typedef void (APIENTRYP PFNGLTEXCOORD3SPROC)(GLshort s, GLshort t, GLshort r);
-GLAPI PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
-#define glTexCoord3s glad_glTexCoord3s
-typedef void (APIENTRYP PFNGLTEXCOORD3SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
-#define glTexCoord3sv glad_glTexCoord3sv
-typedef void (APIENTRYP PFNGLTEXCOORD4DPROC)(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-GLAPI PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
-#define glTexCoord4d glad_glTexCoord4d
-typedef void (APIENTRYP PFNGLTEXCOORD4DVPROC)(const GLdouble *v);
-GLAPI PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
-#define glTexCoord4dv glad_glTexCoord4dv
-typedef void (APIENTRYP PFNGLTEXCOORD4FPROC)(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-GLAPI PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
-#define glTexCoord4f glad_glTexCoord4f
-typedef void (APIENTRYP PFNGLTEXCOORD4FVPROC)(const GLfloat *v);
-GLAPI PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
-#define glTexCoord4fv glad_glTexCoord4fv
-typedef void (APIENTRYP PFNGLTEXCOORD4IPROC)(GLint s, GLint t, GLint r, GLint q);
-GLAPI PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
-#define glTexCoord4i glad_glTexCoord4i
-typedef void (APIENTRYP PFNGLTEXCOORD4IVPROC)(const GLint *v);
-GLAPI PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
-#define glTexCoord4iv glad_glTexCoord4iv
-typedef void (APIENTRYP PFNGLTEXCOORD4SPROC)(GLshort s, GLshort t, GLshort r, GLshort q);
-GLAPI PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
-#define glTexCoord4s glad_glTexCoord4s
-typedef void (APIENTRYP PFNGLTEXCOORD4SVPROC)(const GLshort *v);
-GLAPI PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
-#define glTexCoord4sv glad_glTexCoord4sv
-typedef void (APIENTRYP PFNGLVERTEX2DPROC)(GLdouble x, GLdouble y);
-GLAPI PFNGLVERTEX2DPROC glad_glVertex2d;
-#define glVertex2d glad_glVertex2d
-typedef void (APIENTRYP PFNGLVERTEX2DVPROC)(const GLdouble *v);
-GLAPI PFNGLVERTEX2DVPROC glad_glVertex2dv;
-#define glVertex2dv glad_glVertex2dv
-typedef void (APIENTRYP PFNGLVERTEX2FPROC)(GLfloat x, GLfloat y);
-GLAPI PFNGLVERTEX2FPROC glad_glVertex2f;
-#define glVertex2f glad_glVertex2f
-typedef void (APIENTRYP PFNGLVERTEX2FVPROC)(const GLfloat *v);
-GLAPI PFNGLVERTEX2FVPROC glad_glVertex2fv;
-#define glVertex2fv glad_glVertex2fv
-typedef void (APIENTRYP PFNGLVERTEX2IPROC)(GLint x, GLint y);
-GLAPI PFNGLVERTEX2IPROC glad_glVertex2i;
-#define glVertex2i glad_glVertex2i
-typedef void (APIENTRYP PFNGLVERTEX2IVPROC)(const GLint *v);
-GLAPI PFNGLVERTEX2IVPROC glad_glVertex2iv;
-#define glVertex2iv glad_glVertex2iv
-typedef void (APIENTRYP PFNGLVERTEX2SPROC)(GLshort x, GLshort y);
-GLAPI PFNGLVERTEX2SPROC glad_glVertex2s;
-#define glVertex2s glad_glVertex2s
-typedef void (APIENTRYP PFNGLVERTEX2SVPROC)(const GLshort *v);
-GLAPI PFNGLVERTEX2SVPROC glad_glVertex2sv;
-#define glVertex2sv glad_glVertex2sv
-typedef void (APIENTRYP PFNGLVERTEX3DPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLVERTEX3DPROC glad_glVertex3d;
-#define glVertex3d glad_glVertex3d
-typedef void (APIENTRYP PFNGLVERTEX3DVPROC)(const GLdouble *v);
-GLAPI PFNGLVERTEX3DVPROC glad_glVertex3dv;
-#define glVertex3dv glad_glVertex3dv
-typedef void (APIENTRYP PFNGLVERTEX3FPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLVERTEX3FPROC glad_glVertex3f;
-#define glVertex3f glad_glVertex3f
-typedef void (APIENTRYP PFNGLVERTEX3FVPROC)(const GLfloat *v);
-GLAPI PFNGLVERTEX3FVPROC glad_glVertex3fv;
-#define glVertex3fv glad_glVertex3fv
-typedef void (APIENTRYP PFNGLVERTEX3IPROC)(GLint x, GLint y, GLint z);
-GLAPI PFNGLVERTEX3IPROC glad_glVertex3i;
-#define glVertex3i glad_glVertex3i
-typedef void (APIENTRYP PFNGLVERTEX3IVPROC)(const GLint *v);
-GLAPI PFNGLVERTEX3IVPROC glad_glVertex3iv;
-#define glVertex3iv glad_glVertex3iv
-typedef void (APIENTRYP PFNGLVERTEX3SPROC)(GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLVERTEX3SPROC glad_glVertex3s;
-#define glVertex3s glad_glVertex3s
-typedef void (APIENTRYP PFNGLVERTEX3SVPROC)(const GLshort *v);
-GLAPI PFNGLVERTEX3SVPROC glad_glVertex3sv;
-#define glVertex3sv glad_glVertex3sv
-typedef void (APIENTRYP PFNGLVERTEX4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-GLAPI PFNGLVERTEX4DPROC glad_glVertex4d;
-#define glVertex4d glad_glVertex4d
-typedef void (APIENTRYP PFNGLVERTEX4DVPROC)(const GLdouble *v);
-GLAPI PFNGLVERTEX4DVPROC glad_glVertex4dv;
-#define glVertex4dv glad_glVertex4dv
-typedef void (APIENTRYP PFNGLVERTEX4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GLAPI PFNGLVERTEX4FPROC glad_glVertex4f;
-#define glVertex4f glad_glVertex4f
-typedef void (APIENTRYP PFNGLVERTEX4FVPROC)(const GLfloat *v);
-GLAPI PFNGLVERTEX4FVPROC glad_glVertex4fv;
-#define glVertex4fv glad_glVertex4fv
-typedef void (APIENTRYP PFNGLVERTEX4IPROC)(GLint x, GLint y, GLint z, GLint w);
-GLAPI PFNGLVERTEX4IPROC glad_glVertex4i;
-#define glVertex4i glad_glVertex4i
-typedef void (APIENTRYP PFNGLVERTEX4IVPROC)(const GLint *v);
-GLAPI PFNGLVERTEX4IVPROC glad_glVertex4iv;
-#define glVertex4iv glad_glVertex4iv
-typedef void (APIENTRYP PFNGLVERTEX4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
-GLAPI PFNGLVERTEX4SPROC glad_glVertex4s;
-#define glVertex4s glad_glVertex4s
-typedef void (APIENTRYP PFNGLVERTEX4SVPROC)(const GLshort *v);
-GLAPI PFNGLVERTEX4SVPROC glad_glVertex4sv;
-#define glVertex4sv glad_glVertex4sv
-typedef void (APIENTRYP PFNGLCLIPPLANEPROC)(GLenum plane, const GLdouble *equation);
-GLAPI PFNGLCLIPPLANEPROC glad_glClipPlane;
-#define glClipPlane glad_glClipPlane
-typedef void (APIENTRYP PFNGLCOLORMATERIALPROC)(GLenum face, GLenum mode);
-GLAPI PFNGLCOLORMATERIALPROC glad_glColorMaterial;
-#define glColorMaterial glad_glColorMaterial
-typedef void (APIENTRYP PFNGLFOGFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLFOGFPROC glad_glFogf;
-#define glFogf glad_glFogf
-typedef void (APIENTRYP PFNGLFOGFVPROC)(GLenum pname, const GLfloat *params);
-GLAPI PFNGLFOGFVPROC glad_glFogfv;
-#define glFogfv glad_glFogfv
-typedef void (APIENTRYP PFNGLFOGIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLFOGIPROC glad_glFogi;
-#define glFogi glad_glFogi
-typedef void (APIENTRYP PFNGLFOGIVPROC)(GLenum pname, const GLint *params);
-GLAPI PFNGLFOGIVPROC glad_glFogiv;
-#define glFogiv glad_glFogiv
-typedef void (APIENTRYP PFNGLLIGHTFPROC)(GLenum light, GLenum pname, GLfloat param);
-GLAPI PFNGLLIGHTFPROC glad_glLightf;
-#define glLightf glad_glLightf
-typedef void (APIENTRYP PFNGLLIGHTFVPROC)(GLenum light, GLenum pname, const GLfloat *params);
-GLAPI PFNGLLIGHTFVPROC glad_glLightfv;
-#define glLightfv glad_glLightfv
-typedef void (APIENTRYP PFNGLLIGHTIPROC)(GLenum light, GLenum pname, GLint param);
-GLAPI PFNGLLIGHTIPROC glad_glLighti;
-#define glLighti glad_glLighti
-typedef void (APIENTRYP PFNGLLIGHTIVPROC)(GLenum light, GLenum pname, const GLint *params);
-GLAPI PFNGLLIGHTIVPROC glad_glLightiv;
-#define glLightiv glad_glLightiv
-typedef void (APIENTRYP PFNGLLIGHTMODELFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLLIGHTMODELFPROC glad_glLightModelf;
-#define glLightModelf glad_glLightModelf
-typedef void (APIENTRYP PFNGLLIGHTMODELFVPROC)(GLenum pname, const GLfloat *params);
-GLAPI PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
-#define glLightModelfv glad_glLightModelfv
-typedef void (APIENTRYP PFNGLLIGHTMODELIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLLIGHTMODELIPROC glad_glLightModeli;
-#define glLightModeli glad_glLightModeli
-typedef void (APIENTRYP PFNGLLIGHTMODELIVPROC)(GLenum pname, const GLint *params);
-GLAPI PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
-#define glLightModeliv glad_glLightModeliv
-typedef void (APIENTRYP PFNGLLINESTIPPLEPROC)(GLint factor, GLushort pattern);
-GLAPI PFNGLLINESTIPPLEPROC glad_glLineStipple;
-#define glLineStipple glad_glLineStipple
-typedef void (APIENTRYP PFNGLMATERIALFPROC)(GLenum face, GLenum pname, GLfloat param);
-GLAPI PFNGLMATERIALFPROC glad_glMaterialf;
-#define glMaterialf glad_glMaterialf
-typedef void (APIENTRYP PFNGLMATERIALFVPROC)(GLenum face, GLenum pname, const GLfloat *params);
-GLAPI PFNGLMATERIALFVPROC glad_glMaterialfv;
-#define glMaterialfv glad_glMaterialfv
-typedef void (APIENTRYP PFNGLMATERIALIPROC)(GLenum face, GLenum pname, GLint param);
-GLAPI PFNGLMATERIALIPROC glad_glMateriali;
-#define glMateriali glad_glMateriali
-typedef void (APIENTRYP PFNGLMATERIALIVPROC)(GLenum face, GLenum pname, const GLint *params);
-GLAPI PFNGLMATERIALIVPROC glad_glMaterialiv;
-#define glMaterialiv glad_glMaterialiv
-typedef void (APIENTRYP PFNGLPOLYGONSTIPPLEPROC)(const GLubyte *mask);
-GLAPI PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
-#define glPolygonStipple glad_glPolygonStipple
-typedef void (APIENTRYP PFNGLSHADEMODELPROC)(GLenum mode);
-GLAPI PFNGLSHADEMODELPROC glad_glShadeModel;
-#define glShadeModel glad_glShadeModel
-typedef void (APIENTRYP PFNGLTEXENVFPROC)(GLenum target, GLenum pname, GLfloat param);
-GLAPI PFNGLTEXENVFPROC glad_glTexEnvf;
-#define glTexEnvf glad_glTexEnvf
-typedef void (APIENTRYP PFNGLTEXENVFVPROC)(GLenum target, GLenum pname, const GLfloat *params);
-GLAPI PFNGLTEXENVFVPROC glad_glTexEnvfv;
-#define glTexEnvfv glad_glTexEnvfv
-typedef void (APIENTRYP PFNGLTEXENVIPROC)(GLenum target, GLenum pname, GLint param);
-GLAPI PFNGLTEXENVIPROC glad_glTexEnvi;
-#define glTexEnvi glad_glTexEnvi
-typedef void (APIENTRYP PFNGLTEXENVIVPROC)(GLenum target, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXENVIVPROC glad_glTexEnviv;
-#define glTexEnviv glad_glTexEnviv
-typedef void (APIENTRYP PFNGLTEXGENDPROC)(GLenum coord, GLenum pname, GLdouble param);
-GLAPI PFNGLTEXGENDPROC glad_glTexGend;
-#define glTexGend glad_glTexGend
-typedef void (APIENTRYP PFNGLTEXGENDVPROC)(GLenum coord, GLenum pname, const GLdouble *params);
-GLAPI PFNGLTEXGENDVPROC glad_glTexGendv;
-#define glTexGendv glad_glTexGendv
-typedef void (APIENTRYP PFNGLTEXGENFPROC)(GLenum coord, GLenum pname, GLfloat param);
-GLAPI PFNGLTEXGENFPROC glad_glTexGenf;
-#define glTexGenf glad_glTexGenf
-typedef void (APIENTRYP PFNGLTEXGENFVPROC)(GLenum coord, GLenum pname, const GLfloat *params);
-GLAPI PFNGLTEXGENFVPROC glad_glTexGenfv;
-#define glTexGenfv glad_glTexGenfv
-typedef void (APIENTRYP PFNGLTEXGENIPROC)(GLenum coord, GLenum pname, GLint param);
-GLAPI PFNGLTEXGENIPROC glad_glTexGeni;
-#define glTexGeni glad_glTexGeni
-typedef void (APIENTRYP PFNGLTEXGENIVPROC)(GLenum coord, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXGENIVPROC glad_glTexGeniv;
-#define glTexGeniv glad_glTexGeniv
-typedef void (APIENTRYP PFNGLFEEDBACKBUFFERPROC)(GLsizei size, GLenum type, GLfloat *buffer);
-GLAPI PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
-#define glFeedbackBuffer glad_glFeedbackBuffer
-typedef void (APIENTRYP PFNGLSELECTBUFFERPROC)(GLsizei size, GLuint *buffer);
-GLAPI PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
-#define glSelectBuffer glad_glSelectBuffer
-typedef GLint (APIENTRYP PFNGLRENDERMODEPROC)(GLenum mode);
-GLAPI PFNGLRENDERMODEPROC glad_glRenderMode;
-#define glRenderMode glad_glRenderMode
-typedef void (APIENTRYP PFNGLINITNAMESPROC)(void);
-GLAPI PFNGLINITNAMESPROC glad_glInitNames;
-#define glInitNames glad_glInitNames
-typedef void (APIENTRYP PFNGLLOADNAMEPROC)(GLuint name);
-GLAPI PFNGLLOADNAMEPROC glad_glLoadName;
-#define glLoadName glad_glLoadName
-typedef void (APIENTRYP PFNGLPASSTHROUGHPROC)(GLfloat token);
-GLAPI PFNGLPASSTHROUGHPROC glad_glPassThrough;
-#define glPassThrough glad_glPassThrough
-typedef void (APIENTRYP PFNGLPOPNAMEPROC)(void);
-GLAPI PFNGLPOPNAMEPROC glad_glPopName;
-#define glPopName glad_glPopName
-typedef void (APIENTRYP PFNGLPUSHNAMEPROC)(GLuint name);
-GLAPI PFNGLPUSHNAMEPROC glad_glPushName;
-#define glPushName glad_glPushName
-typedef void (APIENTRYP PFNGLCLEARACCUMPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLCLEARACCUMPROC glad_glClearAccum;
-#define glClearAccum glad_glClearAccum
-typedef void (APIENTRYP PFNGLCLEARINDEXPROC)(GLfloat c);
-GLAPI PFNGLCLEARINDEXPROC glad_glClearIndex;
-#define glClearIndex glad_glClearIndex
-typedef void (APIENTRYP PFNGLINDEXMASKPROC)(GLuint mask);
-GLAPI PFNGLINDEXMASKPROC glad_glIndexMask;
-#define glIndexMask glad_glIndexMask
-typedef void (APIENTRYP PFNGLACCUMPROC)(GLenum op, GLfloat value);
-GLAPI PFNGLACCUMPROC glad_glAccum;
-#define glAccum glad_glAccum
-typedef void (APIENTRYP PFNGLPOPATTRIBPROC)(void);
-GLAPI PFNGLPOPATTRIBPROC glad_glPopAttrib;
-#define glPopAttrib glad_glPopAttrib
-typedef void (APIENTRYP PFNGLPUSHATTRIBPROC)(GLbitfield mask);
-GLAPI PFNGLPUSHATTRIBPROC glad_glPushAttrib;
-#define glPushAttrib glad_glPushAttrib
-typedef void (APIENTRYP PFNGLMAP1DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
-GLAPI PFNGLMAP1DPROC glad_glMap1d;
-#define glMap1d glad_glMap1d
-typedef void (APIENTRYP PFNGLMAP1FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
-GLAPI PFNGLMAP1FPROC glad_glMap1f;
-#define glMap1f glad_glMap1f
-typedef void (APIENTRYP PFNGLMAP2DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
-GLAPI PFNGLMAP2DPROC glad_glMap2d;
-#define glMap2d glad_glMap2d
-typedef void (APIENTRYP PFNGLMAP2FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
-GLAPI PFNGLMAP2FPROC glad_glMap2f;
-#define glMap2f glad_glMap2f
-typedef void (APIENTRYP PFNGLMAPGRID1DPROC)(GLint un, GLdouble u1, GLdouble u2);
-GLAPI PFNGLMAPGRID1DPROC glad_glMapGrid1d;
-#define glMapGrid1d glad_glMapGrid1d
-typedef void (APIENTRYP PFNGLMAPGRID1FPROC)(GLint un, GLfloat u1, GLfloat u2);
-GLAPI PFNGLMAPGRID1FPROC glad_glMapGrid1f;
-#define glMapGrid1f glad_glMapGrid1f
-typedef void (APIENTRYP PFNGLMAPGRID2DPROC)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
-GLAPI PFNGLMAPGRID2DPROC glad_glMapGrid2d;
-#define glMapGrid2d glad_glMapGrid2d
-typedef void (APIENTRYP PFNGLMAPGRID2FPROC)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
-GLAPI PFNGLMAPGRID2FPROC glad_glMapGrid2f;
-#define glMapGrid2f glad_glMapGrid2f
-typedef void (APIENTRYP PFNGLEVALCOORD1DPROC)(GLdouble u);
-GLAPI PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
-#define glEvalCoord1d glad_glEvalCoord1d
-typedef void (APIENTRYP PFNGLEVALCOORD1DVPROC)(const GLdouble *u);
-GLAPI PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
-#define glEvalCoord1dv glad_glEvalCoord1dv
-typedef void (APIENTRYP PFNGLEVALCOORD1FPROC)(GLfloat u);
-GLAPI PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
-#define glEvalCoord1f glad_glEvalCoord1f
-typedef void (APIENTRYP PFNGLEVALCOORD1FVPROC)(const GLfloat *u);
-GLAPI PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
-#define glEvalCoord1fv glad_glEvalCoord1fv
-typedef void (APIENTRYP PFNGLEVALCOORD2DPROC)(GLdouble u, GLdouble v);
-GLAPI PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
-#define glEvalCoord2d glad_glEvalCoord2d
-typedef void (APIENTRYP PFNGLEVALCOORD2DVPROC)(const GLdouble *u);
-GLAPI PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
-#define glEvalCoord2dv glad_glEvalCoord2dv
-typedef void (APIENTRYP PFNGLEVALCOORD2FPROC)(GLfloat u, GLfloat v);
-GLAPI PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
-#define glEvalCoord2f glad_glEvalCoord2f
-typedef void (APIENTRYP PFNGLEVALCOORD2FVPROC)(const GLfloat *u);
-GLAPI PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
-#define glEvalCoord2fv glad_glEvalCoord2fv
-typedef void (APIENTRYP PFNGLEVALMESH1PROC)(GLenum mode, GLint i1, GLint i2);
-GLAPI PFNGLEVALMESH1PROC glad_glEvalMesh1;
-#define glEvalMesh1 glad_glEvalMesh1
-typedef void (APIENTRYP PFNGLEVALPOINT1PROC)(GLint i);
-GLAPI PFNGLEVALPOINT1PROC glad_glEvalPoint1;
-#define glEvalPoint1 glad_glEvalPoint1
-typedef void (APIENTRYP PFNGLEVALMESH2PROC)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
-GLAPI PFNGLEVALMESH2PROC glad_glEvalMesh2;
-#define glEvalMesh2 glad_glEvalMesh2
-typedef void (APIENTRYP PFNGLEVALPOINT2PROC)(GLint i, GLint j);
-GLAPI PFNGLEVALPOINT2PROC glad_glEvalPoint2;
-#define glEvalPoint2 glad_glEvalPoint2
-typedef void (APIENTRYP PFNGLALPHAFUNCPROC)(GLenum func, GLfloat ref);
-GLAPI PFNGLALPHAFUNCPROC glad_glAlphaFunc;
-#define glAlphaFunc glad_glAlphaFunc
-typedef void (APIENTRYP PFNGLPIXELZOOMPROC)(GLfloat xfactor, GLfloat yfactor);
-GLAPI PFNGLPIXELZOOMPROC glad_glPixelZoom;
-#define glPixelZoom glad_glPixelZoom
-typedef void (APIENTRYP PFNGLPIXELTRANSFERFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
-#define glPixelTransferf glad_glPixelTransferf
-typedef void (APIENTRYP PFNGLPIXELTRANSFERIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
-#define glPixelTransferi glad_glPixelTransferi
-typedef void (APIENTRYP PFNGLPIXELMAPFVPROC)(GLenum map, GLsizei mapsize, const GLfloat *values);
-GLAPI PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
-#define glPixelMapfv glad_glPixelMapfv
-typedef void (APIENTRYP PFNGLPIXELMAPUIVPROC)(GLenum map, GLsizei mapsize, const GLuint *values);
-GLAPI PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
-#define glPixelMapuiv glad_glPixelMapuiv
-typedef void (APIENTRYP PFNGLPIXELMAPUSVPROC)(GLenum map, GLsizei mapsize, const GLushort *values);
-GLAPI PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
-#define glPixelMapusv glad_glPixelMapusv
-typedef void (APIENTRYP PFNGLCOPYPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-GLAPI PFNGLCOPYPIXELSPROC glad_glCopyPixels;
-#define glCopyPixels glad_glCopyPixels
-typedef void (APIENTRYP PFNGLDRAWPIXELSPROC)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLDRAWPIXELSPROC glad_glDrawPixels;
-#define glDrawPixels glad_glDrawPixels
-typedef void (APIENTRYP PFNGLGETCLIPPLANEPROC)(GLenum plane, GLdouble *equation);
-GLAPI PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
-#define glGetClipPlane glad_glGetClipPlane
-typedef void (APIENTRYP PFNGLGETLIGHTFVPROC)(GLenum light, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETLIGHTFVPROC glad_glGetLightfv;
-#define glGetLightfv glad_glGetLightfv
-typedef void (APIENTRYP PFNGLGETLIGHTIVPROC)(GLenum light, GLenum pname, GLint *params);
-GLAPI PFNGLGETLIGHTIVPROC glad_glGetLightiv;
-#define glGetLightiv glad_glGetLightiv
-typedef void (APIENTRYP PFNGLGETMAPDVPROC)(GLenum target, GLenum query, GLdouble *v);
-GLAPI PFNGLGETMAPDVPROC glad_glGetMapdv;
-#define glGetMapdv glad_glGetMapdv
-typedef void (APIENTRYP PFNGLGETMAPFVPROC)(GLenum target, GLenum query, GLfloat *v);
-GLAPI PFNGLGETMAPFVPROC glad_glGetMapfv;
-#define glGetMapfv glad_glGetMapfv
-typedef void (APIENTRYP PFNGLGETMAPIVPROC)(GLenum target, GLenum query, GLint *v);
-GLAPI PFNGLGETMAPIVPROC glad_glGetMapiv;
-#define glGetMapiv glad_glGetMapiv
-typedef void (APIENTRYP PFNGLGETMATERIALFVPROC)(GLenum face, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
-#define glGetMaterialfv glad_glGetMaterialfv
-typedef void (APIENTRYP PFNGLGETMATERIALIVPROC)(GLenum face, GLenum pname, GLint *params);
-GLAPI PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
-#define glGetMaterialiv glad_glGetMaterialiv
-typedef void (APIENTRYP PFNGLGETPIXELMAPFVPROC)(GLenum map, GLfloat *values);
-GLAPI PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
-#define glGetPixelMapfv glad_glGetPixelMapfv
-typedef void (APIENTRYP PFNGLGETPIXELMAPUIVPROC)(GLenum map, GLuint *values);
-GLAPI PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
-#define glGetPixelMapuiv glad_glGetPixelMapuiv
-typedef void (APIENTRYP PFNGLGETPIXELMAPUSVPROC)(GLenum map, GLushort *values);
-GLAPI PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
-#define glGetPixelMapusv glad_glGetPixelMapusv
-typedef void (APIENTRYP PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte *mask);
-GLAPI PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
-#define glGetPolygonStipple glad_glGetPolygonStipple
-typedef void (APIENTRYP PFNGLGETTEXENVFVPROC)(GLenum target, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
-#define glGetTexEnvfv glad_glGetTexEnvfv
-typedef void (APIENTRYP PFNGLGETTEXENVIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
-#define glGetTexEnviv glad_glGetTexEnviv
-typedef void (APIENTRYP PFNGLGETTEXGENDVPROC)(GLenum coord, GLenum pname, GLdouble *params);
-GLAPI PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
-#define glGetTexGendv glad_glGetTexGendv
-typedef void (APIENTRYP PFNGLGETTEXGENFVPROC)(GLenum coord, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
-#define glGetTexGenfv glad_glGetTexGenfv
-typedef void (APIENTRYP PFNGLGETTEXGENIVPROC)(GLenum coord, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
-#define glGetTexGeniv glad_glGetTexGeniv
-typedef GLboolean (APIENTRYP PFNGLISLISTPROC)(GLuint list);
-GLAPI PFNGLISLISTPROC glad_glIsList;
-#define glIsList glad_glIsList
-typedef void (APIENTRYP PFNGLFRUSTUMPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-GLAPI PFNGLFRUSTUMPROC glad_glFrustum;
-#define glFrustum glad_glFrustum
-typedef void (APIENTRYP PFNGLLOADIDENTITYPROC)(void);
-GLAPI PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
-#define glLoadIdentity glad_glLoadIdentity
-typedef void (APIENTRYP PFNGLLOADMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
-#define glLoadMatrixf glad_glLoadMatrixf
-typedef void (APIENTRYP PFNGLLOADMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
-#define glLoadMatrixd glad_glLoadMatrixd
-typedef void (APIENTRYP PFNGLMATRIXMODEPROC)(GLenum mode);
-GLAPI PFNGLMATRIXMODEPROC glad_glMatrixMode;
-#define glMatrixMode glad_glMatrixMode
-typedef void (APIENTRYP PFNGLMULTMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
-#define glMultMatrixf glad_glMultMatrixf
-typedef void (APIENTRYP PFNGLMULTMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
-#define glMultMatrixd glad_glMultMatrixd
-typedef void (APIENTRYP PFNGLORTHOPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-GLAPI PFNGLORTHOPROC glad_glOrtho;
-#define glOrtho glad_glOrtho
-typedef void (APIENTRYP PFNGLPOPMATRIXPROC)(void);
-GLAPI PFNGLPOPMATRIXPROC glad_glPopMatrix;
-#define glPopMatrix glad_glPopMatrix
-typedef void (APIENTRYP PFNGLPUSHMATRIXPROC)(void);
-GLAPI PFNGLPUSHMATRIXPROC glad_glPushMatrix;
-#define glPushMatrix glad_glPushMatrix
-typedef void (APIENTRYP PFNGLROTATEDPROC)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLROTATEDPROC glad_glRotated;
-#define glRotated glad_glRotated
-typedef void (APIENTRYP PFNGLROTATEFPROC)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLROTATEFPROC glad_glRotatef;
-#define glRotatef glad_glRotatef
-typedef void (APIENTRYP PFNGLSCALEDPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLSCALEDPROC glad_glScaled;
-#define glScaled glad_glScaled
-typedef void (APIENTRYP PFNGLSCALEFPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLSCALEFPROC glad_glScalef;
-#define glScalef glad_glScalef
-typedef void (APIENTRYP PFNGLTRANSLATEDPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLTRANSLATEDPROC glad_glTranslated;
-#define glTranslated glad_glTranslated
-typedef void (APIENTRYP PFNGLTRANSLATEFPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLTRANSLATEFPROC glad_glTranslatef;
-#define glTranslatef glad_glTranslatef
-#endif
-#ifndef GL_VERSION_1_1
-#define GL_VERSION_1_1 1
-GLAPI int GLAD_GL_VERSION_1_1;
-typedef void (APIENTRYP PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
-GLAPI PFNGLDRAWARRAYSPROC glad_glDrawArrays;
-#define glDrawArrays glad_glDrawArrays
-typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices);
-GLAPI PFNGLDRAWELEMENTSPROC glad_glDrawElements;
-#define glDrawElements glad_glDrawElements
-typedef void (APIENTRYP PFNGLGETPOINTERVPROC)(GLenum pname, void **params);
-GLAPI PFNGLGETPOINTERVPROC glad_glGetPointerv;
-#define glGetPointerv glad_glGetPointerv
-typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
-GLAPI PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
-#define glPolygonOffset glad_glPolygonOffset
-typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
-GLAPI PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
-#define glCopyTexImage1D glad_glCopyTexImage1D
-typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-GLAPI PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
-#define glCopyTexImage2D glad_glCopyTexImage2D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
-GLAPI PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
-#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
-#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
-#define glTexSubImage1D glad_glTexSubImage1D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
-#define glTexSubImage2D glad_glTexSubImage2D
-typedef void (APIENTRYP PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
-GLAPI PFNGLBINDTEXTUREPROC glad_glBindTexture;
-#define glBindTexture glad_glBindTexture
-typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint *textures);
-GLAPI PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
-#define glDeleteTextures glad_glDeleteTextures
-typedef void (APIENTRYP PFNGLGENTEXTURESPROC)(GLsizei n, GLuint *textures);
-GLAPI PFNGLGENTEXTURESPROC glad_glGenTextures;
-#define glGenTextures glad_glGenTextures
-typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC)(GLuint texture);
-GLAPI PFNGLISTEXTUREPROC glad_glIsTexture;
-#define glIsTexture glad_glIsTexture
-typedef void (APIENTRYP PFNGLARRAYELEMENTPROC)(GLint i);
-GLAPI PFNGLARRAYELEMENTPROC glad_glArrayElement;
-#define glArrayElement glad_glArrayElement
-typedef void (APIENTRYP PFNGLCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLCOLORPOINTERPROC glad_glColorPointer;
-#define glColorPointer glad_glColorPointer
-typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEPROC)(GLenum array);
-GLAPI PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
-#define glDisableClientState glad_glDisableClientState
-typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERPROC)(GLsizei stride, const void *pointer);
-GLAPI PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
-#define glEdgeFlagPointer glad_glEdgeFlagPointer
-typedef void (APIENTRYP PFNGLENABLECLIENTSTATEPROC)(GLenum array);
-GLAPI PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
-#define glEnableClientState glad_glEnableClientState
-typedef void (APIENTRYP PFNGLINDEXPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLINDEXPOINTERPROC glad_glIndexPointer;
-#define glIndexPointer glad_glIndexPointer
-typedef void (APIENTRYP PFNGLINTERLEAVEDARRAYSPROC)(GLenum format, GLsizei stride, const void *pointer);
-GLAPI PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
-#define glInterleavedArrays glad_glInterleavedArrays
-typedef void (APIENTRYP PFNGLNORMALPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLNORMALPOINTERPROC glad_glNormalPointer;
-#define glNormalPointer glad_glNormalPointer
-typedef void (APIENTRYP PFNGLTEXCOORDPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
-#define glTexCoordPointer glad_glTexCoordPointer
-typedef void (APIENTRYP PFNGLVERTEXPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
-#define glVertexPointer glad_glVertexPointer
-typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTPROC)(GLsizei n, const GLuint *textures, GLboolean *residences);
-GLAPI PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
-#define glAreTexturesResident glad_glAreTexturesResident
-typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESPROC)(GLsizei n, const GLuint *textures, const GLfloat *priorities);
-GLAPI PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
-#define glPrioritizeTextures glad_glPrioritizeTextures
-typedef void (APIENTRYP PFNGLINDEXUBPROC)(GLubyte c);
-GLAPI PFNGLINDEXUBPROC glad_glIndexub;
-#define glIndexub glad_glIndexub
-typedef void (APIENTRYP PFNGLINDEXUBVPROC)(const GLubyte *c);
-GLAPI PFNGLINDEXUBVPROC glad_glIndexubv;
-#define glIndexubv glad_glIndexubv
-typedef void (APIENTRYP PFNGLPOPCLIENTATTRIBPROC)(void);
-GLAPI PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
-#define glPopClientAttrib glad_glPopClientAttrib
-typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield mask);
-GLAPI PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
-#define glPushClientAttrib glad_glPushClientAttrib
-#endif
-#ifndef GL_VERSION_1_2
-#define GL_VERSION_1_2 1
-GLAPI int GLAD_GL_VERSION_1_2;
-typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
-GLAPI PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
-#define glDrawRangeElements glad_glDrawRangeElements
-typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
-#define glTexImage3D glad_glTexImage3D
-typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
-GLAPI PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
-#define glTexSubImage3D glad_glTexSubImage3D
-typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GLAPI PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
-#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
-#endif
-#ifndef GL_VERSION_1_3
-#define GL_VERSION_1_3 1
-GLAPI int GLAD_GL_VERSION_1_3;
-typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture);
-GLAPI PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
-#define glActiveTexture glad_glActiveTexture
-typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
-GLAPI PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
-#define glSampleCoverage glad_glSampleCoverage
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
-#define glCompressedTexImage3D glad_glCompressedTexImage3D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
-#define glCompressedTexImage2D glad_glCompressedTexImage2D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
-#define glCompressedTexImage1D glad_glCompressedTexImage1D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
-#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
-#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
-typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
-GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
-#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
-typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void *img);
-GLAPI PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
-#define glGetCompressedTexImage glad_glGetCompressedTexImage
-typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC)(GLenum texture);
-GLAPI PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
-#define glClientActiveTexture glad_glClientActiveTexture
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC)(GLenum target, GLdouble s);
-GLAPI PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
-#define glMultiTexCoord1d glad_glMultiTexCoord1d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
-#define glMultiTexCoord1dv glad_glMultiTexCoord1dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC)(GLenum target, GLfloat s);
-GLAPI PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
-#define glMultiTexCoord1f glad_glMultiTexCoord1f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
-#define glMultiTexCoord1fv glad_glMultiTexCoord1fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC)(GLenum target, GLint s);
-GLAPI PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
-#define glMultiTexCoord1i glad_glMultiTexCoord1i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
-#define glMultiTexCoord1iv glad_glMultiTexCoord1iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC)(GLenum target, GLshort s);
-GLAPI PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
-#define glMultiTexCoord1s glad_glMultiTexCoord1s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
-#define glMultiTexCoord1sv glad_glMultiTexCoord1sv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC)(GLenum target, GLdouble s, GLdouble t);
-GLAPI PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
-#define glMultiTexCoord2d glad_glMultiTexCoord2d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
-#define glMultiTexCoord2dv glad_glMultiTexCoord2dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC)(GLenum target, GLfloat s, GLfloat t);
-GLAPI PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
-#define glMultiTexCoord2f glad_glMultiTexCoord2f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
-#define glMultiTexCoord2fv glad_glMultiTexCoord2fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC)(GLenum target, GLint s, GLint t);
-GLAPI PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
-#define glMultiTexCoord2i glad_glMultiTexCoord2i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
-#define glMultiTexCoord2iv glad_glMultiTexCoord2iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC)(GLenum target, GLshort s, GLshort t);
-GLAPI PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
-#define glMultiTexCoord2s glad_glMultiTexCoord2s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
-#define glMultiTexCoord2sv glad_glMultiTexCoord2sv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r);
-GLAPI PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
-#define glMultiTexCoord3d glad_glMultiTexCoord3d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
-#define glMultiTexCoord3dv glad_glMultiTexCoord3dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
-GLAPI PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
-#define glMultiTexCoord3f glad_glMultiTexCoord3f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
-#define glMultiTexCoord3fv glad_glMultiTexCoord3fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC)(GLenum target, GLint s, GLint t, GLint r);
-GLAPI PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
-#define glMultiTexCoord3i glad_glMultiTexCoord3i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
-#define glMultiTexCoord3iv glad_glMultiTexCoord3iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC)(GLenum target, GLshort s, GLshort t, GLshort r);
-GLAPI PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
-#define glMultiTexCoord3s glad_glMultiTexCoord3s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
-#define glMultiTexCoord3sv glad_glMultiTexCoord3sv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-GLAPI PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
-#define glMultiTexCoord4d glad_glMultiTexCoord4d
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC)(GLenum target, const GLdouble *v);
-GLAPI PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
-#define glMultiTexCoord4dv glad_glMultiTexCoord4dv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-GLAPI PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
-#define glMultiTexCoord4f glad_glMultiTexCoord4f
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC)(GLenum target, const GLfloat *v);
-GLAPI PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
-#define glMultiTexCoord4fv glad_glMultiTexCoord4fv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q);
-GLAPI PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
-#define glMultiTexCoord4i glad_glMultiTexCoord4i
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC)(GLenum target, const GLint *v);
-GLAPI PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
-#define glMultiTexCoord4iv glad_glMultiTexCoord4iv
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
-GLAPI PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
-#define glMultiTexCoord4s glad_glMultiTexCoord4s
-typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC)(GLenum target, const GLshort *v);
-GLAPI PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
-#define glMultiTexCoord4sv glad_glMultiTexCoord4sv
-typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
-#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf
-typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
-#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd
-typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC)(const GLfloat *m);
-GLAPI PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
-#define glMultTransposeMatrixf glad_glMultTransposeMatrixf
-typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC)(const GLdouble *m);
-GLAPI PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
-#define glMultTransposeMatrixd glad_glMultTransposeMatrixd
-#endif
-#ifndef GL_VERSION_1_4
-#define GL_VERSION_1_4 1
-GLAPI int GLAD_GL_VERSION_1_4;
-typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
-GLAPI PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
-#define glBlendFuncSeparate glad_glBlendFuncSeparate
-typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
-GLAPI PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
-#define glMultiDrawArrays glad_glMultiDrawArrays
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
-GLAPI PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
-#define glMultiDrawElements glad_glMultiDrawElements
-typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
-GLAPI PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
-#define glPointParameterf glad_glPointParameterf
-typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat *params);
-GLAPI PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
-#define glPointParameterfv glad_glPointParameterfv
-typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
-GLAPI PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
-#define glPointParameteri glad_glPointParameteri
-typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint *params);
-GLAPI PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
-#define glPointParameteriv glad_glPointParameteriv
-typedef void (APIENTRYP PFNGLFOGCOORDFPROC)(GLfloat coord);
-GLAPI PFNGLFOGCOORDFPROC glad_glFogCoordf;
-#define glFogCoordf glad_glFogCoordf
-typedef void (APIENTRYP PFNGLFOGCOORDFVPROC)(const GLfloat *coord);
-GLAPI PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
-#define glFogCoordfv glad_glFogCoordfv
-typedef void (APIENTRYP PFNGLFOGCOORDDPROC)(GLdouble coord);
-GLAPI PFNGLFOGCOORDDPROC glad_glFogCoordd;
-#define glFogCoordd glad_glFogCoordd
-typedef void (APIENTRYP PFNGLFOGCOORDDVPROC)(const GLdouble *coord);
-GLAPI PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
-#define glFogCoorddv glad_glFogCoorddv
-typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
-#define glFogCoordPointer glad_glFogCoordPointer
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
-GLAPI PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
-#define glSecondaryColor3b glad_glSecondaryColor3b
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC)(const GLbyte *v);
-GLAPI PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
-#define glSecondaryColor3bv glad_glSecondaryColor3bv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
-GLAPI PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
-#define glSecondaryColor3d glad_glSecondaryColor3d
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC)(const GLdouble *v);
-GLAPI PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
-#define glSecondaryColor3dv glad_glSecondaryColor3dv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
-GLAPI PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
-#define glSecondaryColor3f glad_glSecondaryColor3f
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC)(const GLfloat *v);
-GLAPI PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
-#define glSecondaryColor3fv glad_glSecondaryColor3fv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC)(GLint red, GLint green, GLint blue);
-GLAPI PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
-#define glSecondaryColor3i glad_glSecondaryColor3i
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC)(const GLint *v);
-GLAPI PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
-#define glSecondaryColor3iv glad_glSecondaryColor3iv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
-GLAPI PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
-#define glSecondaryColor3s glad_glSecondaryColor3s
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC)(const GLshort *v);
-GLAPI PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
-#define glSecondaryColor3sv glad_glSecondaryColor3sv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
-GLAPI PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
-#define glSecondaryColor3ub glad_glSecondaryColor3ub
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC)(const GLubyte *v);
-GLAPI PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
-#define glSecondaryColor3ubv glad_glSecondaryColor3ubv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
-GLAPI PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
-#define glSecondaryColor3ui glad_glSecondaryColor3ui
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC)(const GLuint *v);
-GLAPI PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
-#define glSecondaryColor3uiv glad_glSecondaryColor3uiv
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
-GLAPI PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
-#define glSecondaryColor3us glad_glSecondaryColor3us
-typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC)(const GLushort *v);
-GLAPI PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
-#define glSecondaryColor3usv glad_glSecondaryColor3usv
-typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
-#define glSecondaryColorPointer glad_glSecondaryColorPointer
-typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC)(GLdouble x, GLdouble y);
-GLAPI PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
-#define glWindowPos2d glad_glWindowPos2d
-typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC)(const GLdouble *v);
-GLAPI PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
-#define glWindowPos2dv glad_glWindowPos2dv
-typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC)(GLfloat x, GLfloat y);
-GLAPI PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
-#define glWindowPos2f glad_glWindowPos2f
-typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC)(const GLfloat *v);
-GLAPI PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
-#define glWindowPos2fv glad_glWindowPos2fv
-typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC)(GLint x, GLint y);
-GLAPI PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
-#define glWindowPos2i glad_glWindowPos2i
-typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC)(const GLint *v);
-GLAPI PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
-#define glWindowPos2iv glad_glWindowPos2iv
-typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC)(GLshort x, GLshort y);
-GLAPI PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
-#define glWindowPos2s glad_glWindowPos2s
-typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC)(const GLshort *v);
-GLAPI PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
-#define glWindowPos2sv glad_glWindowPos2sv
-typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
-#define glWindowPos3d glad_glWindowPos3d
-typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC)(const GLdouble *v);
-GLAPI PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
-#define glWindowPos3dv glad_glWindowPos3dv
-typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
-#define glWindowPos3f glad_glWindowPos3f
-typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC)(const GLfloat *v);
-GLAPI PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
-#define glWindowPos3fv glad_glWindowPos3fv
-typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC)(GLint x, GLint y, GLint z);
-GLAPI PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
-#define glWindowPos3i glad_glWindowPos3i
-typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC)(const GLint *v);
-GLAPI PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
-#define glWindowPos3iv glad_glWindowPos3iv
-typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC)(GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
-#define glWindowPos3s glad_glWindowPos3s
-typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC)(const GLshort *v);
-GLAPI PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
-#define glWindowPos3sv glad_glWindowPos3sv
-typedef void (APIENTRYP PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GLAPI PFNGLBLENDCOLORPROC glad_glBlendColor;
-#define glBlendColor glad_glBlendColor
-typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC)(GLenum mode);
-GLAPI PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
-#define glBlendEquation glad_glBlendEquation
-#endif
-#ifndef GL_VERSION_1_5
-#define GL_VERSION_1_5 1
-GLAPI int GLAD_GL_VERSION_1_5;
-typedef void (APIENTRYP PFNGLGENQUERIESPROC)(GLsizei n, GLuint *ids);
-GLAPI PFNGLGENQUERIESPROC glad_glGenQueries;
-#define glGenQueries glad_glGenQueries
-typedef void (APIENTRYP PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint *ids);
-GLAPI PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
-#define glDeleteQueries glad_glDeleteQueries
-typedef GLboolean (APIENTRYP PFNGLISQUERYPROC)(GLuint id);
-GLAPI PFNGLISQUERYPROC glad_glIsQuery;
-#define glIsQuery glad_glIsQuery
-typedef void (APIENTRYP PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
-GLAPI PFNGLBEGINQUERYPROC glad_glBeginQuery;
-#define glBeginQuery glad_glBeginQuery
-typedef void (APIENTRYP PFNGLENDQUERYPROC)(GLenum target);
-GLAPI PFNGLENDQUERYPROC glad_glEndQuery;
-#define glEndQuery glad_glEndQuery
-typedef void (APIENTRYP PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETQUERYIVPROC glad_glGetQueryiv;
-#define glGetQueryiv glad_glGetQueryiv
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint *params);
-GLAPI PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
-#define glGetQueryObjectiv glad_glGetQueryObjectiv
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint *params);
-GLAPI PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
-#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
-typedef void (APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
-GLAPI PFNGLBINDBUFFERPROC glad_glBindBuffer;
-#define glBindBuffer glad_glBindBuffer
-typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint *buffers);
-GLAPI PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
-#define glDeleteBuffers glad_glDeleteBuffers
-typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers);
-GLAPI PFNGLGENBUFFERSPROC glad_glGenBuffers;
-#define glGenBuffers glad_glGenBuffers
-typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC)(GLuint buffer);
-GLAPI PFNGLISBUFFERPROC glad_glIsBuffer;
-#define glIsBuffer glad_glIsBuffer
-typedef void (APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
-GLAPI PFNGLBUFFERDATAPROC glad_glBufferData;
-#define glBufferData glad_glBufferData
-typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
-GLAPI PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
-#define glBufferSubData glad_glBufferSubData
-typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void *data);
-GLAPI PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
-#define glGetBufferSubData glad_glGetBufferSubData
-typedef void * (APIENTRYP PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
-GLAPI PFNGLMAPBUFFERPROC glad_glMapBuffer;
-#define glMapBuffer glad_glMapBuffer
-typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC)(GLenum target);
-GLAPI PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
-#define glUnmapBuffer glad_glUnmapBuffer
-typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
-#define glGetBufferParameteriv glad_glGetBufferParameteriv
-typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void **params);
-GLAPI PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
-#define glGetBufferPointerv glad_glGetBufferPointerv
-#endif
-#ifndef GL_VERSION_2_0
-#define GL_VERSION_2_0 1
-GLAPI int GLAD_GL_VERSION_2_0;
-typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
-GLAPI PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
-#define glBlendEquationSeparate glad_glBlendEquationSeparate
-typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum *bufs);
-GLAPI PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
-#define glDrawBuffers glad_glDrawBuffers
-typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
-GLAPI PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
-#define glStencilOpSeparate glad_glStencilOpSeparate
-typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
-GLAPI PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
-#define glStencilFuncSeparate glad_glStencilFuncSeparate
-typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
-GLAPI PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
-#define glStencilMaskSeparate glad_glStencilMaskSeparate
-typedef void (APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
-GLAPI PFNGLATTACHSHADERPROC glad_glAttachShader;
-#define glAttachShader glad_glAttachShader
-typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar *name);
-GLAPI PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
-#define glBindAttribLocation glad_glBindAttribLocation
-typedef void (APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader);
-GLAPI PFNGLCOMPILESHADERPROC glad_glCompileShader;
-#define glCompileShader glad_glCompileShader
-typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC)(void);
-GLAPI PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
-#define glCreateProgram glad_glCreateProgram
-typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC)(GLenum type);
-GLAPI PFNGLCREATESHADERPROC glad_glCreateShader;
-#define glCreateShader glad_glCreateShader
-typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program);
-GLAPI PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
-#define glDeleteProgram glad_glDeleteProgram
-typedef void (APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader);
-GLAPI PFNGLDELETESHADERPROC glad_glDeleteShader;
-#define glDeleteShader glad_glDeleteShader
-typedef void (APIENTRYP PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
-GLAPI PFNGLDETACHSHADERPROC glad_glDetachShader;
-#define glDetachShader glad_glDetachShader
-typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
-GLAPI PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
-#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
-typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
-GLAPI PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
-#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
-typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-GLAPI PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
-#define glGetActiveAttrib glad_glGetActiveAttrib
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
-GLAPI PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
-#define glGetActiveUniform glad_glGetActiveUniform
-typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
-GLAPI PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
-#define glGetAttachedShaders glad_glGetAttachedShaders
-typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
-#define glGetAttribLocation glad_glGetAttribLocation
-typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint *params);
-GLAPI PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
-#define glGetProgramiv glad_glGetProgramiv
-typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
-GLAPI PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
-#define glGetProgramInfoLog glad_glGetProgramInfoLog
-typedef void (APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint *params);
-GLAPI PFNGLGETSHADERIVPROC glad_glGetShaderiv;
-#define glGetShaderiv glad_glGetShaderiv
-typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
-GLAPI PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
-#define glGetShaderInfoLog glad_glGetShaderInfoLog
-typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
-GLAPI PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
-#define glGetShaderSource glad_glGetShaderSource
-typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
-#define glGetUniformLocation glad_glGetUniformLocation
-typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat *params);
-GLAPI PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
-#define glGetUniformfv glad_glGetUniformfv
-typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint *params);
-GLAPI PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
-#define glGetUniformiv glad_glGetUniformiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble *params);
-GLAPI PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
-#define glGetVertexAttribdv glad_glGetVertexAttribdv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
-#define glGetVertexAttribfv glad_glGetVertexAttribfv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint *params);
-GLAPI PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
-#define glGetVertexAttribiv glad_glGetVertexAttribiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void **pointer);
-GLAPI PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
-#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
-typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC)(GLuint program);
-GLAPI PFNGLISPROGRAMPROC glad_glIsProgram;
-#define glIsProgram glad_glIsProgram
-typedef GLboolean (APIENTRYP PFNGLISSHADERPROC)(GLuint shader);
-GLAPI PFNGLISSHADERPROC glad_glIsShader;
-#define glIsShader glad_glIsShader
-typedef void (APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program);
-GLAPI PFNGLLINKPROGRAMPROC glad_glLinkProgram;
-#define glLinkProgram glad_glLinkProgram
-typedef void (APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
-GLAPI PFNGLSHADERSOURCEPROC glad_glShaderSource;
-#define glShaderSource glad_glShaderSource
-typedef void (APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program);
-GLAPI PFNGLUSEPROGRAMPROC glad_glUseProgram;
-#define glUseProgram glad_glUseProgram
-typedef void (APIENTRYP PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
-GLAPI PFNGLUNIFORM1FPROC glad_glUniform1f;
-#define glUniform1f glad_glUniform1f
-typedef void (APIENTRYP PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
-GLAPI PFNGLUNIFORM2FPROC glad_glUniform2f;
-#define glUniform2f glad_glUniform2f
-typedef void (APIENTRYP PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-GLAPI PFNGLUNIFORM3FPROC glad_glUniform3f;
-#define glUniform3f glad_glUniform3f
-typedef void (APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
-GLAPI PFNGLUNIFORM4FPROC glad_glUniform4f;
-#define glUniform4f glad_glUniform4f
-typedef void (APIENTRYP PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
-GLAPI PFNGLUNIFORM1IPROC glad_glUniform1i;
-#define glUniform1i glad_glUniform1i
-typedef void (APIENTRYP PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
-GLAPI PFNGLUNIFORM2IPROC glad_glUniform2i;
-#define glUniform2i glad_glUniform2i
-typedef void (APIENTRYP PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
-GLAPI PFNGLUNIFORM3IPROC glad_glUniform3i;
-#define glUniform3i glad_glUniform3i
-typedef void (APIENTRYP PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
-GLAPI PFNGLUNIFORM4IPROC glad_glUniform4i;
-#define glUniform4i glad_glUniform4i
-typedef void (APIENTRYP PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM1FVPROC glad_glUniform1fv;
-#define glUniform1fv glad_glUniform1fv
-typedef void (APIENTRYP PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM2FVPROC glad_glUniform2fv;
-#define glUniform2fv glad_glUniform2fv
-typedef void (APIENTRYP PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM3FVPROC glad_glUniform3fv;
-#define glUniform3fv glad_glUniform3fv
-typedef void (APIENTRYP PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat *value);
-GLAPI PFNGLUNIFORM4FVPROC glad_glUniform4fv;
-#define glUniform4fv glad_glUniform4fv
-typedef void (APIENTRYP PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM1IVPROC glad_glUniform1iv;
-#define glUniform1iv glad_glUniform1iv
-typedef void (APIENTRYP PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM2IVPROC glad_glUniform2iv;
-#define glUniform2iv glad_glUniform2iv
-typedef void (APIENTRYP PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM3IVPROC glad_glUniform3iv;
-#define glUniform3iv glad_glUniform3iv
-typedef void (APIENTRYP PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint *value);
-GLAPI PFNGLUNIFORM4IVPROC glad_glUniform4iv;
-#define glUniform4iv glad_glUniform4iv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
-#define glUniformMatrix2fv glad_glUniformMatrix2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
-#define glUniformMatrix3fv glad_glUniformMatrix3fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
-#define glUniformMatrix4fv glad_glUniformMatrix4fv
-typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC)(GLuint program);
-GLAPI PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
-#define glValidateProgram glad_glValidateProgram
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
-GLAPI PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
-#define glVertexAttrib1d glad_glVertexAttrib1d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
-#define glVertexAttrib1dv glad_glVertexAttrib1dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
-GLAPI PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
-#define glVertexAttrib1f glad_glVertexAttrib1f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
-#define glVertexAttrib1fv glad_glVertexAttrib1fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
-GLAPI PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
-#define glVertexAttrib1s glad_glVertexAttrib1s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
-#define glVertexAttrib1sv glad_glVertexAttrib1sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
-GLAPI PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
-#define glVertexAttrib2d glad_glVertexAttrib2d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
-#define glVertexAttrib2dv glad_glVertexAttrib2dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
-GLAPI PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
-#define glVertexAttrib2f glad_glVertexAttrib2f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
-#define glVertexAttrib2fv glad_glVertexAttrib2fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
-GLAPI PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
-#define glVertexAttrib2s glad_glVertexAttrib2s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
-#define glVertexAttrib2sv glad_glVertexAttrib2sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
-GLAPI PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
-#define glVertexAttrib3d glad_glVertexAttrib3d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
-#define glVertexAttrib3dv glad_glVertexAttrib3dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
-GLAPI PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
-#define glVertexAttrib3f glad_glVertexAttrib3f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
-#define glVertexAttrib3fv glad_glVertexAttrib3fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
-GLAPI PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
-#define glVertexAttrib3s glad_glVertexAttrib3s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
-#define glVertexAttrib3sv glad_glVertexAttrib3sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte *v);
-GLAPI PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
-#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
-#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
-#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
-GLAPI PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
-#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte *v);
-GLAPI PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
-#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
-#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort *v);
-GLAPI PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
-#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte *v);
-GLAPI PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
-#define glVertexAttrib4bv glad_glVertexAttrib4bv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-GLAPI PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
-#define glVertexAttrib4d glad_glVertexAttrib4d
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble *v);
-GLAPI PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
-#define glVertexAttrib4dv glad_glVertexAttrib4dv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-GLAPI PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
-#define glVertexAttrib4f glad_glVertexAttrib4f
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat *v);
-GLAPI PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
-#define glVertexAttrib4fv glad_glVertexAttrib4fv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
-#define glVertexAttrib4iv glad_glVertexAttrib4iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
-GLAPI PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
-#define glVertexAttrib4s glad_glVertexAttrib4s
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
-#define glVertexAttrib4sv glad_glVertexAttrib4sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte *v);
-GLAPI PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
-#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
-#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort *v);
-GLAPI PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
-#define glVertexAttrib4usv glad_glVertexAttrib4usv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
-GLAPI PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
-#define glVertexAttribPointer glad_glVertexAttribPointer
-#endif
-#ifndef GL_VERSION_2_1
-#define GL_VERSION_2_1 1
-GLAPI int GLAD_GL_VERSION_2_1;
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
-#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
-#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
-#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
-#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
-#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
-typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
-GLAPI PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
-#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
-#endif
-#ifndef GL_VERSION_3_0
-#define GL_VERSION_3_0 1
-GLAPI int GLAD_GL_VERSION_3_0;
-typedef void (APIENTRYP PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
-GLAPI PFNGLCOLORMASKIPROC glad_glColorMaski;
-#define glColorMaski glad_glColorMaski
-typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean *data);
-GLAPI PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
-#define glGetBooleani_v glad_glGetBooleani_v
-typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint *data);
-GLAPI PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
-#define glGetIntegeri_v glad_glGetIntegeri_v
-typedef void (APIENTRYP PFNGLENABLEIPROC)(GLenum target, GLuint index);
-GLAPI PFNGLENABLEIPROC glad_glEnablei;
-#define glEnablei glad_glEnablei
-typedef void (APIENTRYP PFNGLDISABLEIPROC)(GLenum target, GLuint index);
-GLAPI PFNGLDISABLEIPROC glad_glDisablei;
-#define glDisablei glad_glDisablei
-typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
-GLAPI PFNGLISENABLEDIPROC glad_glIsEnabledi;
-#define glIsEnabledi glad_glIsEnabledi
-typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
-GLAPI PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
-#define glBeginTransformFeedback glad_glBeginTransformFeedback
-typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC)(void);
-GLAPI PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
-#define glEndTransformFeedback glad_glEndTransformFeedback
-typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
-GLAPI PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
-#define glBindBufferRange glad_glBindBufferRange
-typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
-GLAPI PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
-#define glBindBufferBase glad_glBindBufferBase
-typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
-GLAPI PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
-#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
-typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
-GLAPI PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
-#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
-typedef void (APIENTRYP PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
-GLAPI PFNGLCLAMPCOLORPROC glad_glClampColor;
-#define glClampColor glad_glClampColor
-typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
-GLAPI PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
-#define glBeginConditionalRender glad_glBeginConditionalRender
-typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC)(void);
-GLAPI PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
-#define glEndConditionalRender glad_glEndConditionalRender
-typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
-GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
-#define glVertexAttribIPointer glad_glVertexAttribIPointer
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint *params);
-GLAPI PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
-#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
-typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint *params);
-GLAPI PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
-#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
-GLAPI PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
-#define glVertexAttribI1i glad_glVertexAttribI1i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
-GLAPI PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
-#define glVertexAttribI2i glad_glVertexAttribI2i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
-GLAPI PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
-#define glVertexAttribI3i glad_glVertexAttribI3i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
-GLAPI PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
-#define glVertexAttribI4i glad_glVertexAttribI4i
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
-GLAPI PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
-#define glVertexAttribI1ui glad_glVertexAttribI1ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
-GLAPI PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
-#define glVertexAttribI2ui glad_glVertexAttribI2ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
-GLAPI PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
-#define glVertexAttribI3ui glad_glVertexAttribI3ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
-GLAPI PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
-#define glVertexAttribI4ui glad_glVertexAttribI4ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
-#define glVertexAttribI1iv glad_glVertexAttribI1iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
-#define glVertexAttribI2iv glad_glVertexAttribI2iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
-#define glVertexAttribI3iv glad_glVertexAttribI3iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint *v);
-GLAPI PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
-#define glVertexAttribI4iv glad_glVertexAttribI4iv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
-#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
-#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
-#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint *v);
-GLAPI PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
-#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte *v);
-GLAPI PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
-#define glVertexAttribI4bv glad_glVertexAttribI4bv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort *v);
-GLAPI PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
-#define glVertexAttribI4sv glad_glVertexAttribI4sv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte *v);
-GLAPI PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
-#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort *v);
-GLAPI PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
-#define glVertexAttribI4usv glad_glVertexAttribI4usv
-typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint *params);
-GLAPI PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
-#define glGetUniformuiv glad_glGetUniformuiv
-typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar *name);
-GLAPI PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
-#define glBindFragDataLocation glad_glBindFragDataLocation
-typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
-#define glGetFragDataLocation glad_glGetFragDataLocation
-typedef void (APIENTRYP PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
-GLAPI PFNGLUNIFORM1UIPROC glad_glUniform1ui;
-#define glUniform1ui glad_glUniform1ui
-typedef void (APIENTRYP PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
-GLAPI PFNGLUNIFORM2UIPROC glad_glUniform2ui;
-#define glUniform2ui glad_glUniform2ui
-typedef void (APIENTRYP PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
-GLAPI PFNGLUNIFORM3UIPROC glad_glUniform3ui;
-#define glUniform3ui glad_glUniform3ui
-typedef void (APIENTRYP PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
-GLAPI PFNGLUNIFORM4UIPROC glad_glUniform4ui;
-#define glUniform4ui glad_glUniform4ui
-typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
-#define glUniform1uiv glad_glUniform1uiv
-typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
-#define glUniform2uiv glad_glUniform2uiv
-typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
-#define glUniform3uiv glad_glUniform3uiv
-typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint *value);
-GLAPI PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
-#define glUniform4uiv glad_glUniform4uiv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint *params);
-GLAPI PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
-#define glTexParameterIiv glad_glTexParameterIiv
-typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint *params);
-GLAPI PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
-#define glTexParameterIuiv glad_glTexParameterIuiv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
-#define glGetTexParameterIiv glad_glGetTexParameterIiv
-typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint *params);
-GLAPI PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
-#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint *value);
-GLAPI PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
-#define glClearBufferiv glad_glClearBufferiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint *value);
-GLAPI PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
-#define glClearBufferuiv glad_glClearBufferuiv
-typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat *value);
-GLAPI PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
-#define glClearBufferfv glad_glClearBufferfv
-typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
-GLAPI PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
-#define glClearBufferfi glad_glClearBufferfi
-typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
-GLAPI PFNGLGETSTRINGIPROC glad_glGetStringi;
-#define glGetStringi glad_glGetStringi
-typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
-GLAPI PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
-#define glIsRenderbuffer glad_glIsRenderbuffer
-typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
-GLAPI PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
-#define glBindRenderbuffer glad_glBindRenderbuffer
-typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint *renderbuffers);
-GLAPI PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
-#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
-typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint *renderbuffers);
-GLAPI PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
-#define glGenRenderbuffers glad_glGenRenderbuffers
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
-#define glRenderbufferStorage glad_glRenderbufferStorage
-typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
-#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
-typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
-GLAPI PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
-#define glIsFramebuffer glad_glIsFramebuffer
-typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
-GLAPI PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
-#define glBindFramebuffer glad_glBindFramebuffer
-typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint *framebuffers);
-GLAPI PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
-#define glDeleteFramebuffers glad_glDeleteFramebuffers
-typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint *framebuffers);
-GLAPI PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
-#define glGenFramebuffers glad_glGenFramebuffers
-typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
-GLAPI PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
-#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
-#define glFramebufferTexture1D glad_glFramebufferTexture1D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
-#define glFramebufferTexture2D glad_glFramebufferTexture2D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-GLAPI PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
-#define glFramebufferTexture3D glad_glFramebufferTexture3D
-typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-GLAPI PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
-#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
-typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
-#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
-typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC)(GLenum target);
-GLAPI PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
-#define glGenerateMipmap glad_glGenerateMipmap
-typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-GLAPI PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
-#define glBlitFramebuffer glad_glBlitFramebuffer
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
-#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
-GLAPI PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
-#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
-typedef void * (APIENTRYP PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-GLAPI PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
-#define glMapBufferRange glad_glMapBufferRange
-typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
-GLAPI PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
-#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
-typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint array);
-GLAPI PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
-#define glBindVertexArray glad_glBindVertexArray
-typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint *arrays);
-GLAPI PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
-#define glDeleteVertexArrays glad_glDeleteVertexArrays
-typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint *arrays);
-GLAPI PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
-#define glGenVertexArrays glad_glGenVertexArrays
-typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC)(GLuint array);
-GLAPI PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
-#define glIsVertexArray glad_glIsVertexArray
-#endif
-#ifndef GL_VERSION_3_1
-#define GL_VERSION_3_1 1
-GLAPI int GLAD_GL_VERSION_3_1;
-typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
-GLAPI PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
-#define glDrawArraysInstanced glad_glDrawArraysInstanced
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
-GLAPI PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
-#define glDrawElementsInstanced glad_glDrawElementsInstanced
-typedef void (APIENTRYP PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
-GLAPI PFNGLTEXBUFFERPROC glad_glTexBuffer;
-#define glTexBuffer glad_glTexBuffer
-typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
-GLAPI PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
-#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
-typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
-GLAPI PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
-#define glCopyBufferSubData glad_glCopyBufferSubData
-typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
-GLAPI PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
-#define glGetUniformIndices glad_glGetUniformIndices
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
-GLAPI PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
-#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
-GLAPI PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
-#define glGetActiveUniformName glad_glGetActiveUniformName
-typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar *uniformBlockName);
-GLAPI PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
-#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
-GLAPI PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
-#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
-typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
-GLAPI PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
-#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
-typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
-GLAPI PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
-#define glUniformBlockBinding glad_glUniformBlockBinding
-#endif
-#ifndef GL_VERSION_3_2
-#define GL_VERSION_3_2 1
-GLAPI int GLAD_GL_VERSION_3_2;
-typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
-GLAPI PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
-#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
-typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
-GLAPI PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
-#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
-GLAPI PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
-#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
-GLAPI PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
-#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
-typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
-GLAPI PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
-#define glProvokingVertex glad_glProvokingVertex
-typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
-GLAPI PFNGLFENCESYNCPROC glad_glFenceSync;
-#define glFenceSync glad_glFenceSync
-typedef GLboolean (APIENTRYP PFNGLISSYNCPROC)(GLsync sync);
-GLAPI PFNGLISSYNCPROC glad_glIsSync;
-#define glIsSync glad_glIsSync
-typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync sync);
-GLAPI PFNGLDELETESYNCPROC glad_glDeleteSync;
-#define glDeleteSync glad_glDeleteSync
-typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
-GLAPI PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
-#define glClientWaitSync glad_glClientWaitSync
-typedef void (APIENTRYP PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
-GLAPI PFNGLWAITSYNCPROC glad_glWaitSync;
-#define glWaitSync glad_glWaitSync
-typedef void (APIENTRYP PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 *data);
-GLAPI PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
-#define glGetInteger64v glad_glGetInteger64v
-typedef void (APIENTRYP PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values);
-GLAPI PFNGLGETSYNCIVPROC glad_glGetSynciv;
-#define glGetSynciv glad_glGetSynciv
-typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 *data);
-GLAPI PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
-#define glGetInteger64i_v glad_glGetInteger64i_v
-typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 *params);
-GLAPI PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
-#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
-#define glFramebufferTexture glad_glFramebufferTexture
-typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
-GLAPI PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
-#define glTexImage2DMultisample glad_glTexImage2DMultisample
-typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
-GLAPI PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
-#define glTexImage3DMultisample glad_glTexImage3DMultisample
-typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat *val);
-GLAPI PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
-#define glGetMultisamplefv glad_glGetMultisamplefv
-typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
-GLAPI PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
-#define glSampleMaski glad_glSampleMaski
-#endif
-#ifndef GL_VERSION_3_3
-#define GL_VERSION_3_3 1
-GLAPI int GLAD_GL_VERSION_3_3;
-typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
-GLAPI PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
-#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
-typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar *name);
-GLAPI PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
-#define glGetFragDataIndex glad_glGetFragDataIndex
-typedef void (APIENTRYP PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint *samplers);
-GLAPI PFNGLGENSAMPLERSPROC glad_glGenSamplers;
-#define glGenSamplers glad_glGenSamplers
-typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint *samplers);
-GLAPI PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
-#define glDeleteSamplers glad_glDeleteSamplers
-typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC)(GLuint sampler);
-GLAPI PFNGLISSAMPLERPROC glad_glIsSampler;
-#define glIsSampler glad_glIsSampler
-typedef void (APIENTRYP PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
-GLAPI PFNGLBINDSAMPLERPROC glad_glBindSampler;
-#define glBindSampler glad_glBindSampler
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
-GLAPI PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
-#define glSamplerParameteri glad_glSamplerParameteri
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint *param);
-GLAPI PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
-#define glSamplerParameteriv glad_glSamplerParameteriv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
-GLAPI PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
-#define glSamplerParameterf glad_glSamplerParameterf
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat *param);
-GLAPI PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
-#define glSamplerParameterfv glad_glSamplerParameterfv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint *param);
-GLAPI PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
-#define glSamplerParameterIiv glad_glSamplerParameterIiv
-typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint *param);
-GLAPI PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
-#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint *params);
-GLAPI PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
-#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint *params);
-GLAPI PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
-#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat *params);
-GLAPI PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
-#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
-typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint *params);
-GLAPI PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
-#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
-typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
-GLAPI PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
-#define glQueryCounter glad_glQueryCounter
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 *params);
-GLAPI PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
-#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
-typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 *params);
-GLAPI PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
-#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
-typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
-GLAPI PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
-#define glVertexAttribDivisor glad_glVertexAttribDivisor
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
-#define glVertexAttribP1ui glad_glVertexAttribP1ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
-#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
-#define glVertexAttribP2ui glad_glVertexAttribP2ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
-#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
-#define glVertexAttribP3ui glad_glVertexAttribP3ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
-#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
-GLAPI PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
-#define glVertexAttribP4ui glad_glVertexAttribP4ui
-typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
-GLAPI PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
-#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
-typedef void (APIENTRYP PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value);
-GLAPI PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
-#define glVertexP2ui glad_glVertexP2ui
-typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint *value);
-GLAPI PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
-#define glVertexP2uiv glad_glVertexP2uiv
-typedef void (APIENTRYP PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value);
-GLAPI PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
-#define glVertexP3ui glad_glVertexP3ui
-typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint *value);
-GLAPI PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
-#define glVertexP3uiv glad_glVertexP3uiv
-typedef void (APIENTRYP PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value);
-GLAPI PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
-#define glVertexP4ui glad_glVertexP4ui
-typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint *value);
-GLAPI PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
-#define glVertexP4uiv glad_glVertexP4uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
-#define glTexCoordP1ui glad_glTexCoordP1ui
-typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
-#define glTexCoordP1uiv glad_glTexCoordP1uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
-#define glTexCoordP2ui glad_glTexCoordP2ui
-typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
-#define glTexCoordP2uiv glad_glTexCoordP2uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
-#define glTexCoordP3ui glad_glTexCoordP3ui
-typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
-#define glTexCoordP3uiv glad_glTexCoordP3uiv
-typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
-#define glTexCoordP4ui glad_glTexCoordP4ui
-typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
-#define glTexCoordP4uiv glad_glTexCoordP4uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
-#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
-#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
-#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
-#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
-#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
-#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords);
-GLAPI PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
-#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
-typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
-GLAPI PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
-#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
-typedef void (APIENTRYP PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords);
-GLAPI PFNGLNORMALP3UIPROC glad_glNormalP3ui;
-#define glNormalP3ui glad_glNormalP3ui
-typedef void (APIENTRYP PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint *coords);
-GLAPI PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
-#define glNormalP3uiv glad_glNormalP3uiv
-typedef void (APIENTRYP PFNGLCOLORP3UIPROC)(GLenum type, GLuint color);
-GLAPI PFNGLCOLORP3UIPROC glad_glColorP3ui;
-#define glColorP3ui glad_glColorP3ui
-typedef void (APIENTRYP PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint *color);
-GLAPI PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
-#define glColorP3uiv glad_glColorP3uiv
-typedef void (APIENTRYP PFNGLCOLORP4UIPROC)(GLenum type, GLuint color);
-GLAPI PFNGLCOLORP4UIPROC glad_glColorP4ui;
-#define glColorP4ui glad_glColorP4ui
-typedef void (APIENTRYP PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint *color);
-GLAPI PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
-#define glColorP4uiv glad_glColorP4uiv
-typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color);
-GLAPI PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
-#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
-typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint *color);
-GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
-#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
-#endif
-#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
-#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
-#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
-#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
-#define GL_DEBUG_SOURCE_API_ARB 0x8246
-#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
-#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
-#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
-#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
-#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
-#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
-#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
-#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
-#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
-#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
-#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
-#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
-#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
-#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
-#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
-#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
-#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
-#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
-#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
-#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
-#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
-#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
-#define GL_MAX_SAMPLES_EXT 0x8D57
-#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
-#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
-#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
-#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
-#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
-#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
-#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
-#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
-#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
-#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
-#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
-#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
-#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
-#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
-#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
-#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
-#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
-#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
-#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
-#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
-#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
-#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
-#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
-#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
-#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
-#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
-#define GL_FRAMEBUFFER_EXT 0x8D40
-#define GL_RENDERBUFFER_EXT 0x8D41
-#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
-#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
-#define GL_STENCIL_INDEX1_EXT 0x8D46
-#define GL_STENCIL_INDEX4_EXT 0x8D47
-#define GL_STENCIL_INDEX8_EXT 0x8D48
-#define GL_STENCIL_INDEX16_EXT 0x8D49
-#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
-#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
-#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
-#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
-#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
-#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
-#define GL_MAX_VIEWS_OVR 0x9631
-#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
-#ifndef GL_ARB_debug_output
-#define GL_ARB_debug_output 1
-GLAPI int GLAD_GL_ARB_debug_output;
-typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
-GLAPI PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB;
-#define glDebugMessageControlARB glad_glDebugMessageControlARB
-typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
-GLAPI PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB;
-#define glDebugMessageInsertARB glad_glDebugMessageInsertARB
-typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void *userParam);
-GLAPI PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB;
-#define glDebugMessageCallbackARB glad_glDebugMessageCallbackARB
-typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
-GLAPI PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
-#define glGetDebugMessageLogARB glad_glGetDebugMessageLogARB
-#endif
-#ifndef GL_ARB_framebuffer_object
-#define GL_ARB_framebuffer_object 1
-GLAPI int GLAD_GL_ARB_framebuffer_object;
-#endif
-#ifndef GL_EXT_framebuffer_blit
-#define GL_EXT_framebuffer_blit 1
-GLAPI int GLAD_GL_EXT_framebuffer_blit;
-typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-GLAPI PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT;
-#define glBlitFramebufferEXT glad_glBlitFramebufferEXT
-#endif
-#ifndef GL_EXT_framebuffer_multisample
-#define GL_EXT_framebuffer_multisample 1
-GLAPI int GLAD_GL_EXT_framebuffer_multisample;
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
-#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
-#endif
-#ifndef GL_EXT_framebuffer_object
-#define GL_EXT_framebuffer_object 1
-GLAPI int GLAD_GL_EXT_framebuffer_object;
-typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer);
-GLAPI PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT;
-#define glIsRenderbufferEXT glad_glIsRenderbufferEXT
-typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer);
-GLAPI PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT;
-#define glBindRenderbufferEXT glad_glBindRenderbufferEXT
-typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint *renderbuffers);
-GLAPI PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT;
-#define glDeleteRenderbuffersEXT glad_glDeleteRenderbuffersEXT
-typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint *renderbuffers);
-GLAPI PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT;
-#define glGenRenderbuffersEXT glad_glGenRenderbuffersEXT
-typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-GLAPI PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT;
-#define glRenderbufferStorageEXT glad_glRenderbufferStorageEXT
-typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint *params);
-GLAPI PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT;
-#define glGetRenderbufferParameterivEXT glad_glGetRenderbufferParameterivEXT
-typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer);
-GLAPI PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT;
-#define glIsFramebufferEXT glad_glIsFramebufferEXT
-typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
-GLAPI PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT;
-#define glBindFramebufferEXT glad_glBindFramebufferEXT
-typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint *framebuffers);
-GLAPI PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT;
-#define glDeleteFramebuffersEXT glad_glDeleteFramebuffersEXT
-typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint *framebuffers);
-GLAPI PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT;
-#define glGenFramebuffersEXT glad_glGenFramebuffersEXT
-typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
-GLAPI PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT;
-#define glCheckFramebufferStatusEXT glad_glCheckFramebufferStatusEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT;
-#define glFramebufferTexture1DEXT glad_glFramebufferTexture1DEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GLAPI PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT;
-#define glFramebufferTexture2DEXT glad_glFramebufferTexture2DEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-GLAPI PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT;
-#define glFramebufferTexture3DEXT glad_glFramebufferTexture3DEXT
-typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-GLAPI PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT;
-#define glFramebufferRenderbufferEXT glad_glFramebufferRenderbufferEXT
-typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT;
-#define glGetFramebufferAttachmentParameterivEXT glad_glGetFramebufferAttachmentParameterivEXT
-typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC)(GLenum target);
-GLAPI PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT;
-#define glGenerateMipmapEXT glad_glGenerateMipmapEXT
-#endif
-#ifndef GL_OVR_multiview
-#define GL_OVR_multiview 1
-GLAPI int GLAD_GL_OVR_multiview;
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
-GLAPI PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glFramebufferTextureMultiviewOVR;
-#define glFramebufferTextureMultiviewOVR glad_glFramebufferTextureMultiviewOVR
-#endif
-#ifndef GL_OVR_multiview2
-#define GL_OVR_multiview2 1
-GLAPI int GLAD_GL_OVR_multiview2;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/glad/glad/glx.h b/thirdparty/glad/glad/glx.h
new file mode 100644
index 0000000000..ac115fa63b
--- /dev/null
+++ b/thirdparty/glad/glad/glx.h
@@ -0,0 +1,605 @@
+/**
+ * Loader generated by glad 2.0.2 on Tue Nov 15 09:49:49 2022
+ *
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ *
+ * Generator: C/C++
+ * Specification: glx
+ * Extensions: 6
+ *
+ * APIs:
+ * - glx=1.4
+ *
+ * Options:
+ * - ALIAS = False
+ * - DEBUG = False
+ * - HEADER_ONLY = False
+ * - LOADER = True
+ * - MX = False
+ * - ON_DEMAND = False
+ *
+ * Commandline:
+ * --api='glx=1.4' --extensions='GLX_ARB_create_context,GLX_ARB_create_context_profile,GLX_ARB_get_proc_address,GLX_EXT_swap_control,GLX_MESA_swap_control,GLX_SGI_swap_control' c --loader
+ *
+ * Online:
+ * http://glad.sh/#api=glx%3D1.4&extensions=GLX_ARB_create_context%2CGLX_ARB_create_context_profile%2CGLX_ARB_get_proc_address%2CGLX_EXT_swap_control%2CGLX_MESA_swap_control%2CGLX_SGI_swap_control&generator=c&options=LOADER
+ *
+ */
+
+#ifndef GLAD_GLX_H_
+#define GLAD_GLX_H_
+
+#ifdef GLX_H
+ #error GLX header already included (API: glx), remove previous include!
+#endif
+#define GLX_H 1
+
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <glad/gl.h>
+
+#define GLAD_GLX
+#define GLAD_OPTION_GLX_LOADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+ #define GLAD_PLATFORM_WIN32 1
+ #else
+ #define GLAD_PLATFORM_WIN32 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+ #ifdef __APPLE__
+ #define GLAD_PLATFORM_APPLE 1
+ #else
+ #define GLAD_PLATFORM_APPLE 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+ #ifdef __EMSCRIPTEN__
+ #define GLAD_PLATFORM_EMSCRIPTEN 1
+ #else
+ #define GLAD_PLATFORM_EMSCRIPTEN 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+ #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+ #ifdef __has_include
+ #if __has_include(<winapifamily.h>)
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #endif
+
+ #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+ #include <winapifamily.h>
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define GLAD_PLATFORM_UWP 1
+ #endif
+ #endif
+
+ #ifndef GLAD_PLATFORM_UWP
+ #define GLAD_PLATFORM_UWP 0
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define GLAD_GNUC_EXTENSION __extension__
+#else
+ #define GLAD_GNUC_EXTENSION
+#endif
+
+#define GLAD_UNUSED(x) (void)(x)
+
+#ifndef GLAD_API_CALL
+ #if defined(GLAD_API_CALL_EXPORT)
+ #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+ #if defined(GLAD_API_CALL_EXPORT_BUILD)
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllexport) extern
+ #endif
+ #else
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllimport) extern
+ #endif
+ #endif
+ #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+ #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+#endif
+
+#ifdef APIENTRY
+ #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+ #define GLAD_API_PTR __stdcall
+#else
+ #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.2"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GLX_ACCUM_ALPHA_SIZE 17
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ALPHA_SIZE 11
+#define GLX_AUX_BUFFERS 7
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_ENUM 7
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_VISUAL 4
+#define GLX_BLUE_SIZE 10
+#define GLX_BUFFER_SIZE 2
+#define GLX_BufferSwapComplete 1
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define GLX_DAMAGED 0x8020
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_DEPTH_SIZE 12
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_DONT_CARE 0xFFFFFFFF
+#define GLX_DOUBLEBUFFER 5
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_EVENT_MASK 0x801F
+#define GLX_EXTENSIONS 0x3
+#define GLX_EXTENSION_NAME "GLX"
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_GREEN_SIZE 9
+#define GLX_HEIGHT 0x801E
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_LEVEL 3
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#define GLX_NONE 0x8000
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_NO_EXTENSION 3
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_PbufferClobber 0
+#define GLX_RED_SIZE 8
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_RGBA 4
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_SAMPLES 100001
+#define GLX_SAMPLE_BUFFERS 100000
+#define GLX_SAVED 0x8021
+#define GLX_SCREEN 0x800C
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_STENCIL_SIZE 13
+#define GLX_STEREO 6
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_USE_GL 1
+#define GLX_VENDOR 0x1
+#define GLX_VERSION 0x2
+#define GLX_VISUAL_ID 0x800B
+#define GLX_WIDTH 0x801D
+#define GLX_WINDOW 0x8022
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_X_VISUAL_TYPE 0x22
+#define __GLX_NUMBER_EVENTS 17
+
+
+#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GLX_OML_sync_control extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include <inttypes.h>
+#endif
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+
+#else
+
+#endif
+
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+
+#else
+
+#endif
+
+
+
+
+
+
+
+typedef XID GLXFBConfigID;
+typedef struct __GLXFBConfigRec *GLXFBConfig;
+typedef XID GLXContextID;
+typedef struct __GLXcontextRec *GLXContext;
+typedef XID GLXPixmap;
+typedef XID GLXDrawable;
+typedef XID GLXWindow;
+typedef XID GLXPbuffer;
+typedef void (GLAD_API_PTR *__GLXextFuncPtr)(void);
+typedef XID GLXVideoCaptureDeviceNV;
+typedef unsigned int GLXVideoDeviceNV;
+typedef XID GLXVideoSourceSGIX;
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+typedef XID GLXPbufferSGIX;
+typedef struct {
+ int event_type; /* GLX_DAMAGED or GLX_SAVED */
+ int draw_type; /* GLX_WINDOW or GLX_PBUFFER */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came for SendEvent request */
+ Display *display; /* display the event was read from */
+ GLXDrawable drawable; /* XID of Drawable */
+ unsigned int buffer_mask; /* mask indicating which buffers are affected */
+ unsigned int aux_buffer; /* which aux buffer was affected */
+ int x, y;
+ int width, height;
+ int count; /* if nonzero, at least this many more */
+} GLXPbufferClobberEvent;
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ GLXDrawable drawable; /* drawable on which event was requested in event mask */
+ int event_type;
+ int64_t ust;
+ int64_t msc;
+ int64_t sbc;
+} GLXBufferSwapComplete;
+typedef union __GLXEvent {
+ GLXPbufferClobberEvent glxpbufferclobber;
+ GLXBufferSwapComplete glxbufferswapcomplete;
+ long pad[24];
+} GLXEvent;
+typedef struct {
+ int type;
+ unsigned long serial;
+ Bool send_event;
+ Display *display;
+ int extension;
+ int evtype;
+ GLXDrawable window;
+ Bool stereo_tree;
+} GLXStereoNotifyEventEXT;
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came for SendEvent request */
+ Display *display; /* display the event was read from */
+ GLXDrawable drawable; /* i.d. of Drawable */
+ int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */
+ int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */
+ unsigned int mask; /* mask indicating which buffers are affected*/
+ int x, y;
+ int width, height;
+ int count; /* if nonzero, at least this many more */
+} GLXBufferClobberEventSGIX;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int networkId;
+} GLXHyperpipeNetworkSGIX;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int channel;
+ unsigned int participationType;
+ int timeSlice;
+} GLXHyperpipeConfigSGIX;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int srcXOrigin, srcYOrigin, srcWidth, srcHeight;
+ int destXOrigin, destYOrigin, destWidth, destHeight;
+} GLXPipeRect;
+typedef struct {
+ char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ int XOrigin, YOrigin, maxHeight, maxWidth;
+} GLXPipeRectLimits;
+
+
+#define GLX_VERSION_1_0 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_0;
+#define GLX_VERSION_1_1 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_1;
+#define GLX_VERSION_1_2 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_2;
+#define GLX_VERSION_1_3 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_3;
+#define GLX_VERSION_1_4 1
+GLAD_API_CALL int GLAD_GLX_VERSION_1_4;
+#define GLX_ARB_create_context 1
+GLAD_API_CALL int GLAD_GLX_ARB_create_context;
+#define GLX_ARB_create_context_profile 1
+GLAD_API_CALL int GLAD_GLX_ARB_create_context_profile;
+#define GLX_ARB_get_proc_address 1
+GLAD_API_CALL int GLAD_GLX_ARB_get_proc_address;
+#define GLX_EXT_swap_control 1
+GLAD_API_CALL int GLAD_GLX_EXT_swap_control;
+#define GLX_MESA_swap_control 1
+GLAD_API_CALL int GLAD_GLX_MESA_swap_control;
+#define GLX_SGI_swap_control 1
+GLAD_API_CALL int GLAD_GLX_SGI_swap_control;
+
+
+typedef GLXFBConfig * (GLAD_API_PTR *PFNGLXCHOOSEFBCONFIGPROC)(Display * dpy, int screen, const int * attrib_list, int * nelements);
+typedef XVisualInfo * (GLAD_API_PTR *PFNGLXCHOOSEVISUALPROC)(Display * dpy, int screen, int * attribList);
+typedef void (GLAD_API_PTR *PFNGLXCOPYCONTEXTPROC)(Display * dpy, GLXContext src, GLXContext dst, unsigned long mask);
+typedef GLXContext (GLAD_API_PTR *PFNGLXCREATECONTEXTPROC)(Display * dpy, XVisualInfo * vis, GLXContext shareList, Bool direct);
+typedef GLXContext (GLAD_API_PTR *PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display * dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int * attrib_list);
+typedef GLXPixmap (GLAD_API_PTR *PFNGLXCREATEGLXPIXMAPPROC)(Display * dpy, XVisualInfo * visual, Pixmap pixmap);
+typedef GLXContext (GLAD_API_PTR *PFNGLXCREATENEWCONTEXTPROC)(Display * dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPbuffer (GLAD_API_PTR *PFNGLXCREATEPBUFFERPROC)(Display * dpy, GLXFBConfig config, const int * attrib_list);
+typedef GLXPixmap (GLAD_API_PTR *PFNGLXCREATEPIXMAPPROC)(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list);
+typedef GLXWindow (GLAD_API_PTR *PFNGLXCREATEWINDOWPROC)(Display * dpy, GLXFBConfig config, Window win, const int * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYCONTEXTPROC)(Display * dpy, GLXContext ctx);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYGLXPIXMAPPROC)(Display * dpy, GLXPixmap pixmap);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYPBUFFERPROC)(Display * dpy, GLXPbuffer pbuf);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYPIXMAPPROC)(Display * dpy, GLXPixmap pixmap);
+typedef void (GLAD_API_PTR *PFNGLXDESTROYWINDOWPROC)(Display * dpy, GLXWindow win);
+typedef const char * (GLAD_API_PTR *PFNGLXGETCLIENTSTRINGPROC)(Display * dpy, int name);
+typedef int (GLAD_API_PTR *PFNGLXGETCONFIGPROC)(Display * dpy, XVisualInfo * visual, int attrib, int * value);
+typedef GLXContext (GLAD_API_PTR *PFNGLXGETCURRENTCONTEXTPROC)(void);
+typedef Display * (GLAD_API_PTR *PFNGLXGETCURRENTDISPLAYPROC)(void);
+typedef GLXDrawable (GLAD_API_PTR *PFNGLXGETCURRENTDRAWABLEPROC)(void);
+typedef GLXDrawable (GLAD_API_PTR *PFNGLXGETCURRENTREADDRAWABLEPROC)(void);
+typedef int (GLAD_API_PTR *PFNGLXGETFBCONFIGATTRIBPROC)(Display * dpy, GLXFBConfig config, int attribute, int * value);
+typedef GLXFBConfig * (GLAD_API_PTR *PFNGLXGETFBCONFIGSPROC)(Display * dpy, int screen, int * nelements);
+typedef __GLXextFuncPtr (GLAD_API_PTR *PFNGLXGETPROCADDRESSPROC)(const GLubyte * procName);
+typedef __GLXextFuncPtr (GLAD_API_PTR *PFNGLXGETPROCADDRESSARBPROC)(const GLubyte * procName);
+typedef void (GLAD_API_PTR *PFNGLXGETSELECTEDEVENTPROC)(Display * dpy, GLXDrawable draw, unsigned long * event_mask);
+typedef int (GLAD_API_PTR *PFNGLXGETSWAPINTERVALMESAPROC)(void);
+typedef XVisualInfo * (GLAD_API_PTR *PFNGLXGETVISUALFROMFBCONFIGPROC)(Display * dpy, GLXFBConfig config);
+typedef Bool (GLAD_API_PTR *PFNGLXISDIRECTPROC)(Display * dpy, GLXContext ctx);
+typedef Bool (GLAD_API_PTR *PFNGLXMAKECONTEXTCURRENTPROC)(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef Bool (GLAD_API_PTR *PFNGLXMAKECURRENTPROC)(Display * dpy, GLXDrawable drawable, GLXContext ctx);
+typedef int (GLAD_API_PTR *PFNGLXQUERYCONTEXTPROC)(Display * dpy, GLXContext ctx, int attribute, int * value);
+typedef void (GLAD_API_PTR *PFNGLXQUERYDRAWABLEPROC)(Display * dpy, GLXDrawable draw, int attribute, unsigned int * value);
+typedef Bool (GLAD_API_PTR *PFNGLXQUERYEXTENSIONPROC)(Display * dpy, int * errorb, int * event);
+typedef const char * (GLAD_API_PTR *PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display * dpy, int screen);
+typedef const char * (GLAD_API_PTR *PFNGLXQUERYSERVERSTRINGPROC)(Display * dpy, int screen, int name);
+typedef Bool (GLAD_API_PTR *PFNGLXQUERYVERSIONPROC)(Display * dpy, int * maj, int * min);
+typedef void (GLAD_API_PTR *PFNGLXSELECTEVENTPROC)(Display * dpy, GLXDrawable draw, unsigned long event_mask);
+typedef void (GLAD_API_PTR *PFNGLXSWAPBUFFERSPROC)(Display * dpy, GLXDrawable drawable);
+typedef void (GLAD_API_PTR *PFNGLXSWAPINTERVALEXTPROC)(Display * dpy, GLXDrawable drawable, int interval);
+typedef int (GLAD_API_PTR *PFNGLXSWAPINTERVALMESAPROC)(unsigned int interval);
+typedef int (GLAD_API_PTR *PFNGLXSWAPINTERVALSGIPROC)(int interval);
+typedef void (GLAD_API_PTR *PFNGLXUSEXFONTPROC)(Font font, int first, int count, int list);
+typedef void (GLAD_API_PTR *PFNGLXWAITGLPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLXWAITXPROC)(void);
+
+GLAD_API_CALL PFNGLXCHOOSEFBCONFIGPROC glad_glXChooseFBConfig;
+#define glXChooseFBConfig glad_glXChooseFBConfig
+GLAD_API_CALL PFNGLXCHOOSEVISUALPROC glad_glXChooseVisual;
+#define glXChooseVisual glad_glXChooseVisual
+GLAD_API_CALL PFNGLXCOPYCONTEXTPROC glad_glXCopyContext;
+#define glXCopyContext glad_glXCopyContext
+GLAD_API_CALL PFNGLXCREATECONTEXTPROC glad_glXCreateContext;
+#define glXCreateContext glad_glXCreateContext
+GLAD_API_CALL PFNGLXCREATECONTEXTATTRIBSARBPROC glad_glXCreateContextAttribsARB;
+#define glXCreateContextAttribsARB glad_glXCreateContextAttribsARB
+GLAD_API_CALL PFNGLXCREATEGLXPIXMAPPROC glad_glXCreateGLXPixmap;
+#define glXCreateGLXPixmap glad_glXCreateGLXPixmap
+GLAD_API_CALL PFNGLXCREATENEWCONTEXTPROC glad_glXCreateNewContext;
+#define glXCreateNewContext glad_glXCreateNewContext
+GLAD_API_CALL PFNGLXCREATEPBUFFERPROC glad_glXCreatePbuffer;
+#define glXCreatePbuffer glad_glXCreatePbuffer
+GLAD_API_CALL PFNGLXCREATEPIXMAPPROC glad_glXCreatePixmap;
+#define glXCreatePixmap glad_glXCreatePixmap
+GLAD_API_CALL PFNGLXCREATEWINDOWPROC glad_glXCreateWindow;
+#define glXCreateWindow glad_glXCreateWindow
+GLAD_API_CALL PFNGLXDESTROYCONTEXTPROC glad_glXDestroyContext;
+#define glXDestroyContext glad_glXDestroyContext
+GLAD_API_CALL PFNGLXDESTROYGLXPIXMAPPROC glad_glXDestroyGLXPixmap;
+#define glXDestroyGLXPixmap glad_glXDestroyGLXPixmap
+GLAD_API_CALL PFNGLXDESTROYPBUFFERPROC glad_glXDestroyPbuffer;
+#define glXDestroyPbuffer glad_glXDestroyPbuffer
+GLAD_API_CALL PFNGLXDESTROYPIXMAPPROC glad_glXDestroyPixmap;
+#define glXDestroyPixmap glad_glXDestroyPixmap
+GLAD_API_CALL PFNGLXDESTROYWINDOWPROC glad_glXDestroyWindow;
+#define glXDestroyWindow glad_glXDestroyWindow
+GLAD_API_CALL PFNGLXGETCLIENTSTRINGPROC glad_glXGetClientString;
+#define glXGetClientString glad_glXGetClientString
+GLAD_API_CALL PFNGLXGETCONFIGPROC glad_glXGetConfig;
+#define glXGetConfig glad_glXGetConfig
+GLAD_API_CALL PFNGLXGETCURRENTCONTEXTPROC glad_glXGetCurrentContext;
+#define glXGetCurrentContext glad_glXGetCurrentContext
+GLAD_API_CALL PFNGLXGETCURRENTDISPLAYPROC glad_glXGetCurrentDisplay;
+#define glXGetCurrentDisplay glad_glXGetCurrentDisplay
+GLAD_API_CALL PFNGLXGETCURRENTDRAWABLEPROC glad_glXGetCurrentDrawable;
+#define glXGetCurrentDrawable glad_glXGetCurrentDrawable
+GLAD_API_CALL PFNGLXGETCURRENTREADDRAWABLEPROC glad_glXGetCurrentReadDrawable;
+#define glXGetCurrentReadDrawable glad_glXGetCurrentReadDrawable
+GLAD_API_CALL PFNGLXGETFBCONFIGATTRIBPROC glad_glXGetFBConfigAttrib;
+#define glXGetFBConfigAttrib glad_glXGetFBConfigAttrib
+GLAD_API_CALL PFNGLXGETFBCONFIGSPROC glad_glXGetFBConfigs;
+#define glXGetFBConfigs glad_glXGetFBConfigs
+GLAD_API_CALL PFNGLXGETPROCADDRESSPROC glad_glXGetProcAddress;
+#define glXGetProcAddress glad_glXGetProcAddress
+GLAD_API_CALL PFNGLXGETPROCADDRESSARBPROC glad_glXGetProcAddressARB;
+#define glXGetProcAddressARB glad_glXGetProcAddressARB
+GLAD_API_CALL PFNGLXGETSELECTEDEVENTPROC glad_glXGetSelectedEvent;
+#define glXGetSelectedEvent glad_glXGetSelectedEvent
+GLAD_API_CALL PFNGLXGETSWAPINTERVALMESAPROC glad_glXGetSwapIntervalMESA;
+#define glXGetSwapIntervalMESA glad_glXGetSwapIntervalMESA
+GLAD_API_CALL PFNGLXGETVISUALFROMFBCONFIGPROC glad_glXGetVisualFromFBConfig;
+#define glXGetVisualFromFBConfig glad_glXGetVisualFromFBConfig
+GLAD_API_CALL PFNGLXISDIRECTPROC glad_glXIsDirect;
+#define glXIsDirect glad_glXIsDirect
+GLAD_API_CALL PFNGLXMAKECONTEXTCURRENTPROC glad_glXMakeContextCurrent;
+#define glXMakeContextCurrent glad_glXMakeContextCurrent
+GLAD_API_CALL PFNGLXMAKECURRENTPROC glad_glXMakeCurrent;
+#define glXMakeCurrent glad_glXMakeCurrent
+GLAD_API_CALL PFNGLXQUERYCONTEXTPROC glad_glXQueryContext;
+#define glXQueryContext glad_glXQueryContext
+GLAD_API_CALL PFNGLXQUERYDRAWABLEPROC glad_glXQueryDrawable;
+#define glXQueryDrawable glad_glXQueryDrawable
+GLAD_API_CALL PFNGLXQUERYEXTENSIONPROC glad_glXQueryExtension;
+#define glXQueryExtension glad_glXQueryExtension
+GLAD_API_CALL PFNGLXQUERYEXTENSIONSSTRINGPROC glad_glXQueryExtensionsString;
+#define glXQueryExtensionsString glad_glXQueryExtensionsString
+GLAD_API_CALL PFNGLXQUERYSERVERSTRINGPROC glad_glXQueryServerString;
+#define glXQueryServerString glad_glXQueryServerString
+GLAD_API_CALL PFNGLXQUERYVERSIONPROC glad_glXQueryVersion;
+#define glXQueryVersion glad_glXQueryVersion
+GLAD_API_CALL PFNGLXSELECTEVENTPROC glad_glXSelectEvent;
+#define glXSelectEvent glad_glXSelectEvent
+GLAD_API_CALL PFNGLXSWAPBUFFERSPROC glad_glXSwapBuffers;
+#define glXSwapBuffers glad_glXSwapBuffers
+GLAD_API_CALL PFNGLXSWAPINTERVALEXTPROC glad_glXSwapIntervalEXT;
+#define glXSwapIntervalEXT glad_glXSwapIntervalEXT
+GLAD_API_CALL PFNGLXSWAPINTERVALMESAPROC glad_glXSwapIntervalMESA;
+#define glXSwapIntervalMESA glad_glXSwapIntervalMESA
+GLAD_API_CALL PFNGLXSWAPINTERVALSGIPROC glad_glXSwapIntervalSGI;
+#define glXSwapIntervalSGI glad_glXSwapIntervalSGI
+GLAD_API_CALL PFNGLXUSEXFONTPROC glad_glXUseXFont;
+#define glXUseXFont glad_glXUseXFont
+GLAD_API_CALL PFNGLXWAITGLPROC glad_glXWaitGL;
+#define glXWaitGL glad_glXWaitGL
+GLAD_API_CALL PFNGLXWAITXPROC glad_glXWaitX;
+#define glXWaitX glad_glXWaitX
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLXUserPtr(Display *display, int screen, GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGLX(Display *display, int screen, GLADloadfunc load);
+
+#ifdef GLAD_GLX
+
+GLAD_API_CALL int gladLoaderLoadGLX(Display *display, int screen);
+
+GLAD_API_CALL void gladLoaderUnloadGLX(void);
+
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/thirdparty/glad/glx.c b/thirdparty/glad/glx.c
new file mode 100644
index 0000000000..6391027db2
--- /dev/null
+++ b/thirdparty/glad/glx.c
@@ -0,0 +1,395 @@
+/**
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/glx.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int GLAD_GLX_VERSION_1_0 = 0;
+int GLAD_GLX_VERSION_1_1 = 0;
+int GLAD_GLX_VERSION_1_2 = 0;
+int GLAD_GLX_VERSION_1_3 = 0;
+int GLAD_GLX_VERSION_1_4 = 0;
+int GLAD_GLX_ARB_create_context = 0;
+int GLAD_GLX_ARB_create_context_profile = 0;
+int GLAD_GLX_ARB_get_proc_address = 0;
+int GLAD_GLX_EXT_swap_control = 0;
+int GLAD_GLX_MESA_swap_control = 0;
+int GLAD_GLX_SGI_swap_control = 0;
+
+
+
+PFNGLXCHOOSEFBCONFIGPROC glad_glXChooseFBConfig = NULL;
+PFNGLXCHOOSEVISUALPROC glad_glXChooseVisual = NULL;
+PFNGLXCOPYCONTEXTPROC glad_glXCopyContext = NULL;
+PFNGLXCREATECONTEXTPROC glad_glXCreateContext = NULL;
+PFNGLXCREATECONTEXTATTRIBSARBPROC glad_glXCreateContextAttribsARB = NULL;
+PFNGLXCREATEGLXPIXMAPPROC glad_glXCreateGLXPixmap = NULL;
+PFNGLXCREATENEWCONTEXTPROC glad_glXCreateNewContext = NULL;
+PFNGLXCREATEPBUFFERPROC glad_glXCreatePbuffer = NULL;
+PFNGLXCREATEPIXMAPPROC glad_glXCreatePixmap = NULL;
+PFNGLXCREATEWINDOWPROC glad_glXCreateWindow = NULL;
+PFNGLXDESTROYCONTEXTPROC glad_glXDestroyContext = NULL;
+PFNGLXDESTROYGLXPIXMAPPROC glad_glXDestroyGLXPixmap = NULL;
+PFNGLXDESTROYPBUFFERPROC glad_glXDestroyPbuffer = NULL;
+PFNGLXDESTROYPIXMAPPROC glad_glXDestroyPixmap = NULL;
+PFNGLXDESTROYWINDOWPROC glad_glXDestroyWindow = NULL;
+PFNGLXGETCLIENTSTRINGPROC glad_glXGetClientString = NULL;
+PFNGLXGETCONFIGPROC glad_glXGetConfig = NULL;
+PFNGLXGETCURRENTCONTEXTPROC glad_glXGetCurrentContext = NULL;
+PFNGLXGETCURRENTDISPLAYPROC glad_glXGetCurrentDisplay = NULL;
+PFNGLXGETCURRENTDRAWABLEPROC glad_glXGetCurrentDrawable = NULL;
+PFNGLXGETCURRENTREADDRAWABLEPROC glad_glXGetCurrentReadDrawable = NULL;
+PFNGLXGETFBCONFIGATTRIBPROC glad_glXGetFBConfigAttrib = NULL;
+PFNGLXGETFBCONFIGSPROC glad_glXGetFBConfigs = NULL;
+PFNGLXGETPROCADDRESSPROC glad_glXGetProcAddress = NULL;
+PFNGLXGETPROCADDRESSARBPROC glad_glXGetProcAddressARB = NULL;
+PFNGLXGETSELECTEDEVENTPROC glad_glXGetSelectedEvent = NULL;
+PFNGLXGETSWAPINTERVALMESAPROC glad_glXGetSwapIntervalMESA = NULL;
+PFNGLXGETVISUALFROMFBCONFIGPROC glad_glXGetVisualFromFBConfig = NULL;
+PFNGLXISDIRECTPROC glad_glXIsDirect = NULL;
+PFNGLXMAKECONTEXTCURRENTPROC glad_glXMakeContextCurrent = NULL;
+PFNGLXMAKECURRENTPROC glad_glXMakeCurrent = NULL;
+PFNGLXQUERYCONTEXTPROC glad_glXQueryContext = NULL;
+PFNGLXQUERYDRAWABLEPROC glad_glXQueryDrawable = NULL;
+PFNGLXQUERYEXTENSIONPROC glad_glXQueryExtension = NULL;
+PFNGLXQUERYEXTENSIONSSTRINGPROC glad_glXQueryExtensionsString = NULL;
+PFNGLXQUERYSERVERSTRINGPROC glad_glXQueryServerString = NULL;
+PFNGLXQUERYVERSIONPROC glad_glXQueryVersion = NULL;
+PFNGLXSELECTEVENTPROC glad_glXSelectEvent = NULL;
+PFNGLXSWAPBUFFERSPROC glad_glXSwapBuffers = NULL;
+PFNGLXSWAPINTERVALEXTPROC glad_glXSwapIntervalEXT = NULL;
+PFNGLXSWAPINTERVALMESAPROC glad_glXSwapIntervalMESA = NULL;
+PFNGLXSWAPINTERVALSGIPROC glad_glXSwapIntervalSGI = NULL;
+PFNGLXUSEXFONTPROC glad_glXUseXFont = NULL;
+PFNGLXWAITGLPROC glad_glXWaitGL = NULL;
+PFNGLXWAITXPROC glad_glXWaitX = NULL;
+
+
+static void glad_glx_load_GLX_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_0) return;
+ glad_glXChooseVisual = (PFNGLXCHOOSEVISUALPROC) load(userptr, "glXChooseVisual");
+ glad_glXCopyContext = (PFNGLXCOPYCONTEXTPROC) load(userptr, "glXCopyContext");
+ glad_glXCreateContext = (PFNGLXCREATECONTEXTPROC) load(userptr, "glXCreateContext");
+ glad_glXCreateGLXPixmap = (PFNGLXCREATEGLXPIXMAPPROC) load(userptr, "glXCreateGLXPixmap");
+ glad_glXDestroyContext = (PFNGLXDESTROYCONTEXTPROC) load(userptr, "glXDestroyContext");
+ glad_glXDestroyGLXPixmap = (PFNGLXDESTROYGLXPIXMAPPROC) load(userptr, "glXDestroyGLXPixmap");
+ glad_glXGetConfig = (PFNGLXGETCONFIGPROC) load(userptr, "glXGetConfig");
+ glad_glXGetCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) load(userptr, "glXGetCurrentContext");
+ glad_glXGetCurrentDrawable = (PFNGLXGETCURRENTDRAWABLEPROC) load(userptr, "glXGetCurrentDrawable");
+ glad_glXIsDirect = (PFNGLXISDIRECTPROC) load(userptr, "glXIsDirect");
+ glad_glXMakeCurrent = (PFNGLXMAKECURRENTPROC) load(userptr, "glXMakeCurrent");
+ glad_glXQueryExtension = (PFNGLXQUERYEXTENSIONPROC) load(userptr, "glXQueryExtension");
+ glad_glXQueryVersion = (PFNGLXQUERYVERSIONPROC) load(userptr, "glXQueryVersion");
+ glad_glXSwapBuffers = (PFNGLXSWAPBUFFERSPROC) load(userptr, "glXSwapBuffers");
+ glad_glXUseXFont = (PFNGLXUSEXFONTPROC) load(userptr, "glXUseXFont");
+ glad_glXWaitGL = (PFNGLXWAITGLPROC) load(userptr, "glXWaitGL");
+ glad_glXWaitX = (PFNGLXWAITXPROC) load(userptr, "glXWaitX");
+}
+static void glad_glx_load_GLX_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_1) return;
+ glad_glXGetClientString = (PFNGLXGETCLIENTSTRINGPROC) load(userptr, "glXGetClientString");
+ glad_glXQueryExtensionsString = (PFNGLXQUERYEXTENSIONSSTRINGPROC) load(userptr, "glXQueryExtensionsString");
+ glad_glXQueryServerString = (PFNGLXQUERYSERVERSTRINGPROC) load(userptr, "glXQueryServerString");
+}
+static void glad_glx_load_GLX_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_2) return;
+ glad_glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC) load(userptr, "glXGetCurrentDisplay");
+}
+static void glad_glx_load_GLX_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_3) return;
+ glad_glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) load(userptr, "glXChooseFBConfig");
+ glad_glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC) load(userptr, "glXCreateNewContext");
+ glad_glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC) load(userptr, "glXCreatePbuffer");
+ glad_glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC) load(userptr, "glXCreatePixmap");
+ glad_glXCreateWindow = (PFNGLXCREATEWINDOWPROC) load(userptr, "glXCreateWindow");
+ glad_glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) load(userptr, "glXDestroyPbuffer");
+ glad_glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC) load(userptr, "glXDestroyPixmap");
+ glad_glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC) load(userptr, "glXDestroyWindow");
+ glad_glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC) load(userptr, "glXGetCurrentReadDrawable");
+ glad_glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC) load(userptr, "glXGetFBConfigAttrib");
+ glad_glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC) load(userptr, "glXGetFBConfigs");
+ glad_glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC) load(userptr, "glXGetSelectedEvent");
+ glad_glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) load(userptr, "glXGetVisualFromFBConfig");
+ glad_glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC) load(userptr, "glXMakeContextCurrent");
+ glad_glXQueryContext = (PFNGLXQUERYCONTEXTPROC) load(userptr, "glXQueryContext");
+ glad_glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC) load(userptr, "glXQueryDrawable");
+ glad_glXSelectEvent = (PFNGLXSELECTEVENTPROC) load(userptr, "glXSelectEvent");
+}
+static void glad_glx_load_GLX_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_VERSION_1_4) return;
+ glad_glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC) load(userptr, "glXGetProcAddress");
+}
+static void glad_glx_load_GLX_ARB_create_context( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_ARB_create_context) return;
+ glad_glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) load(userptr, "glXCreateContextAttribsARB");
+}
+static void glad_glx_load_GLX_ARB_get_proc_address( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_ARB_get_proc_address) return;
+ glad_glXGetProcAddressARB = (PFNGLXGETPROCADDRESSARBPROC) load(userptr, "glXGetProcAddressARB");
+}
+static void glad_glx_load_GLX_EXT_swap_control( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_EXT_swap_control) return;
+ glad_glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) load(userptr, "glXSwapIntervalEXT");
+}
+static void glad_glx_load_GLX_MESA_swap_control( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_MESA_swap_control) return;
+ glad_glXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) load(userptr, "glXGetSwapIntervalMESA");
+ glad_glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) load(userptr, "glXSwapIntervalMESA");
+}
+static void glad_glx_load_GLX_SGI_swap_control( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GLX_SGI_swap_control) return;
+ glad_glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) load(userptr, "glXSwapIntervalSGI");
+}
+
+
+
+static int glad_glx_has_extension(Display *display, int screen, const char *ext) {
+#ifndef GLX_VERSION_1_1
+ GLAD_UNUSED(display);
+ GLAD_UNUSED(screen);
+ GLAD_UNUSED(ext);
+#else
+ const char *terminator;
+ const char *loc;
+ const char *extensions;
+
+ if (glXQueryExtensionsString == NULL) {
+ return 0;
+ }
+
+ extensions = glXQueryExtensionsString(display, screen);
+
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL)
+ break;
+
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+#endif
+
+ return 0;
+}
+
+static GLADapiproc glad_glx_get_proc_from_userptr(void *userptr, const char* name) {
+ return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_glx_find_extensions(Display *display, int screen) {
+ GLAD_GLX_ARB_create_context = glad_glx_has_extension(display, screen, "GLX_ARB_create_context");
+ GLAD_GLX_ARB_create_context_profile = glad_glx_has_extension(display, screen, "GLX_ARB_create_context_profile");
+ GLAD_GLX_ARB_get_proc_address = glad_glx_has_extension(display, screen, "GLX_ARB_get_proc_address");
+ GLAD_GLX_EXT_swap_control = glad_glx_has_extension(display, screen, "GLX_EXT_swap_control");
+ GLAD_GLX_MESA_swap_control = glad_glx_has_extension(display, screen, "GLX_MESA_swap_control");
+ GLAD_GLX_SGI_swap_control = glad_glx_has_extension(display, screen, "GLX_SGI_swap_control");
+ return 1;
+}
+
+static int glad_glx_find_core_glx(Display **display, int *screen) {
+ int major = 0, minor = 0;
+ if(*display == NULL) {
+#ifdef GLAD_GLX_NO_X11
+ GLAD_UNUSED(screen);
+ return 0;
+#else
+ *display = XOpenDisplay(0);
+ if (*display == NULL) {
+ return 0;
+ }
+ *screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(*display));
+#endif
+ }
+ glXQueryVersion(*display, &major, &minor);
+ GLAD_GLX_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+ GLAD_GLX_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+ GLAD_GLX_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+ GLAD_GLX_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+ GLAD_GLX_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+ return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLXUserPtr(Display *display, int screen, GLADuserptrloadfunc load, void *userptr) {
+ int version;
+ glXQueryVersion = (PFNGLXQUERYVERSIONPROC) load(userptr, "glXQueryVersion");
+ if(glXQueryVersion == NULL) return 0;
+ version = glad_glx_find_core_glx(&display, &screen);
+
+ glad_glx_load_GLX_VERSION_1_0(load, userptr);
+ glad_glx_load_GLX_VERSION_1_1(load, userptr);
+ glad_glx_load_GLX_VERSION_1_2(load, userptr);
+ glad_glx_load_GLX_VERSION_1_3(load, userptr);
+ glad_glx_load_GLX_VERSION_1_4(load, userptr);
+
+ if (!glad_glx_find_extensions(display, screen)) return 0;
+ glad_glx_load_GLX_ARB_create_context(load, userptr);
+ glad_glx_load_GLX_ARB_get_proc_address(load, userptr);
+ glad_glx_load_GLX_EXT_swap_control(load, userptr);
+ glad_glx_load_GLX_MESA_swap_control(load, userptr);
+ glad_glx_load_GLX_SGI_swap_control(load, userptr);
+
+
+ return version;
+}
+
+int gladLoadGLX(Display *display, int screen, GLADloadfunc load) {
+ return gladLoadGLXUserPtr(display, screen, glad_glx_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+#ifdef GLAD_GLX
+
+#ifndef GLAD_LOADER_LIBRARY_C_
+#define GLAD_LOADER_LIBRARY_C_
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if GLAD_PLATFORM_WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+
+static void* glad_get_dlopen_handle(const char *lib_names[], int length) {
+ void *handle = NULL;
+ int i;
+
+ for (i = 0; i < length; ++i) {
+#if GLAD_PLATFORM_WIN32
+ #if GLAD_PLATFORM_UWP
+ size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR);
+ LPWSTR buffer = (LPWSTR) malloc(buffer_size);
+ if (buffer != NULL) {
+ int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size);
+ if (ret != 0) {
+ handle = (void*) LoadPackagedLibrary(buffer, 0);
+ }
+ free((void*) buffer);
+ }
+ #else
+ handle = (void*) LoadLibraryA(lib_names[i]);
+ #endif
+#else
+ handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL);
+#endif
+ if (handle != NULL) {
+ return handle;
+ }
+ }
+
+ return NULL;
+}
+
+static void glad_close_dlopen_handle(void* handle) {
+ if (handle != NULL) {
+#if GLAD_PLATFORM_WIN32
+ FreeLibrary((HMODULE) handle);
+#else
+ dlclose(handle);
+#endif
+ }
+}
+
+static GLADapiproc glad_dlsym_handle(void* handle, const char *name) {
+ if (handle == NULL) {
+ return NULL;
+ }
+
+#if GLAD_PLATFORM_WIN32
+ return (GLADapiproc) GetProcAddress((HMODULE) handle, name);
+#else
+ return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name);
+#endif
+}
+
+#endif /* GLAD_LOADER_LIBRARY_C_ */
+
+typedef void* (GLAD_API_PTR *GLADglxprocaddrfunc)(const char*);
+
+static GLADapiproc glad_glx_get_proc(void *userptr, const char *name) {
+ return GLAD_GNUC_EXTENSION ((GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static void* _glx_handle;
+
+static void* glad_glx_dlopen_handle(void) {
+ static const char *NAMES[] = {
+#if defined __CYGWIN__
+ "libGL-1.so",
+#endif
+ "libGL.so.1",
+ "libGL.so"
+ };
+
+ if (_glx_handle == NULL) {
+ _glx_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0]));
+ }
+
+ return _glx_handle;
+}
+
+int gladLoaderLoadGLX(Display *display, int screen) {
+ int version = 0;
+ void *handle = NULL;
+ int did_load = 0;
+ GLADglxprocaddrfunc loader;
+
+ did_load = _glx_handle == NULL;
+ handle = glad_glx_dlopen_handle();
+ if (handle != NULL) {
+ loader = (GLADglxprocaddrfunc) glad_dlsym_handle(handle, "glXGetProcAddressARB");
+ if (loader != NULL) {
+ version = gladLoadGLXUserPtr(display, screen, glad_glx_get_proc, GLAD_GNUC_EXTENSION (void*) loader);
+ }
+
+ if (!version && did_load) {
+ gladLoaderUnloadGLX();
+ }
+ }
+
+ return version;
+}
+
+
+void gladLoaderUnloadGLX() {
+ if (_glx_handle != NULL) {
+ glad_close_dlopen_handle(_glx_handle);
+ _glx_handle = NULL;
+ }
+}
+
+#endif /* GLAD_GLX */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/thirdparty/libtheora/LICENSE b/thirdparty/libtheora/LICENSE
index 5e5ec08469..97e8431790 100644
--- a/thirdparty/libtheora/LICENSE
+++ b/thirdparty/libtheora/LICENSE
@@ -4,13 +4,13 @@ In addition to and irrespective of the copyright license associated
with this software, On2 Technologies, Inc. makes the following statement
regarding technology used in this software:
- On2 represents and warrants that it shall not assert any rights
+ On2 represents and warrants that it shall not assert any rights
relating to infringement of On2's registered patents, nor initiate
any litigation asserting such rights, against any person who, or
- entity which utilizes the On2 VP3 Codec Software, including any
- use, distribution, and sale of said Software; which make changes,
+ entity which utilizes the On2 VP3 Codec Software, including any
+ use, distribution, and sale of said Software; which make changes,
modifications, and improvements in said Software; and to use,
- distribute, and sell said changes as well as applications for other
+ distribute, and sell said changes as well as applications for other
fields of use.
This reference implementation is originally derived from the On2 VP3
diff --git a/thirdparty/libtheora/analyze.c b/thirdparty/libtheora/analyze.c
index af01b60dff..19d7612d23 100644
--- a/thirdparty/libtheora/analyze.c
+++ b/thirdparty/libtheora/analyze.c
@@ -18,12 +18,12 @@
#include <string.h>
#include "encint.h"
#include "modedec.h"
+#if defined(OC_COLLECT_METRICS)
+# include "collect.c"
+#endif
-typedef struct oc_fr_state oc_fr_state;
-typedef struct oc_qii_state oc_qii_state;
-typedef struct oc_enc_pipeline_state oc_enc_pipeline_state;
typedef struct oc_rd_metric oc_rd_metric;
typedef struct oc_mode_choice oc_mode_choice;
@@ -42,7 +42,7 @@ typedef struct oc_mode_choice oc_mode_choice;
This is the inverse of the equivalent table OC_MODE_ALPHABETS in the
decoder.*/
static const unsigned char OC_MODE_RANKS[7][OC_NMODES]={
- /*Last MV dominates.*/
+ /*Last MV dominates.*/
/*L P M N I G GM 4*/
{3,4,2,0,1,5,6,7},
/*L P N M I G GM 4*/
@@ -87,6 +87,29 @@ static void oc_mode_scheme_chooser_reset(oc_mode_scheme_chooser *_chooser){
}
}
+/*Return the cost of coding _mb_mode in the specified scheme.*/
+static int oc_mode_scheme_chooser_scheme_mb_cost(
+ const oc_mode_scheme_chooser *_chooser,int _scheme,int _mb_mode){
+ int codebook;
+ int ri;
+ codebook=_scheme+1>>3;
+ /*For any scheme except 0, we can just use the bit cost of the mode's rank
+ in that scheme.*/
+ ri=_chooser->mode_ranks[_scheme][_mb_mode];
+ if(_scheme==0){
+ int mc;
+ /*For scheme 0, incrementing the mode count could potentially change the
+ mode's rank.
+ Find the index where the mode would be moved to in the optimal list,
+ and use its bit cost instead of the one for the mode's current
+ position in the list.*/
+ /*We don't actually reorder the list; this is for computing opportunity
+ cost, not an update.*/
+ mc=_chooser->mode_counts[_mb_mode];
+ while(ri>0&&mc>=_chooser->mode_counts[_chooser->scheme0_list[ri-1]])ri--;
+ }
+ return OC_MODE_BITS[codebook][ri];
+}
/*This is the real purpose of this data structure: not actually selecting a
mode scheme, but estimating the cost of coding a given mode given all the
@@ -108,46 +131,32 @@ static int oc_mode_scheme_chooser_cost(oc_mode_scheme_chooser *_chooser,
int best_bits;
int mode_bits;
int si;
- int scheme_bits;
+ int scheme0_bits;
+ int scheme1_bits;
scheme0=_chooser->scheme_list[0];
scheme1=_chooser->scheme_list[1];
- best_bits=_chooser->scheme_bits[scheme0];
- mode_bits=OC_MODE_BITS[scheme0+1>>3][_chooser->mode_ranks[scheme0][_mb_mode]];
+ scheme0_bits=_chooser->scheme_bits[scheme0];
+ scheme1_bits=_chooser->scheme_bits[scheme1];
+ mode_bits=oc_mode_scheme_chooser_scheme_mb_cost(_chooser,scheme0,_mb_mode);
/*Typical case: If the difference between the best scheme and the next best
is greater than 6 bits, then adding just one mode cannot change which
scheme we use.*/
- if(_chooser->scheme_bits[scheme1]-best_bits>6)return mode_bits;
+ if(scheme1_bits-scheme0_bits>6)return mode_bits;
/*Otherwise, check to see if adding this mode selects a different scheme as
the best.*/
si=1;
- best_bits+=mode_bits;
+ best_bits=scheme0_bits+mode_bits;
do{
- /*For any scheme except 0, we can just use the bit cost of the mode's rank
- in that scheme.*/
- if(scheme1!=0){
- scheme_bits=_chooser->scheme_bits[scheme1]+
- OC_MODE_BITS[scheme1+1>>3][_chooser->mode_ranks[scheme1][_mb_mode]];
- }
- else{
- int ri;
- /*For scheme 0, incrementing the mode count could potentially change the
- mode's rank.
- Find the index where the mode would be moved to in the optimal list,
- and use its bit cost instead of the one for the mode's current
- position in the list.*/
- /*We don't recompute scheme bits; this is computing opportunity cost, not
- an update.*/
- for(ri=_chooser->scheme0_ranks[_mb_mode];ri>0&&
- _chooser->mode_counts[_mb_mode]>=
- _chooser->mode_counts[_chooser->scheme0_list[ri-1]];ri--);
- scheme_bits=_chooser->scheme_bits[0]+OC_MODE_BITS[0][ri];
- }
- if(scheme_bits<best_bits)best_bits=scheme_bits;
+ int cur_bits;
+ cur_bits=scheme1_bits+
+ oc_mode_scheme_chooser_scheme_mb_cost(_chooser,scheme1,_mb_mode);
+ if(cur_bits<best_bits)best_bits=cur_bits;
if(++si>=8)break;
scheme1=_chooser->scheme_list[si];
+ scheme1_bits=_chooser->scheme_bits[scheme1];
}
- while(_chooser->scheme_bits[scheme1]-_chooser->scheme_bits[scheme0]<=6);
- return best_bits-_chooser->scheme_bits[scheme0];
+ while(scheme1_bits-scheme0_bits<=6);
+ return best_bits-scheme0_bits;
}
/*Incrementally update the mode counts and per-scheme bit counts and re-order
@@ -211,22 +220,6 @@ static int oc_block_run_bits(int _run_count){
-/*State to track coded block flags and their bit cost.*/
-struct oc_fr_state{
- ptrdiff_t bits;
- unsigned sb_partial_count:16;
- unsigned sb_full_count:16;
- unsigned b_coded_count_prev:8;
- unsigned b_coded_count:8;
- unsigned b_count:8;
- signed int sb_partial:2;
- signed int sb_full:2;
- signed int b_coded_prev:2;
- signed int b_coded:2;
-};
-
-
-
static void oc_fr_state_init(oc_fr_state *_fr){
_fr->bits=0;
_fr->sb_partial_count=0;
@@ -234,6 +227,8 @@ static void oc_fr_state_init(oc_fr_state *_fr){
_fr->b_coded_count_prev=0;
_fr->b_coded_count=0;
_fr->b_count=0;
+ _fr->sb_prefer_partial=0;
+ _fr->sb_bits=0;
_fr->sb_partial=-1;
_fr->sb_full=-1;
_fr->b_coded_prev=-1;
@@ -241,14 +236,14 @@ static void oc_fr_state_init(oc_fr_state *_fr){
}
-static void oc_fr_state_advance_sb(oc_fr_state *_fr,
+static int oc_fr_state_sb_cost(const oc_fr_state *_fr,
int _sb_partial,int _sb_full){
- ptrdiff_t bits;
- int sb_partial_count;
- int sb_full_count;
- bits=_fr->bits;
+ int bits;
+ int sb_partial_count;
+ int sb_full_count;
+ bits=0;
+ sb_partial_count=_fr->sb_partial_count;
/*Extend the sb_partial run, or start a new one.*/
- sb_partial_count=_fr->sb_partial;
if(_fr->sb_partial==_sb_partial){
if(sb_partial_count>=4129){
bits++;
@@ -257,8 +252,7 @@ static void oc_fr_state_advance_sb(oc_fr_state *_fr,
else bits-=oc_sb_run_bits(sb_partial_count);
}
else sb_partial_count=0;
- sb_partial_count++;
- bits+=oc_sb_run_bits(sb_partial_count);
+ bits+=oc_sb_run_bits(++sb_partial_count);
if(!_sb_partial){
/*Extend the sb_full run, or start a new one.*/
sb_full_count=_fr->sb_full_count;
@@ -270,98 +264,161 @@ static void oc_fr_state_advance_sb(oc_fr_state *_fr,
else bits-=oc_sb_run_bits(sb_full_count);
}
else sb_full_count=0;
+ bits+=oc_sb_run_bits(++sb_full_count);
+ }
+ return bits;
+}
+
+static void oc_fr_state_advance_sb(oc_fr_state *_fr,
+ int _sb_partial,int _sb_full){
+ int sb_partial_count;
+ int sb_full_count;
+ sb_partial_count=_fr->sb_partial_count;
+ if(_fr->sb_partial!=_sb_partial||sb_partial_count>=4129)sb_partial_count=0;
+ sb_partial_count++;
+ if(!_sb_partial){
+ sb_full_count=_fr->sb_full_count;
+ if(_fr->sb_full!=_sb_full||sb_full_count>=4129)sb_full_count=0;
sb_full_count++;
- bits+=oc_sb_run_bits(sb_full_count);
- _fr->sb_full=_sb_full;
_fr->sb_full_count=sb_full_count;
+ _fr->sb_full=_sb_full;
+ /*Roll back the partial block state.*/
+ _fr->b_coded=_fr->b_coded_prev;
+ _fr->b_coded_count=_fr->b_coded_count_prev;
+ }
+ else{
+ /*Commit back the partial block state.*/
+ _fr->b_coded_prev=_fr->b_coded;
+ _fr->b_coded_count_prev=_fr->b_coded_count;
}
- _fr->bits=bits;
- _fr->sb_partial=_sb_partial;
_fr->sb_partial_count=sb_partial_count;
+ _fr->sb_partial=_sb_partial;
+ _fr->b_count=0;
+ _fr->sb_prefer_partial=0;
+ _fr->sb_bits=0;
}
-/*Flush any outstanding block flags for a SB (e.g., one with fewer than 16
- blocks).*/
+/*Commit the state of the current super block and advance to the next.*/
static void oc_fr_state_flush_sb(oc_fr_state *_fr){
- ptrdiff_t bits;
- int sb_partial;
- int sb_full=sb_full;
- int b_coded_count;
- int b_coded;
- int b_count;
+ int sb_partial;
+ int sb_full;
+ int b_coded_count;
+ int b_count;
b_count=_fr->b_count;
- if(b_count>0){
- bits=_fr->bits;
- b_coded=_fr->b_coded;
- b_coded_count=_fr->b_coded_count;
- if(b_coded_count>=b_count){
- /*This SB was fully coded/uncoded; roll back the partial block flags.*/
- bits-=oc_block_run_bits(b_coded_count);
- if(b_coded_count>b_count)bits+=oc_block_run_bits(b_coded_count-b_count);
- sb_partial=0;
- sb_full=b_coded;
- b_coded=_fr->b_coded_prev;
- b_coded_count=_fr->b_coded_count_prev;
- }
- else{
- /*It was partially coded.*/
- sb_partial=1;
- /*sb_full is unused.*/
+ b_coded_count=_fr->b_coded_count;
+ sb_full=_fr->b_coded;
+ sb_partial=b_coded_count<b_count;
+ if(!sb_partial){
+ /*If the super block is fully coded/uncoded...*/
+ if(_fr->sb_prefer_partial){
+ /*So far coding this super block as partial was cheaper anyway.*/
+ if(b_coded_count>15||_fr->b_coded_prev<0){
+ int sb_bits;
+ /*If the block run is too long, this will limit how far it can be
+ extended into the next partial super block.
+ If we need to extend it farther, we don't want to have to roll all
+ the way back here (since there could be many full SBs between now
+ and then), so we disallow this.
+ Similarly, if this is the start of a stripe, we don't know how the
+ length of the outstanding block run from the previous stripe.*/
+ sb_bits=oc_fr_state_sb_cost(_fr,sb_partial,sb_full);
+ _fr->bits+=sb_bits-_fr->sb_bits;
+ _fr->sb_bits=sb_bits;
+ }
+ else sb_partial=1;
}
- _fr->bits=bits;
- _fr->b_coded_count=b_coded_count;
- _fr->b_coded_count_prev=b_coded_count;
- _fr->b_count=0;
- _fr->b_coded=b_coded;
- _fr->b_coded_prev=b_coded;
- oc_fr_state_advance_sb(_fr,sb_partial,sb_full);
}
+ oc_fr_state_advance_sb(_fr,sb_partial,sb_full);
}
static void oc_fr_state_advance_block(oc_fr_state *_fr,int _b_coded){
ptrdiff_t bits;
+ int sb_bits;
int b_coded_count;
int b_count;
- int sb_partial;
- int sb_full=sb_full;
- bits=_fr->bits;
- /*Extend the b_coded run, or start a new one.*/
+ int sb_prefer_partial;
+ sb_bits=_fr->sb_bits;
+ bits=_fr->bits-sb_bits;
+ b_count=_fr->b_count;
b_coded_count=_fr->b_coded_count;
- if(_fr->b_coded==_b_coded)bits-=oc_block_run_bits(b_coded_count);
- else b_coded_count=0;
- b_coded_count++;
- b_count=_fr->b_count+1;
- if(b_count>=16){
- /*We finished a superblock.*/
- if(b_coded_count>=16){
- /*It was fully coded/uncoded; roll back the partial block flags.*/
- if(b_coded_count>16)bits+=oc_block_run_bits(b_coded_count-16);
- sb_partial=0;
- sb_full=_b_coded;
- _b_coded=_fr->b_coded_prev;
- b_coded_count=_fr->b_coded_count_prev;
+ sb_prefer_partial=_fr->sb_prefer_partial;
+ if(b_coded_count>=b_count){
+ int sb_partial_bits;
+ /*This super block is currently fully coded/uncoded.*/
+ if(b_count<=0){
+ /*This is the first block in this SB.*/
+ b_count=1;
+ /*Check to see whether it's cheaper to code it partially or fully.*/
+ if(_fr->b_coded==_b_coded){
+ sb_partial_bits=-oc_block_run_bits(b_coded_count);
+ sb_partial_bits+=oc_block_run_bits(++b_coded_count);
+ }
+ else{
+ b_coded_count=1;
+ sb_partial_bits=2;
+ }
+ sb_partial_bits+=oc_fr_state_sb_cost(_fr,1,_b_coded);
+ sb_bits=oc_fr_state_sb_cost(_fr,0,_b_coded);
+ sb_prefer_partial=sb_partial_bits<sb_bits;
+ sb_bits^=(sb_partial_bits^sb_bits)&-sb_prefer_partial;
+ }
+ else if(_fr->b_coded==_b_coded){
+ b_coded_count++;
+ if(++b_count<16){
+ if(sb_prefer_partial){
+ /*Check to see if it's cheaper to code it fully.*/
+ sb_partial_bits=sb_bits;
+ sb_partial_bits+=oc_block_run_bits(b_coded_count);
+ if(b_coded_count>0){
+ sb_partial_bits-=oc_block_run_bits(b_coded_count-1);
+ }
+ sb_bits=oc_fr_state_sb_cost(_fr,0,_b_coded);
+ sb_prefer_partial=sb_partial_bits<sb_bits;
+ sb_bits^=(sb_partial_bits^sb_bits)&-sb_prefer_partial;
+ }
+ /*There's no need to check the converse (whether it's cheaper to code
+ this SB partially if we were coding it fully), since the cost to
+ code a SB partially can only increase as we add more blocks, whereas
+ the cost to code it fully stays constant.*/
+ }
+ else{
+ /*If we get to the end and this SB is still full, then force it to be
+ coded full.
+ Otherwise we might not be able to extend the block run far enough
+ into the next partial SB.*/
+ if(sb_prefer_partial){
+ sb_prefer_partial=0;
+ sb_bits=oc_fr_state_sb_cost(_fr,0,_b_coded);
+ }
+ }
}
else{
- bits+=oc_block_run_bits(b_coded_count);
- /*It was partially coded.*/
- sb_partial=1;
- /*sb_full is unused.*/
+ /*This SB was full, but now must be made partial.*/
+ if(!sb_prefer_partial){
+ sb_bits=oc_block_run_bits(b_coded_count);
+ if(b_coded_count>b_count){
+ sb_bits-=oc_block_run_bits(b_coded_count-b_count);
+ }
+ sb_bits+=oc_fr_state_sb_cost(_fr,1,_b_coded);
+ }
+ b_count++;
+ b_coded_count=1;
+ sb_prefer_partial=1;
+ sb_bits+=2;
}
- _fr->bits=bits;
- _fr->b_coded_count=b_coded_count;
- _fr->b_coded_count_prev=b_coded_count;
- _fr->b_count=0;
- _fr->b_coded=_b_coded;
- _fr->b_coded_prev=_b_coded;
- oc_fr_state_advance_sb(_fr,sb_partial,sb_full);
}
else{
- bits+=oc_block_run_bits(b_coded_count);
- _fr->bits=bits;
- _fr->b_coded_count=b_coded_count;
- _fr->b_count=b_count;
- _fr->b_coded=_b_coded;
+ b_count++;
+ if(_fr->b_coded==_b_coded)sb_bits-=oc_block_run_bits(b_coded_count);
+ else b_coded_count=0;
+ sb_bits+=oc_block_run_bits(++b_coded_count);
}
+ _fr->bits=bits+sb_bits;
+ _fr->b_coded_count=b_coded_count;
+ _fr->b_coded=_b_coded;
+ _fr->b_count=b_count;
+ _fr->sb_prefer_partial=sb_prefer_partial;
+ _fr->sb_bits=sb_bits;
}
static void oc_fr_skip_block(oc_fr_state *_fr){
@@ -395,16 +452,6 @@ static int oc_fr_cost4(const oc_fr_state *_pre,const oc_fr_state *_post){
-struct oc_qii_state{
- ptrdiff_t bits;
- unsigned qi01_count:14;
- signed int qi01:2;
- unsigned qi12_count:14;
- signed int qi12:2;
-};
-
-
-
static void oc_qii_state_init(oc_qii_state *_qs){
_qs->bits=0;
_qs->qi01_count=0;
@@ -458,49 +505,17 @@ static void oc_qii_state_advance(oc_qii_state *_qd,
-/*Temporary encoder state for the analysis pipeline.*/
-struct oc_enc_pipeline_state{
- int bounding_values[256];
- oc_fr_state fr[3];
- oc_qii_state qs[3];
- /*Condensed dequantization tables.*/
- const ogg_uint16_t *dequant[3][3][2];
- /*Condensed quantization tables.*/
- const oc_iquant *enquant[3][3][2];
- /*Skip SSD storage for the current MCU in each plane.*/
- unsigned *skip_ssd[3];
- /*Coded/uncoded fragment lists for each plane for the current MCU.*/
- ptrdiff_t *coded_fragis[3];
- ptrdiff_t *uncoded_fragis[3];
- ptrdiff_t ncoded_fragis[3];
- ptrdiff_t nuncoded_fragis[3];
- /*The starting fragment for the current MCU in each plane.*/
- ptrdiff_t froffset[3];
- /*The starting row for the current MCU in each plane.*/
- int fragy0[3];
- /*The ending row for the current MCU in each plane.*/
- int fragy_end[3];
- /*The starting superblock for the current MCU in each plane.*/
- unsigned sbi0[3];
- /*The ending superblock for the current MCU in each plane.*/
- unsigned sbi_end[3];
- /*The number of tokens for zzi=1 for each color plane.*/
- int ndct_tokens1[3];
- /*The outstanding eob_run count for zzi=1 for each color plane.*/
- int eob_run1[3];
- /*Whether or not the loop filter is enabled.*/
- int loop_filter;
-};
-
-
static void oc_enc_pipeline_init(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe){
ptrdiff_t *coded_fragis;
unsigned mcu_nvsbs;
ptrdiff_t mcu_nfrags;
+ int flimit;
int hdec;
int vdec;
int pli;
+ int nqis;
int qii;
+ int qi0;
int qti;
/*Initialize the per-plane coded block flag trackers.
These are used for bit-estimation purposes only; the real flag bits span
@@ -529,24 +544,36 @@ static void oc_enc_pipeline_init(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe){
memset(_pipe->ncoded_fragis,0,sizeof(_pipe->ncoded_fragis));
memset(_pipe->nuncoded_fragis,0,sizeof(_pipe->nuncoded_fragis));
/*Set up condensed quantizer tables.*/
+ qi0=_enc->state.qis[0];
+ nqis=_enc->state.nqis;
for(pli=0;pli<3;pli++){
- for(qii=0;qii<_enc->state.nqis;qii++){
+ for(qii=0;qii<nqis;qii++){
int qi;
qi=_enc->state.qis[qii];
for(qti=0;qti<2;qti++){
- _pipe->dequant[pli][qii][qti]=_enc->state.dequant_tables[qi][pli][qti];
- _pipe->enquant[pli][qii][qti]=_enc->enquant_tables[qi][pli][qti];
+ /*Set the DC coefficient in the dequantization table.*/
+ _enc->state.dequant_tables[qi][pli][qti][0]=
+ _enc->dequant_dc[qi0][pli][qti];
+ _enc->dequant[pli][qii][qti]=_enc->state.dequant_tables[qi][pli][qti];
+ /*Copy over the quantization table.*/
+ memcpy(_enc->enquant[pli][qii][qti],_enc->enquant_tables[qi][pli][qti],
+ _enc->opt_data.enquant_table_size);
}
}
}
+ /*Fix up the DC coefficients in the quantization tables.*/
+ oc_enc_enquant_table_fixup(_enc,_enc->enquant,nqis);
/*Initialize the tokenization state.*/
for(pli=0;pli<3;pli++){
_pipe->ndct_tokens1[pli]=0;
_pipe->eob_run1[pli]=0;
}
/*Initialize the bounding value array for the loop filter.*/
- _pipe->loop_filter=!oc_state_loop_filter_init(&_enc->state,
- _pipe->bounding_values);
+ flimit=_enc->state.loop_filter_limits[_enc->state.qis[0]];
+ _pipe->loop_filter=flimit!=0;
+ if(flimit!=0)oc_loop_filter_init(&_enc->state,_pipe->bounding_values,flimit);
+ /*Clear the temporary DCT scratch space.*/
+ memset(_pipe->dct_data,0,sizeof(_pipe->dct_data));
}
/*Sets the current MCU stripe to super block row _sby.
@@ -585,13 +612,17 @@ static int oc_enc_pipeline_set_stripe(oc_enc_ctx *_enc,
static void oc_enc_pipeline_finish_mcu_plane(oc_enc_ctx *_enc,
oc_enc_pipeline_state *_pipe,int _pli,int _sdelay,int _edelay){
- int refi;
/*Copy over all the uncoded fragments from this plane and advance the uncoded
fragment list.*/
- _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
- oc_state_frag_copy_list(&_enc->state,_pipe->uncoded_fragis[_pli],
- _pipe->nuncoded_fragis[_pli],OC_FRAME_SELF,OC_FRAME_PREV,_pli);
- _pipe->nuncoded_fragis[_pli]=0;
+ if(_pipe->nuncoded_fragis[_pli]>0){
+ _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
+ oc_frag_copy_list(&_enc->state,
+ _enc->state.ref_frame_data[OC_FRAME_SELF],
+ _enc->state.ref_frame_data[OC_FRAME_PREV],
+ _enc->state.ref_ystride[_pli],_pipe->uncoded_fragis[_pli],
+ _pipe->nuncoded_fragis[_pli],_enc->state.frag_buf_offs);
+ _pipe->nuncoded_fragis[_pli]=0;
+ }
/*Perform DC prediction.*/
oc_enc_pred_dc_frag_rows(_enc,_pli,
_pipe->fragy0[_pli],_pipe->fragy_end[_pli]);
@@ -606,17 +637,18 @@ static void oc_enc_pipeline_finish_mcu_plane(oc_enc_ctx *_enc,
_pipe->coded_fragis[_pli]+=_pipe->ncoded_fragis[_pli];
_pipe->ncoded_fragis[_pli]=0;
/*Apply the loop filter if necessary.*/
- refi=_enc->state.ref_frame_idx[OC_FRAME_SELF];
if(_pipe->loop_filter){
- oc_state_loop_filter_frag_rows(&_enc->state,_pipe->bounding_values,
- refi,_pli,_pipe->fragy0[_pli]-_sdelay,_pipe->fragy_end[_pli]-_edelay);
+ oc_state_loop_filter_frag_rows(&_enc->state,
+ _pipe->bounding_values,OC_FRAME_SELF,_pli,
+ _pipe->fragy0[_pli]-_sdelay,_pipe->fragy_end[_pli]-_edelay);
}
else _sdelay=_edelay=0;
/*To fill borders, we have an additional two pixel delay, since a fragment
in the next row could filter its top edge, using two pixels from a
fragment in this row.
But there's no reason to delay a full fragment between the two.*/
- oc_state_borders_fill_rows(&_enc->state,refi,_pli,
+ oc_state_borders_fill_rows(&_enc->state,
+ _enc->state.ref_frame_idx[OC_FRAME_SELF],_pli,
(_pipe->fragy0[_pli]-_sdelay<<3)-(_sdelay<<1),
(_pipe->fragy_end[_pli]-_edelay<<3)-(_edelay<<1));
}
@@ -634,62 +666,62 @@ struct oc_rd_metric{
static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
- oc_enc_pipeline_state *_pipe,int _pli,ptrdiff_t _fragi,int _overhead_bits,
- oc_rd_metric *_mo,oc_token_checkpoint **_stack){
- OC_ALIGN16(ogg_int16_t dct[64]);
- OC_ALIGN16(ogg_int16_t data[64]);
- ogg_uint16_t dc_dequant;
+ oc_enc_pipeline_state *_pipe,int _pli,ptrdiff_t _fragi,
+ unsigned _rd_scale,unsigned _rd_iscale,oc_rd_metric *_mo,
+ oc_fr_state *_fr,oc_token_checkpoint **_stack){
+ ogg_int16_t *data;
+ ogg_int16_t *dct;
+ ogg_int16_t *idct;
+ oc_qii_state qs;
const ogg_uint16_t *dequant;
- const oc_iquant *enquant;
+ ogg_uint16_t dequant_dc;
ptrdiff_t frag_offs;
int ystride;
const unsigned char *src;
const unsigned char *ref;
unsigned char *dst;
- int frame_type;
int nonzero;
unsigned uncoded_ssd;
unsigned coded_ssd;
- int coded_dc;
oc_token_checkpoint *checkpoint;
oc_fragment *frags;
int mb_mode;
+ int refi;
int mv_offs[2];
int nmv_offs;
int ac_bits;
int borderi;
+ int nqis;
int qti;
int qii;
- int pi;
- int zzi;
- int v;
- int val;
- int d;
- int s;
int dc;
+ nqis=_enc->state.nqis;
frags=_enc->state.frags;
frag_offs=_enc->state.frag_buf_offs[_fragi];
ystride=_enc->state.ref_ystride[_pli];
src=_enc->state.ref_frame_data[OC_FRAME_IO]+frag_offs;
borderi=frags[_fragi].borderi;
qii=frags[_fragi].qii;
+ data=_enc->pipe.dct_data;
+ dct=data+64;
+ idct=data+128;
if(qii&~3){
#if !defined(OC_COLLECT_METRICS)
if(_enc->sp_level>=OC_SP_LEVEL_EARLY_SKIP){
/*Enable early skip detection.*/
frags[_fragi].coded=0;
+ frags[_fragi].refi=OC_FRAME_NONE;
+ oc_fr_skip_block(_fr);
return 0;
}
#endif
/*Try and code this block anyway.*/
qii&=3;
- frags[_fragi].qii=qii;
}
+ refi=frags[_fragi].refi;
mb_mode=frags[_fragi].mb_mode;
- ref=_enc->state.ref_frame_data[
- _enc->state.ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]+frag_offs;
- dst=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_SELF]]
- +frag_offs;
+ ref=_enc->state.ref_frame_data[refi]+frag_offs;
+ dst=_enc->state.ref_frame_data[OC_FRAME_SELF]+frag_offs;
/*Motion compensation:*/
switch(mb_mode){
case OC_MODE_INTRA:{
@@ -704,9 +736,9 @@ static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
}break;
default:{
const oc_mv *frag_mvs;
- frag_mvs=(const oc_mv *)_enc->state.frag_mvs;
- nmv_offs=oc_state_get_mv_offsets(&_enc->state,mv_offs,_pli,
- frag_mvs[_fragi][0],frag_mvs[_fragi][1]);
+ frag_mvs=_enc->state.frag_mvs;
+ nmv_offs=oc_state_get_mv_offsets(&_enc->state,mv_offs,
+ _pli,frag_mvs[_fragi]);
if(nmv_offs>1){
oc_enc_frag_copy2(_enc,dst,
ref+mv_offs[0],ref+mv_offs[1],ystride);
@@ -717,126 +749,121 @@ static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
}
#if defined(OC_COLLECT_METRICS)
{
+ unsigned sad;
unsigned satd;
switch(nmv_offs){
- case 0:satd=oc_enc_frag_intra_satd(_enc,src,ystride);break;
+ case 0:{
+ sad=oc_enc_frag_intra_sad(_enc,src,ystride);
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src,ystride);
+ }break;
case 1:{
- satd=oc_enc_frag_satd_thresh(_enc,src,ref+mv_offs[0],ystride,UINT_MAX);
+ sad=oc_enc_frag_sad_thresh(_enc,src,ref+mv_offs[0],ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src,ref+mv_offs[0],ystride);
+ satd+=abs(dc);
}break;
default:{
- satd=oc_enc_frag_satd_thresh(_enc,src,dst,ystride,UINT_MAX);
- }
+ sad=oc_enc_frag_sad_thresh(_enc,src,dst,ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src,dst,ystride);
+ satd+=abs(dc);
+ }break;
}
+ _enc->frag_sad[_fragi]=sad;
_enc->frag_satd[_fragi]=satd;
}
#endif
/*Transform:*/
oc_enc_fdct8x8(_enc,dct,data);
- /*Quantize the DC coefficient:*/
+ /*Quantize:*/
qti=mb_mode!=OC_MODE_INTRA;
- enquant=_pipe->enquant[_pli][0][qti];
- dc_dequant=_pipe->dequant[_pli][0][qti][0];
- v=dct[0];
- val=v<<1;
- s=OC_SIGNMASK(val);
- val+=dc_dequant+s^s;
- val=((enquant[0].m*(ogg_int32_t)val>>16)+val>>enquant[0].l)-s;
- dc=OC_CLAMPI(-580,val,580);
- nonzero=0;
- /*Quantize the AC coefficients:*/
- dequant=_pipe->dequant[_pli][qii][qti];
- enquant=_pipe->enquant[_pli][qii][qti];
- for(zzi=1;zzi<64;zzi++){
- v=dct[OC_FZIG_ZAG[zzi]];
- d=dequant[zzi];
- val=v<<1;
- v=abs(val);
- if(v>=d){
- s=OC_SIGNMASK(val);
- /*The bias added here rounds ties away from zero, since token
- optimization can only decrease the magnitude of the quantized
- value.*/
- val+=d+s^s;
- /*Note the arithmetic right shift is not guaranteed by ANSI C.
- Hopefully no one still uses ones-complement architectures.*/
- val=((enquant[zzi].m*(ogg_int32_t)val>>16)+val>>enquant[zzi].l)-s;
- data[zzi]=OC_CLAMPI(-580,val,580);
- nonzero=zzi;
- }
- else data[zzi]=0;
- }
+ dequant=_enc->dequant[_pli][qii][qti];
+ nonzero=oc_enc_quantize(_enc,data,dct,dequant,_enc->enquant[_pli][qii][qti]);
+ dc=data[0];
/*Tokenize.*/
checkpoint=*_stack;
- ac_bits=oc_enc_tokenize_ac(_enc,_pli,_fragi,data,dequant,dct,nonzero+1,
- _stack,qti?0:3);
+ if(_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ ac_bits=oc_enc_tokenize_ac(_enc,_pli,_fragi,idct,data,dequant,dct,
+ nonzero+1,_stack,OC_RD_ISCALE(_enc->lambda,_rd_iscale),qti?0:3);
+ }
+ else{
+ ac_bits=oc_enc_tokenize_ac_fast(_enc,_pli,_fragi,idct,data,dequant,dct,
+ nonzero+1,_stack,OC_RD_ISCALE(_enc->lambda,_rd_iscale),qti?0:3);
+ }
/*Reconstruct.
TODO: nonzero may need to be adjusted after tokenization.*/
+ dequant_dc=dequant[0];
if(nonzero==0){
ogg_int16_t p;
int ci;
+ int qi01;
+ int qi12;
/*We round this dequant product (and not any of the others) because there's
no iDCT rounding.*/
- p=(ogg_int16_t)(dc*(ogg_int32_t)dc_dequant+15>>5);
+ p=(ogg_int16_t)(dc*(ogg_int32_t)dequant_dc+15>>5);
/*LOOP VECTORIZES.*/
for(ci=0;ci<64;ci++)data[ci]=p;
+ /*We didn't code any AC coefficients, so don't change the quantizer.*/
+ qi01=_pipe->qs[_pli].qi01;
+ qi12=_pipe->qs[_pli].qi12;
+ if(qi01>0)qii=1+qi12;
+ else if(qi01>=0)qii=0;
}
else{
- data[0]=dc*dc_dequant;
- oc_idct8x8(&_enc->state,data,nonzero+1);
+ idct[0]=dc*dequant_dc;
+ /*Note: This clears idct[] back to zero for the next block.*/
+ oc_idct8x8(&_enc->state,data,idct,nonzero+1);
+ }
+ frags[_fragi].qii=qii;
+ if(nqis>1){
+ oc_qii_state_advance(&qs,_pipe->qs+_pli,qii);
+ ac_bits+=qs.bits-_pipe->qs[_pli].bits;
}
if(!qti)oc_enc_frag_recon_intra(_enc,dst,ystride,data);
else{
oc_enc_frag_recon_inter(_enc,dst,
nmv_offs==1?ref+mv_offs[0]:dst,ystride,data);
}
- frame_type=_enc->state.frame_type;
+ /*If _fr is NULL, then this is an INTRA frame, and we can't skip blocks.*/
#if !defined(OC_COLLECT_METRICS)
- if(frame_type!=OC_INTRA_FRAME)
+ if(_fr!=NULL)
#endif
{
/*In retrospect, should we have skipped this block?*/
- oc_enc_frag_sub(_enc,data,src,dst,ystride);
- coded_ssd=coded_dc=0;
if(borderi<0){
- for(pi=0;pi<64;pi++){
- coded_ssd+=data[pi]*data[pi];
- coded_dc+=data[pi];
- }
+ coded_ssd=oc_enc_frag_ssd(_enc,src,dst,ystride);
}
else{
- ogg_int64_t mask;
- mask=_enc->state.borders[borderi].mask;
- for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){
- coded_ssd+=data[pi]*data[pi];
- coded_dc+=data[pi];
- }
+ coded_ssd=oc_enc_frag_border_ssd(_enc,src,dst,ystride,
+ _enc->state.borders[borderi].mask);
}
/*Scale to match DCT domain.*/
coded_ssd<<=4;
- /*We actually only want the AC contribution to the SSD.*/
- coded_ssd-=coded_dc*coded_dc>>2;
#if defined(OC_COLLECT_METRICS)
_enc->frag_ssd[_fragi]=coded_ssd;
}
- if(frame_type!=OC_INTRA_FRAME){
+ if(_fr!=NULL){
#endif
+ coded_ssd=OC_RD_SCALE(coded_ssd,_rd_scale);
uncoded_ssd=_pipe->skip_ssd[_pli][_fragi-_pipe->froffset[_pli]];
- if(uncoded_ssd<UINT_MAX){
+ if(uncoded_ssd<UINT_MAX&&
+ /*Don't allow luma blocks to be skipped in 4MV mode when VP3 compatibility
+ is enabled.*/
+ (!_enc->vp3_compatible||mb_mode!=OC_MODE_INTER_MV_FOUR||_pli)){
+ int overhead_bits;
+ overhead_bits=oc_fr_cost1(_fr);
/*Although the fragment coding overhead determination is accurate, it is
greedy, using very coarse-grained local information.
Allowing it to mildly discourage coding turns out to be beneficial, but
it's not clear that allowing it to encourage coding through negative
coding overhead deltas is useful.
- For that reason, we disallow negative coding_overheads.*/
- if(_overhead_bits<0)_overhead_bits=0;
- if(uncoded_ssd<=coded_ssd+(_overhead_bits+ac_bits)*_enc->lambda&&
- /*Don't allow luma blocks to be skipped in 4MV mode when VP3
- compatibility is enabled.*/
- (!_enc->vp3_compatible||mb_mode!=OC_MODE_INTER_MV_FOUR||_pli)){
+ For that reason, we disallow negative coding overheads.*/
+ if(overhead_bits<0)overhead_bits=0;
+ if(uncoded_ssd<=coded_ssd+(overhead_bits+ac_bits)*_enc->lambda){
/*Hm, not worth it; roll back.*/
oc_enc_tokenlog_rollback(_enc,checkpoint,(*_stack)-checkpoint);
*_stack=checkpoint;
frags[_fragi].coded=0;
+ frags[_fragi].refi=OC_FRAME_NONE;
+ oc_fr_skip_block(_fr);
return 0;
}
}
@@ -844,15 +871,20 @@ static int oc_enc_block_transform_quantize(oc_enc_ctx *_enc,
_mo->uncoded_ac_ssd+=uncoded_ssd;
_mo->coded_ac_ssd+=coded_ssd;
_mo->ac_bits+=ac_bits;
+ oc_fr_code_block(_fr);
}
- oc_qii_state_advance(_pipe->qs+_pli,_pipe->qs+_pli,qii);
+ /*GCC 4.4.4 generates a warning here because it can't tell that
+ the init code in the nqis check above will run anytime this
+ line runs.*/
+ if(nqis>1)*(_pipe->qs+_pli)=*&qs;
frags[_fragi].dc=dc;
frags[_fragi].coded=1;
return 1;
}
-static int oc_enc_mb_transform_quantize_luma(oc_enc_ctx *_enc,
- oc_enc_pipeline_state *_pipe,unsigned _mbi,int _mode_overhead){
+static int oc_enc_mb_transform_quantize_inter_luma(oc_enc_ctx *_enc,
+ oc_enc_pipeline_state *_pipe,unsigned _mbi,int _mode_overhead,
+ const unsigned _rd_scale[4],const unsigned _rd_iscale[4]){
/*Worst case token stack usage for 4 fragments.*/
oc_token_checkpoint stack[64*4];
oc_token_checkpoint *stackptr;
@@ -867,6 +899,7 @@ static int oc_enc_mb_transform_quantize_luma(oc_enc_ctx *_enc,
oc_fr_state fr_checkpoint;
oc_qii_state qs_checkpoint;
int mb_mode;
+ int refi;
int ncoded;
ptrdiff_t fragi;
int bi;
@@ -880,78 +913,83 @@ static int oc_enc_mb_transform_quantize_luma(oc_enc_ctx *_enc,
uncoded_fragis=_pipe->uncoded_fragis[0];
nuncoded_fragis=_pipe->nuncoded_fragis[0];
mb_mode=mb_modes[_mbi];
+ refi=OC_FRAME_FOR_MODE(mb_mode);
ncoded=0;
stackptr=stack;
memset(&mo,0,sizeof(mo));
for(bi=0;bi<4;bi++){
fragi=sb_maps[_mbi>>2][_mbi&3][bi];
+ frags[fragi].refi=refi;
frags[fragi].mb_mode=mb_mode;
- if(oc_enc_block_transform_quantize(_enc,
- _pipe,0,fragi,oc_fr_cost1(_pipe->fr+0),&mo,&stackptr)){
- oc_fr_code_block(_pipe->fr+0);
+ if(oc_enc_block_transform_quantize(_enc,_pipe,0,fragi,
+ _rd_scale[bi],_rd_iscale[bi],&mo,_pipe->fr+0,&stackptr)){
coded_fragis[ncoded_fragis++]=fragi;
ncoded++;
}
- else{
- *(uncoded_fragis-++nuncoded_fragis)=fragi;
- oc_fr_skip_block(_pipe->fr+0);
- }
+ else *(uncoded_fragis-++nuncoded_fragis)=fragi;
}
- if(_enc->state.frame_type!=OC_INTRA_FRAME){
- if(ncoded>0&&!mo.dc_flag){
- int cost;
- /*Some individual blocks were worth coding.
- See if that's still true when accounting for mode and MV overhead.*/
- cost=mo.coded_ac_ssd+_enc->lambda*(mo.ac_bits
- +oc_fr_cost4(&fr_checkpoint,_pipe->fr+0)+_mode_overhead);
- if(mo.uncoded_ac_ssd<=cost){
- /*Taking macroblock overhead into account, it is not worth coding this
- MB.*/
- oc_enc_tokenlog_rollback(_enc,stack,stackptr-stack);
- *(_pipe->fr+0)=*&fr_checkpoint;
- *(_pipe->qs+0)=*&qs_checkpoint;
- for(bi=0;bi<4;bi++){
- fragi=sb_maps[_mbi>>2][_mbi&3][bi];
- if(frags[fragi].coded){
- *(uncoded_fragis-++nuncoded_fragis)=fragi;
- frags[fragi].coded=0;
- }
- oc_fr_skip_block(_pipe->fr+0);
+ if(ncoded>0&&!mo.dc_flag){
+ int cost;
+ /*Some individual blocks were worth coding.
+ See if that's still true when accounting for mode and MV overhead.*/
+ cost=mo.coded_ac_ssd+_enc->lambda*(mo.ac_bits
+ +oc_fr_cost4(&fr_checkpoint,_pipe->fr+0)+_mode_overhead);
+ if(mo.uncoded_ac_ssd<=cost){
+ /*Taking macroblock overhead into account, it is not worth coding this
+ MB.*/
+ oc_enc_tokenlog_rollback(_enc,stack,stackptr-stack);
+ *(_pipe->fr+0)=*&fr_checkpoint;
+ *(_pipe->qs+0)=*&qs_checkpoint;
+ for(bi=0;bi<4;bi++){
+ fragi=sb_maps[_mbi>>2][_mbi&3][bi];
+ if(frags[fragi].coded){
+ *(uncoded_fragis-++nuncoded_fragis)=fragi;
+ frags[fragi].coded=0;
+ frags[fragi].refi=OC_FRAME_NONE;
}
- ncoded_fragis-=ncoded;
- ncoded=0;
+ oc_fr_skip_block(_pipe->fr+0);
}
- }
- /*If no luma blocks coded, the mode is forced.*/
- if(ncoded==0)mb_modes[_mbi]=OC_MODE_INTER_NOMV;
- /*Assume that a 1MV with a single coded block is always cheaper than a 4MV
- with a single coded block.
- This may not be strictly true: a 4MV computes chroma MVs using (0,0) for
- skipped blocks, while a 1MV does not.*/
- else if(ncoded==1&&mb_mode==OC_MODE_INTER_MV_FOUR){
- mb_modes[_mbi]=OC_MODE_INTER_MV;
+ ncoded_fragis-=ncoded;
+ ncoded=0;
}
}
+ /*If no luma blocks coded, the mode is forced.*/
+ if(ncoded==0)mb_modes[_mbi]=OC_MODE_INTER_NOMV;
+ /*Assume that a 1MV with a single coded block is always cheaper than a 4MV
+ with a single coded block.
+ This may not be strictly true: a 4MV computes chroma MVs using (0,0) for
+ skipped blocks, while a 1MV does not.*/
+ else if(ncoded==1&&mb_mode==OC_MODE_INTER_MV_FOUR){
+ mb_modes[_mbi]=OC_MODE_INTER_MV;
+ }
_pipe->ncoded_fragis[0]=ncoded_fragis;
_pipe->nuncoded_fragis[0]=nuncoded_fragis;
return ncoded;
}
-static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
+static void oc_enc_sb_transform_quantize_inter_chroma(oc_enc_ctx *_enc,
oc_enc_pipeline_state *_pipe,int _pli,int _sbi_start,int _sbi_end){
- const oc_sb_map *sb_maps;
- oc_sb_flags *sb_flags;
- ptrdiff_t *coded_fragis;
- ptrdiff_t ncoded_fragis;
- ptrdiff_t *uncoded_fragis;
- ptrdiff_t nuncoded_fragis;
- int sbi;
+ const ogg_uint16_t *mcu_rd_scale;
+ const ogg_uint16_t *mcu_rd_iscale;
+ const oc_sb_map *sb_maps;
+ oc_sb_flags *sb_flags;
+ oc_fr_state *fr;
+ ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t *uncoded_fragis;
+ ptrdiff_t nuncoded_fragis;
+ ptrdiff_t froffset;
+ int sbi;
+ fr=_pipe->fr+_pli;
+ mcu_rd_scale=(const ogg_uint16_t *)_enc->mcu_rd_scale;
+ mcu_rd_iscale=(const ogg_uint16_t *)_enc->mcu_rd_iscale;
sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
sb_flags=_enc->state.sb_flags;
coded_fragis=_pipe->coded_fragis[_pli];
ncoded_fragis=_pipe->ncoded_fragis[_pli];
uncoded_fragis=_pipe->uncoded_fragis[_pli];
nuncoded_fragis=_pipe->nuncoded_fragis[_pli];
+ froffset=_pipe->froffset[_pli];
for(sbi=_sbi_start;sbi<_sbi_end;sbi++){
/*Worst case token stack usage for 1 fragment.*/
oc_token_checkpoint stack[64];
@@ -964,21 +1002,21 @@ static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
fragi=sb_maps[sbi][quadi][bi];
if(fragi>=0){
oc_token_checkpoint *stackptr;
+ unsigned rd_scale;
+ unsigned rd_iscale;
+ rd_scale=mcu_rd_scale[fragi-froffset];
+ rd_iscale=mcu_rd_iscale[fragi-froffset];
stackptr=stack;
- if(oc_enc_block_transform_quantize(_enc,
- _pipe,_pli,fragi,oc_fr_cost1(_pipe->fr+_pli),&mo,&stackptr)){
+ if(oc_enc_block_transform_quantize(_enc,_pipe,_pli,fragi,
+ rd_scale,rd_iscale,&mo,fr,&stackptr)){
coded_fragis[ncoded_fragis++]=fragi;
- oc_fr_code_block(_pipe->fr+_pli);
- }
- else{
- *(uncoded_fragis-++nuncoded_fragis)=fragi;
- oc_fr_skip_block(_pipe->fr+_pli);
}
+ else *(uncoded_fragis-++nuncoded_fragis)=fragi;
}
}
- oc_fr_state_flush_sb(_pipe->fr+_pli);
- sb_flags[sbi].coded_fully=_pipe->fr[_pli].sb_full;
- sb_flags[sbi].coded_partially=_pipe->fr[_pli].sb_partial;
+ oc_fr_state_flush_sb(fr);
+ sb_flags[sbi].coded_fully=fr->sb_full;
+ sb_flags[sbi].coded_partially=fr->sb_partial;
}
_pipe->ncoded_fragis[_pli]=ncoded_fragis;
_pipe->nuncoded_fragis[_pli]=nuncoded_fragis;
@@ -1006,8 +1044,8 @@ static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
The bit counts and SSD measurements are obtained by examining actual encoded
frames, with appropriate lambda values and optimal Huffman codes selected.
EOB bits are assigned to the fragment that started the EOB run (as opposed to
- dividing them among all the blocks in the run; though the latter approach
- seems more theoretically correct, Monty's testing showed a small improvement
+ dividing them among all the blocks in the run; the latter approach seems
+ more theoretically correct, but Monty's testing showed a small improvement
with the former, though that may have been merely statistical noise).
@ARTICLE{Kim03,
@@ -1028,11 +1066,63 @@ static void oc_enc_sb_transform_quantize_chroma(oc_enc_ctx *_enc,
+(((_ssd)&(1<<OC_BIT_SCALE)-1)+((_rate)&(1<<OC_BIT_SCALE)-1)*(_lambda) \
+((1<<OC_BIT_SCALE)>>1)>>OC_BIT_SCALE)
+static void oc_enc_mode_rd_init(oc_enc_ctx *_enc){
+#if !defined(OC_COLLECT_METRICS)
+ const
+#endif
+ oc_mode_rd (*oc_mode_rd_table)[3][2][OC_COMP_BINS]=
+ _enc->sp_level<OC_SP_LEVEL_NOSATD?OC_MODE_RD_SATD:OC_MODE_RD_SAD;
+ int qii;
+#if defined(OC_COLLECT_METRICS)
+ oc_enc_mode_metrics_load(_enc);
+#endif
+ for(qii=0;qii<_enc->state.nqis;qii++){
+ int qi;
+ int pli;
+ qi=_enc->state.qis[qii];
+ for(pli=0;pli<3;pli++){
+ int qti;
+ for(qti=0;qti<2;qti++){
+ int log_plq;
+ int modeline;
+ int bin;
+ int dx;
+ int dq;
+ log_plq=_enc->log_plq[qi][pli][qti];
+ /*Find the pair of rows in the mode table that bracket this quantizer.
+ If it falls outside the range the table covers, then we just use a
+ pair on the edge for linear extrapolation.*/
+ for(modeline=0;modeline<OC_LOGQ_BINS-1&&
+ OC_MODE_LOGQ[modeline+1][pli][qti]>log_plq;modeline++);
+ /*Interpolate a row for this quantizer.*/
+ dx=OC_MODE_LOGQ[modeline][pli][qti]-log_plq;
+ dq=OC_MODE_LOGQ[modeline][pli][qti]-OC_MODE_LOGQ[modeline+1][pli][qti];
+ if(dq==0)dq=1;
+ for(bin=0;bin<OC_COMP_BINS;bin++){
+ int y0;
+ int z0;
+ int dy;
+ int dz;
+ y0=oc_mode_rd_table[modeline][pli][qti][bin].rate;
+ z0=oc_mode_rd_table[modeline][pli][qti][bin].rmse;
+ dy=oc_mode_rd_table[modeline+1][pli][qti][bin].rate-y0;
+ dz=oc_mode_rd_table[modeline+1][pli][qti][bin].rmse-z0;
+ _enc->mode_rd[qii][pli][qti][bin].rate=
+ (ogg_int16_t)OC_CLAMPI(-32768,y0+(dy*dx+(dq>>1))/dq,32767);
+ _enc->mode_rd[qii][pli][qti][bin].rmse=
+ (ogg_int16_t)OC_CLAMPI(-32768,z0+(dz*dx+(dq>>1))/dq,32767);
+ }
+ }
+ }
+ }
+}
+
/*Estimate the R-D cost of the DCT coefficients given the SATD of a block after
prediction.*/
-static unsigned oc_dct_cost2(unsigned *_ssd,
- int _qi,int _pli,int _qti,int _satd){
+static unsigned oc_dct_cost2(oc_enc_ctx *_enc,unsigned *_ssd,
+ int _qii,int _pli,int _qti,int _satd){
unsigned rmse;
+ int shift;
int bin;
int dx;
int y0;
@@ -1042,20 +1132,279 @@ static unsigned oc_dct_cost2(unsigned *_ssd,
/*SATD metrics for chroma planes vary much less than luma, so we scale them
by 4 to distribute them into the mode decision bins more evenly.*/
_satd<<=_pli+1&2;
- bin=OC_MINI(_satd>>OC_SAD_SHIFT,OC_SAD_BINS-2);
- dx=_satd-(bin<<OC_SAD_SHIFT);
- y0=OC_MODE_RD[_qi][_pli][_qti][bin].rate;
- z0=OC_MODE_RD[_qi][_pli][_qti][bin].rmse;
- dy=OC_MODE_RD[_qi][_pli][_qti][bin+1].rate-y0;
- dz=OC_MODE_RD[_qi][_pli][_qti][bin+1].rmse-z0;
- rmse=OC_MAXI(z0+(dz*dx>>OC_SAD_SHIFT),0);
+ shift=_enc->sp_level<OC_SP_LEVEL_NOSATD?OC_SATD_SHIFT:OC_SAD_SHIFT;
+ bin=OC_MINI(_satd>>shift,OC_COMP_BINS-2);
+ dx=_satd-(bin<<shift);
+ y0=_enc->mode_rd[_qii][_pli][_qti][bin].rate;
+ z0=_enc->mode_rd[_qii][_pli][_qti][bin].rmse;
+ dy=_enc->mode_rd[_qii][_pli][_qti][bin+1].rate-y0;
+ dz=_enc->mode_rd[_qii][_pli][_qti][bin+1].rmse-z0;
+ rmse=OC_MAXI(z0+(dz*dx>>shift),0);
*_ssd=rmse*rmse>>2*OC_RMSE_SCALE-OC_BIT_SCALE;
- return OC_MAXI(y0+(dy*dx>>OC_SAD_SHIFT),0);
+ return OC_MAXI(y0+(dy*dx>>shift),0);
+}
+
+/*activity_avg must be positive, or flat regions could get a zero weight, which
+ confounds analysis.
+ We set the minimum to this value so that it also avoids the need for divide
+ by zero checks in oc_mb_masking().*/
+# define OC_ACTIVITY_AVG_MIN (1<<OC_RD_SCALE_BITS)
+
+static unsigned oc_mb_activity(oc_enc_ctx *_enc,unsigned _mbi,
+ unsigned _activity[4]){
+ const unsigned char *src;
+ const ptrdiff_t *frag_buf_offs;
+ const ptrdiff_t *sb_map;
+ unsigned luma;
+ int ystride;
+ ptrdiff_t frag_offs;
+ ptrdiff_t fragi;
+ int bi;
+ frag_buf_offs=_enc->state.frag_buf_offs;
+ sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
+ src=_enc->state.ref_frame_data[OC_FRAME_IO];
+ ystride=_enc->state.ref_ystride[0];
+ luma=0;
+ for(bi=0;bi<4;bi++){
+ const unsigned char *s;
+ unsigned x;
+ unsigned x2;
+ unsigned act;
+ int i;
+ int j;
+ fragi=sb_map[bi];
+ frag_offs=frag_buf_offs[fragi];
+ /*TODO: This could be replaced with SATD^2, since we already have to
+ compute SATD.*/
+ x=x2=0;
+ s=src+frag_offs;
+ for(i=0;i<8;i++){
+ for(j=0;j<8;j++){
+ unsigned c;
+ c=s[j];
+ x+=c;
+ x2+=c*c;
+ }
+ s+=ystride;
+ }
+ luma+=x;
+ act=(x2<<6)-x*x;
+ if(act<8<<12){
+ /*The region is flat.*/
+ act=OC_MINI(act,5<<12);
+ }
+ else{
+ unsigned e1;
+ unsigned e2;
+ unsigned e3;
+ unsigned e4;
+ /*Test for an edge.
+ TODO: There are probably much simpler ways to do this (e.g., it could
+ probably be combined with the SATD calculation).
+ Alternatively, we could split the block around the mean and compute the
+ reduction in variance in each half.
+ For a Gaussian source the reduction should be
+ (1-2/pi) ~= 0.36338022763241865692446494650994.
+ Significantly more reduction is a good indication of a bi-level image.
+ This has the advantage of identifying, in addition to straight edges,
+ small text regions, which would otherwise be classified as "texture".*/
+ e1=e2=e3=e4=0;
+ s=src+frag_offs-1;
+ for(i=0;i<8;i++){
+ for(j=0;j<8;j++){
+ e1+=abs((s[j+2]-s[j]<<1)+(s-ystride)[j+2]-(s-ystride)[j]
+ +(s+ystride)[j+2]-(s+ystride)[j]);
+ e2+=abs(((s+ystride)[j+1]-(s-ystride)[j+1]<<1)
+ +(s+ystride)[j]-(s-ystride)[j]+(s+ystride)[j+2]-(s-ystride)[j+2]);
+ e3+=abs(((s+ystride)[j+2]-(s-ystride)[j]<<1)
+ +(s+ystride)[j+1]-s[j]+s[j+2]-(s-ystride)[j+1]);
+ e4+=abs(((s+ystride)[j]-(s-ystride)[j+2]<<1)
+ +(s+ystride)[j+1]-s[j+2]+s[j]-(s-ystride)[j+1]);
+ }
+ s+=ystride;
+ }
+ /*If the largest component of the edge energy is at least 40% of the
+ total, then classify the block as an edge block.*/
+ if(5*OC_MAXI(OC_MAXI(e1,e2),OC_MAXI(e3,e4))>2*(e1+e2+e3+e4)){
+ /*act=act_th*(act/act_th)**0.7
+ =exp(log(act_th)+0.7*(log(act)-log(act_th))).
+ Here act_th=5.0 and 0x394A=oc_blog32_q10(5<<12).*/
+ act=oc_bexp32_q10(0x394A+(7*(oc_blog32_q10(act)-0x394A+5)/10));
+ }
+ }
+ _activity[bi]=act;
+ }
+ return luma;
+}
+
+static void oc_mb_activity_fast(oc_enc_ctx *_enc,unsigned _mbi,
+ unsigned _activity[4],const unsigned _intra_satd[12]){
+ int bi;
+ for(bi=0;bi<4;bi++){
+ unsigned act;
+ act=(11*_intra_satd[bi]>>8)*_intra_satd[bi];
+ if(act<8<<12){
+ /*The region is flat.*/
+ act=OC_MINI(act,5<<12);
+ }
+ _activity[bi]=act;
+ }
+}
+
+/*Compute the masking scales for the blocks in a macro block.
+ All masking is computed from the luma blocks.
+ We derive scaling factors for the chroma blocks from these, and use the same
+ ones for all chroma blocks, regardless of the subsampling.
+ It's possible for luma to be perfectly flat and yet have high chroma energy,
+ but this is unlikely in non-artificial images, and not a case that has been
+ addressed by any research to my knowledge.
+ The output of the masking process is two scale factors, which are fed into
+ the various R-D optimizations.
+ The first, rd_scale, is applied to D in the equation
+ D*rd_scale+lambda*R.
+ This is the form that must be used to properly combine scores from multiple
+ blocks, and can be interpreted as scaling distortions by their visibility.
+ The inverse, rd_iscale, is applied to lambda in the equation
+ D+rd_iscale*lambda*R.
+ This is equivalent to the first form within a single block, but much faster
+ to use when evaluating many possible distortions (e.g., during actual
+ quantization, where separate distortions are evaluated for every
+ coefficient).
+ The two macros OC_RD_SCALE(rd_scale,d) and OC_RD_ISCALE(rd_iscale,lambda) are
+ used to perform the multiplications with the proper re-scaling for the range
+ of the scaling factors.
+ Many researchers apply masking values directly to the quantizers used, and
+ not to the R-D cost.
+ Since we generally use MSE for D, rd_scale must use the square of their
+ values to generate an equivalent effect.*/
+static unsigned oc_mb_masking(unsigned _rd_scale[5],unsigned _rd_iscale[5],
+ const ogg_uint16_t _chroma_rd_scale[2],const unsigned _activity[4],
+ unsigned _activity_avg,unsigned _luma,unsigned _luma_avg){
+ unsigned activity_sum;
+ unsigned la;
+ unsigned lb;
+ unsigned d;
+ int bi;
+ int bi_min;
+ int bi_min2;
+ /*The ratio lb/la is meant to approximate
+ ((((_luma-16)/219)*(255/128))**0.649**0.4**2), which is the
+ effective luminance masking from~\cite{LKW06} (including the self-masking
+ deflator).
+ The following actually turns out to be a pretty good approximation for
+ _luma>75 or so.
+ For smaller values luminance does not really follow Weber's Law anyway, and
+ this approximation gives a much less aggressive bitrate boost in this
+ region.
+ Though some researchers claim that contrast sensitivity actually decreases
+ for very low luminance values, in my experience excessive brightness on
+ LCDs or buggy color conversions (e.g., treating Y' as full-range instead
+ of the CCIR 601 range) make artifacts in such regions extremely visible.
+ We substitute _luma_avg for 128 to allow the strength of the masking to
+ vary with the actual average image luminance, within certain limits (the
+ caller has clamped _luma_avg to the range [90,160], inclusive).
+ @ARTICLE{LKW06,
+ author="Zhen Liu and Lina J. Karam and Andrew B. Watson",
+ title="{JPEG2000} Encoding With Perceptual Distortion Control",
+ journal="{IEEE} Transactions on Image Processing",
+ volume=15,
+ number=7,
+ pages="1763--1778",
+ month=Jul,
+ year=2006
+ }*/
+#if 0
+ la=_luma+4*_luma_avg;
+ lb=4*_luma+_luma_avg;
+#else
+ /*Disable luminance masking.*/
+ la=lb=1;
+#endif
+ activity_sum=0;
+ for(bi=0;bi<4;bi++){
+ unsigned a;
+ unsigned b;
+ activity_sum+=_activity[bi];
+ /*Apply activity masking.*/
+ a=_activity[bi]+4*_activity_avg;
+ b=4*_activity[bi]+_activity_avg;
+ d=OC_RD_SCALE(b,1);
+ /*And luminance masking.*/
+ d=(a+(d>>1))/d;
+ _rd_scale[bi]=(d*la+(lb>>1))/lb;
+ /*And now the inverse.*/
+ d=OC_MAXI(OC_RD_ISCALE(a,1),1);
+ d=(b+(d>>1))/d;
+ _rd_iscale[bi]=(d*lb+(la>>1))/la;
+ }
+ /*Now compute scaling factors for chroma blocks.
+ We start by finding the two smallest iscales from the luma blocks.*/
+ bi_min=_rd_iscale[1]<_rd_iscale[0];
+ bi_min2=1-bi_min;
+ for(bi=2;bi<4;bi++){
+ if(_rd_iscale[bi]<_rd_iscale[bi_min]){
+ bi_min2=bi_min;
+ bi_min=bi;
+ }
+ else if(_rd_iscale[bi]<_rd_iscale[bi_min2])bi_min2=bi;
+ }
+ /*If the minimum iscale is less than 1.0, use the second smallest instead,
+ and force the value to at least 1.0 (inflating chroma is a waste).*/
+ if(_rd_iscale[bi_min]<(1<<OC_RD_ISCALE_BITS))bi_min=bi_min2;
+ d=OC_MINI(_rd_scale[bi_min],1<<OC_RD_SCALE_BITS);
+ _rd_scale[4]=OC_RD_SCALE(d,_chroma_rd_scale[0]);
+ d=OC_MAXI(_rd_iscale[bi_min],1<<OC_RD_ISCALE_BITS);
+ _rd_iscale[4]=OC_RD_ISCALE(d,_chroma_rd_scale[1]);
+ return activity_sum;
+}
+
+static int oc_mb_intra_satd(oc_enc_ctx *_enc,unsigned _mbi,
+ unsigned _frag_satd[12]){
+ const unsigned char *src;
+ const ptrdiff_t *frag_buf_offs;
+ const ptrdiff_t *sb_map;
+ const oc_mb_map_plane *mb_map;
+ const unsigned char *map_idxs;
+ int map_nidxs;
+ int mapii;
+ int mapi;
+ int ystride;
+ int pli;
+ int bi;
+ ptrdiff_t fragi;
+ ptrdiff_t frag_offs;
+ unsigned luma;
+ int dc;
+ frag_buf_offs=_enc->state.frag_buf_offs;
+ sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
+ src=_enc->state.ref_frame_data[OC_FRAME_IO];
+ ystride=_enc->state.ref_ystride[0];
+ luma=0;
+ for(bi=0;bi<4;bi++){
+ fragi=sb_map[bi];
+ frag_offs=frag_buf_offs[fragi];
+ _frag_satd[bi]=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ luma+=dc;
+ }
+ mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
+ map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
+ map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
+ /*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
+ ystride=_enc->state.ref_ystride[1];
+ for(mapii=4;mapii<map_nidxs;mapii++){
+ mapi=map_idxs[mapii];
+ pli=mapi>>2;
+ bi=mapi&3;
+ fragi=mb_map[pli][bi];
+ frag_offs=frag_buf_offs[fragi];
+ _frag_satd[mapii]=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ return luma;
}
/*Select luma block-level quantizers for a MB in an INTRA frame.*/
static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
- const oc_qii_state *_qs,unsigned _mbi){
+ const oc_qii_state *_qs,unsigned _mbi,const unsigned _rd_scale[4]){
const unsigned char *src;
const ptrdiff_t *frag_buf_offs;
const oc_sb_map *sb_maps;
@@ -1068,6 +1417,7 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
unsigned rate[4][3];
int prev[3][3];
unsigned satd;
+ int dc;
unsigned best_cost;
unsigned best_ssd;
unsigned best_rate;
@@ -1083,19 +1433,30 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
ystride=_enc->state.ref_ystride[0];
fragi=sb_maps[_mbi>>2][_mbi&3][0];
frag_offs=frag_buf_offs[fragi];
- satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ else{
+ satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+ }
nqis=_enc->state.nqis;
lambda=_enc->lambda;
for(qii=0;qii<nqis;qii++){
oc_qii_state_advance(qs[0]+qii,_qs,qii);
- rate[0][qii]=oc_dct_cost2(ssd[0]+qii,_enc->state.qis[qii],0,0,satd)
+ rate[0][qii]=oc_dct_cost2(_enc,ssd[0]+qii,qii,0,0,satd)
+(qs[0][qii].bits-_qs->bits<<OC_BIT_SCALE);
+ ssd[0][qii]=OC_RD_SCALE(ssd[0][qii],_rd_scale[0]);
cost[0][qii]=OC_MODE_RD_COST(ssd[0][qii],rate[0][qii],lambda);
}
for(bi=1;bi<4;bi++){
fragi=sb_maps[_mbi>>2][_mbi&3][bi];
frag_offs=frag_buf_offs[fragi];
- satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ else{
+ satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+ }
for(qii=0;qii<nqis;qii++){
oc_qii_state qt[3];
unsigned cur_ssd;
@@ -1103,7 +1464,8 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
int best_qij;
int qij;
oc_qii_state_advance(qt+0,qs[bi-1]+0,qii);
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],0,0,satd);
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,0,0,satd);
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale[bi]);
best_ssd=ssd[bi-1][0]+cur_ssd;
best_rate=rate[bi-1][0]+cur_rate
+(qt[0].bits-qs[bi-1][0].bits<<OC_BIT_SCALE);
@@ -1152,13 +1514,14 @@ static unsigned oc_analyze_intra_mb_luma(oc_enc_ctx *_enc,
/*Select a block-level quantizer for a single chroma block in an INTRA frame.*/
static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc,
- const oc_qii_state *_qs,int _pli,ptrdiff_t _fragi){
+ const oc_qii_state *_qs,int _pli,ptrdiff_t _fragi,unsigned _rd_scale){
const unsigned char *src;
oc_fragment *frags;
ptrdiff_t frag_offs;
oc_qii_state qt[3];
unsigned cost[3];
unsigned satd;
+ int dc;
unsigned best_cost;
int best_qii;
int qii;
@@ -1168,16 +1531,30 @@ static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc,
src=_enc->state.ref_frame_data[OC_FRAME_IO];
ystride=_enc->state.ref_ystride[_pli];
frag_offs=_enc->state.frag_buf_offs[_fragi];
- satd=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ satd=oc_enc_frag_intra_satd(_enc,&dc,src+frag_offs,ystride);
+ }
+ else{
+ satd=oc_enc_frag_intra_sad(_enc,src+frag_offs,ystride);
+ }
+ /*Most chroma blocks have no AC coefficients to speak of anyway, so it's not
+ worth spending the bits to change the AC quantizer.
+ TODO: This may be worth revisiting when we separate out DC and AC
+ predictions from SATD.*/
+#if 0
nqis=_enc->state.nqis;
+#else
+ nqis=1;
+#endif
lambda=_enc->lambda;
best_qii=0;
for(qii=0;qii<nqis;qii++){
unsigned cur_rate;
unsigned cur_ssd;
oc_qii_state_advance(qt+qii,_qs,qii);
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],_pli,0,satd)
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,_pli,0,satd)
+(qt[qii].bits-_qs->bits<<OC_BIT_SCALE);
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale);
cost[qii]=OC_MODE_RD_COST(cur_ssd,cur_rate,lambda);
}
best_cost=cost[0];
@@ -1192,17 +1569,49 @@ static unsigned oc_analyze_intra_chroma_block(oc_enc_ctx *_enc,
return best_cost;
}
+static void oc_enc_mb_transform_quantize_intra_luma(oc_enc_ctx *_enc,
+ oc_enc_pipeline_state *_pipe,unsigned _mbi,
+ const unsigned _rd_scale[4],const unsigned _rd_iscale[4]){
+ /*Worst case token stack usage for 4 fragments.*/
+ oc_token_checkpoint stack[64*4];
+ oc_token_checkpoint *stackptr;
+ const oc_sb_map *sb_maps;
+ oc_fragment *frags;
+ ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t fragi;
+ int bi;
+ sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
+ frags=_enc->state.frags;
+ coded_fragis=_pipe->coded_fragis[0];
+ ncoded_fragis=_pipe->ncoded_fragis[0];
+ stackptr=stack;
+ for(bi=0;bi<4;bi++){
+ fragi=sb_maps[_mbi>>2][_mbi&3][bi];
+ frags[fragi].refi=OC_FRAME_SELF;
+ frags[fragi].mb_mode=OC_MODE_INTRA;
+ oc_enc_block_transform_quantize(_enc,_pipe,0,fragi,
+ _rd_scale[bi],_rd_iscale[bi],NULL,NULL,&stackptr);
+ coded_fragis[ncoded_fragis++]=fragi;
+ }
+ _pipe->ncoded_fragis[0]=ncoded_fragis;
+}
+
static void oc_enc_sb_transform_quantize_intra_chroma(oc_enc_ctx *_enc,
oc_enc_pipeline_state *_pipe,int _pli,int _sbi_start,int _sbi_end){
- const oc_sb_map *sb_maps;
- oc_sb_flags *sb_flags;
- ptrdiff_t *coded_fragis;
- ptrdiff_t ncoded_fragis;
- int sbi;
+ const ogg_uint16_t *mcu_rd_scale;
+ const ogg_uint16_t *mcu_rd_iscale;
+ const oc_sb_map *sb_maps;
+ ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t froffset;
+ int sbi;
+ mcu_rd_scale=(const ogg_uint16_t *)_enc->mcu_rd_scale;
+ mcu_rd_iscale=(const ogg_uint16_t *)_enc->mcu_rd_iscale;
sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
- sb_flags=_enc->state.sb_flags;
coded_fragis=_pipe->coded_fragis[_pli];
ncoded_fragis=_pipe->ncoded_fragis[_pli];
+ froffset=_pipe->froffset[_pli];
for(sbi=_sbi_start;sbi<_sbi_end;sbi++){
/*Worst case token stack usage for 1 fragment.*/
oc_token_checkpoint stack[64];
@@ -1213,10 +1622,14 @@ static void oc_enc_sb_transform_quantize_intra_chroma(oc_enc_ctx *_enc,
fragi=sb_maps[sbi][quadi][bi];
if(fragi>=0){
oc_token_checkpoint *stackptr;
- oc_analyze_intra_chroma_block(_enc,_pipe->qs+_pli,_pli,fragi);
+ unsigned rd_scale;
+ unsigned rd_iscale;
+ rd_scale=mcu_rd_scale[fragi-froffset];
+ rd_iscale=mcu_rd_iscale[fragi-froffset];
+ oc_analyze_intra_chroma_block(_enc,_pipe->qs+_pli,_pli,fragi,rd_scale);
stackptr=stack;
- oc_enc_block_transform_quantize(_enc,
- _pipe,_pli,fragi,0,NULL,&stackptr);
+ oc_enc_block_transform_quantize(_enc,_pipe,_pli,fragi,
+ rd_scale,rd_iscale,NULL,NULL,&stackptr);
coded_fragis[ncoded_fragis++]=fragi;
}
}
@@ -1226,13 +1639,19 @@ static void oc_enc_sb_transform_quantize_intra_chroma(oc_enc_ctx *_enc,
/*Analysis stage for an INTRA frame.*/
void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode){
- oc_enc_pipeline_state pipe;
+ ogg_int64_t activity_sum;
+ ogg_int64_t luma_sum;
+ unsigned activity_avg;
+ unsigned luma_avg;
+ const ogg_uint16_t *chroma_rd_scale;
+ ogg_uint16_t *mcu_rd_scale;
+ ogg_uint16_t *mcu_rd_iscale;
const unsigned char *map_idxs;
int nmap_idxs;
oc_sb_flags *sb_flags;
signed char *mb_modes;
const oc_mb_map *mb_maps;
- oc_mb_enc_info *embs;
+ const oc_sb_map *sb_maps;
oc_fragment *frags;
unsigned stripe_sby;
unsigned mcu_nvsbs;
@@ -1242,7 +1661,14 @@ void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode){
int pli;
_enc->state.frame_type=OC_INTRA_FRAME;
oc_enc_tokenize_start(_enc);
- oc_enc_pipeline_init(_enc,&pipe);
+ oc_enc_pipeline_init(_enc,&_enc->pipe);
+ oc_enc_mode_rd_init(_enc);
+ activity_sum=luma_sum=0;
+ activity_avg=_enc->activity_avg;
+ luma_avg=OC_CLAMPI(90<<8,_enc->luma_avg,160<<8);
+ chroma_rd_scale=_enc->chroma_rd_scale[OC_INTRA_FRAME][_enc->state.qis[0]];
+ mcu_rd_scale=_enc->mcu_rd_scale;
+ mcu_rd_iscale=_enc->mcu_rd_iscale;
/*Choose MVs and MB modes and quantize and code luma.
Must be done in Hilbert order.*/
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
@@ -1253,52 +1679,91 @@ void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode){
sb_flags=_enc->state.sb_flags;
mb_modes=_enc->state.mb_modes;
mb_maps=(const oc_mb_map *)_enc->state.mb_maps;
- embs=_enc->mb_info;
+ sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
frags=_enc->state.frags;
notstart=0;
notdone=1;
mcu_nvsbs=_enc->mcu_nvsbs;
for(stripe_sby=0;notdone;stripe_sby+=mcu_nvsbs){
- unsigned sbi;
- unsigned sbi_end;
- notdone=oc_enc_pipeline_set_stripe(_enc,&pipe,stripe_sby);
- sbi_end=pipe.sbi_end[0];
- for(sbi=pipe.sbi0[0];sbi<sbi_end;sbi++){
+ ptrdiff_t cfroffset;
+ unsigned sbi;
+ unsigned sbi_end;
+ notdone=oc_enc_pipeline_set_stripe(_enc,&_enc->pipe,stripe_sby);
+ sbi_end=_enc->pipe.sbi_end[0];
+ cfroffset=_enc->pipe.froffset[1];
+ for(sbi=_enc->pipe.sbi0[0];sbi<sbi_end;sbi++){
int quadi;
/*Mode addressing is through Y plane, always 4 MB per SB.*/
for(quadi=0;quadi<4;quadi++)if(sb_flags[sbi].quad_valid&1<<quadi){
+ unsigned activity[4];
+ unsigned rd_scale[5];
+ unsigned rd_iscale[5];
+ unsigned luma;
unsigned mbi;
int mapii;
int mapi;
int bi;
ptrdiff_t fragi;
mbi=sbi<<2|quadi;
+ /*Activity masking.*/
+ if(_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ luma=oc_mb_activity(_enc,mbi,activity);
+ }
+ else{
+ unsigned intra_satd[12];
+ luma=oc_mb_intra_satd(_enc,mbi,intra_satd);
+ oc_mb_activity_fast(_enc,mbi,activity,intra_satd);
+ for(bi=0;bi<4;bi++)frags[sb_maps[mbi>>2][mbi&3][bi]].qii=0;
+ }
+ activity_sum+=oc_mb_masking(rd_scale,rd_iscale,
+ chroma_rd_scale,activity,activity_avg,luma,luma_avg);
+ luma_sum+=luma;
/*Motion estimation:
- We always do a basic 1MV search for all macroblocks, coded or not,
- keyframe or not.*/
- if(!_recode&&_enc->state.curframe_num>0)oc_mcenc_search(_enc,mbi);
- oc_analyze_intra_mb_luma(_enc,pipe.qs+0,mbi);
+ We do a basic 1MV search for all macroblocks, coded or not,
+ keyframe or not, unless we aren't using motion estimation at all.*/
+ if(!_recode&&_enc->state.curframe_num>0&&
+ _enc->sp_level<OC_SP_LEVEL_NOMC&&_enc->keyframe_frequency_force>1){
+ oc_mcenc_search(_enc,mbi);
+ }
+ if(_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ oc_analyze_intra_mb_luma(_enc,_enc->pipe.qs+0,mbi,rd_scale);
+ }
mb_modes[mbi]=OC_MODE_INTRA;
- oc_enc_mb_transform_quantize_luma(_enc,&pipe,mbi,0);
+ oc_enc_mb_transform_quantize_intra_luma(_enc,&_enc->pipe,
+ mbi,rd_scale,rd_iscale);
/*Propagate final MB mode and MVs to the chroma blocks.*/
for(mapii=4;mapii<nmap_idxs;mapii++){
mapi=map_idxs[mapii];
pli=mapi>>2;
bi=mapi&3;
fragi=mb_maps[mbi][pli][bi];
+ frags[fragi].refi=OC_FRAME_SELF;
frags[fragi].mb_mode=OC_MODE_INTRA;
}
+ /*Save masking scale factors for chroma blocks.*/
+ for(mapii=4;mapii<(nmap_idxs-4>>1)+4;mapii++){
+ mapi=map_idxs[mapii];
+ bi=mapi&3;
+ fragi=mb_maps[mbi][1][bi];
+ mcu_rd_scale[fragi-cfroffset]=(ogg_uint16_t)rd_scale[4];
+ mcu_rd_iscale[fragi-cfroffset]=(ogg_uint16_t)rd_iscale[4];
+ }
}
}
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,0,notstart,notdone);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,0,notstart,notdone);
/*Code chroma planes.*/
for(pli=1;pli<3;pli++){
- oc_enc_sb_transform_quantize_intra_chroma(_enc,&pipe,
- pli,pipe.sbi0[pli],pipe.sbi_end[pli]);
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,pli,notstart,notdone);
+ oc_enc_sb_transform_quantize_intra_chroma(_enc,&_enc->pipe,
+ pli,_enc->pipe.sbi0[pli],_enc->pipe.sbi_end[pli]);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,pli,notstart,notdone);
}
notstart=1;
}
+ /*Compute the average block activity and MB luma score for the frame.*/
+ _enc->activity_avg=OC_MAXI(OC_ACTIVITY_AVG_MIN,
+ (unsigned)((activity_sum+(_enc->state.fplanes[0].nfrags>>1))/
+ _enc->state.fplanes[0].nfrags));
+ _enc->luma_avg=(unsigned)((luma_sum+(_enc->state.nmbs>>1))/_enc->state.nmbs);
/*Finish filling in the reference frame borders.*/
refi=_enc->state.ref_frame_idx[OC_FRAME_SELF];
for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_enc->state,refi,pli);
@@ -1339,27 +1804,21 @@ static const unsigned OC_NOSKIP[12]={
static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
oc_mode_choice *_modec,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _frag_satd[12],const unsigned _skip_ssd[12],int _qti){
+ const unsigned _frag_satd[12],const unsigned _skip_ssd[12],
+ const unsigned _rd_scale[4],int _qti){
oc_fr_state fr;
oc_qii_state qs;
unsigned ssd;
unsigned rate;
- int overhead;
unsigned satd;
unsigned best_ssd;
unsigned best_rate;
- int best_overhead;
int best_fri;
int best_qii;
- unsigned cur_cost;
- unsigned cur_ssd;
- unsigned cur_rate;
- int cur_overhead;
int lambda;
int nqis;
int nskipped;
int bi;
- int qii;
lambda=_enc->lambda;
nqis=_enc->state.nqis;
/*We could do a trellis optimization here, but we don't make final skip
@@ -1370,26 +1829,36 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
code the flags, anyway.*/
*&fr=*_fr;
*&qs=*_qs;
- ssd=rate=overhead=nskipped=0;
+ ssd=rate=nskipped=0;
for(bi=0;bi<4;bi++){
oc_fr_state ft[2];
oc_qii_state qt[3];
unsigned best_cost;
+ unsigned cur_cost;
+ unsigned cur_ssd;
+ unsigned cur_rate;
+ unsigned cur_overhead;
+ int qii;
satd=_frag_satd[bi];
*(ft+0)=*&fr;
oc_fr_code_block(ft+0);
- oc_qii_state_advance(qt+0,&qs,0);
- best_overhead=(ft[0].bits-fr.bits<<OC_BIT_SCALE);
- best_rate=oc_dct_cost2(&best_ssd,_enc->state.qis[0],0,_qti,satd)
- +(qt[0].bits-qs.bits<<OC_BIT_SCALE);
- best_cost=OC_MODE_RD_COST(ssd+best_ssd,rate+best_rate+best_overhead,lambda);
+ cur_overhead=ft[0].bits-fr.bits;
+ best_rate=oc_dct_cost2(_enc,&best_ssd,0,0,_qti,satd)
+ +(cur_overhead<<OC_BIT_SCALE);
+ if(nqis>1){
+ oc_qii_state_advance(qt+0,&qs,0);
+ best_rate+=qt[0].bits-qs.bits<<OC_BIT_SCALE;
+ }
+ best_ssd=OC_RD_SCALE(best_ssd,_rd_scale[bi]);
+ best_cost=OC_MODE_RD_COST(ssd+best_ssd,rate+best_rate,lambda);
best_fri=0;
best_qii=0;
for(qii=1;qii<nqis;qii++){
oc_qii_state_advance(qt+qii,&qs,qii);
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],0,_qti,satd)
- +(qt[qii].bits-qs.bits<<OC_BIT_SCALE);
- cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_rate+best_overhead,lambda);
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,0,_qti,satd)
+ +(cur_overhead+qt[qii].bits-qs.bits<<OC_BIT_SCALE);
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale[bi]);
+ cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_rate,lambda);
if(cur_cost<best_cost){
best_cost=cur_cost;
best_ssd=cur_ssd;
@@ -1397,7 +1866,7 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
best_qii=qii;
}
}
- if(_skip_ssd[bi]<UINT_MAX&&nskipped<3){
+ if(_skip_ssd[bi]<(UINT_MAX>>OC_BIT_SCALE+2)&&nskipped<3){
*(ft+1)=*&fr;
oc_fr_skip_block(ft+1);
cur_overhead=ft[1].bits-fr.bits<<OC_BIT_SCALE;
@@ -1405,15 +1874,13 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_overhead,lambda);
if(cur_cost<=best_cost){
best_ssd=cur_ssd;
- best_rate=0;
- best_overhead=cur_overhead;
+ best_rate=cur_overhead;
best_fri=1;
best_qii+=4;
}
}
rate+=best_rate;
ssd+=best_ssd;
- overhead+=best_overhead;
*&fr=*(ft+best_fri);
if(best_fri==0)*&qs=*(qt+best_qii);
else nskipped++;
@@ -1421,12 +1888,12 @@ static void oc_analyze_mb_mode_luma(oc_enc_ctx *_enc,
}
_modec->ssd=ssd;
_modec->rate=rate;
- _modec->overhead=OC_MAXI(overhead,0);
}
static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
oc_mode_choice *_modec,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _frag_satd[12],const unsigned _skip_ssd[12],int _qti){
+ const unsigned _frag_satd[12],const unsigned _skip_ssd[12],
+ unsigned _rd_scale,int _qti){
unsigned ssd;
unsigned rate;
unsigned satd;
@@ -1443,7 +1910,15 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
int bi;
int qii;
lambda=_enc->lambda;
+ /*Most chroma blocks have no AC coefficients to speak of anyway, so it's not
+ worth spending the bits to change the AC quantizer.
+ TODO: This may be worth revisiting when we separate out DC and AC
+ predictions from SATD.*/
+#if 0
nqis=_enc->state.nqis;
+#else
+ nqis=1;
+#endif
ssd=_modec->ssd;
rate=_modec->rate;
/*Because (except in 4:4:4 mode) we aren't considering chroma blocks in coded
@@ -1455,13 +1930,15 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
for(;bi<nblocks;bi++){
unsigned best_cost;
satd=_frag_satd[bi];
- best_rate=oc_dct_cost2(&best_ssd,_enc->state.qis[0],pli,_qti,satd)
+ best_rate=oc_dct_cost2(_enc,&best_ssd,0,pli,_qti,satd)
+OC_CHROMA_QII_RATE;
+ best_ssd=OC_RD_SCALE(best_ssd,_rd_scale);
best_cost=OC_MODE_RD_COST(ssd+best_ssd,rate+best_rate,lambda);
best_qii=0;
for(qii=1;qii<nqis;qii++){
- cur_rate=oc_dct_cost2(&cur_ssd,_enc->state.qis[qii],0,_qti,satd)
+ cur_rate=oc_dct_cost2(_enc,&cur_ssd,qii,pli,_qti,satd)
+OC_CHROMA_QII_RATE;
+ cur_ssd=OC_RD_SCALE(cur_ssd,_rd_scale);
cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate+cur_rate,lambda);
if(cur_cost<best_cost){
best_cost=cur_cost;
@@ -1470,7 +1947,7 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
best_qii=qii;
}
}
- if(_skip_ssd[bi]<UINT_MAX){
+ if(_skip_ssd[bi]<(UINT_MAX>>OC_BIT_SCALE+2)){
cur_ssd=_skip_ssd[bi]<<OC_BIT_SCALE;
cur_cost=OC_MODE_RD_COST(ssd+cur_ssd,rate,lambda);
if(cur_cost<=best_cost){
@@ -1490,65 +1967,50 @@ static void oc_analyze_mb_mode_chroma(oc_enc_ctx *_enc,
}
static void oc_skip_cost(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe,
- unsigned _mbi,unsigned _ssd[12]){
- OC_ALIGN16(ogg_int16_t buffer[64]);
- const unsigned char *src;
- const unsigned char *ref;
- int ystride;
- const oc_fragment *frags;
- const ptrdiff_t *frag_buf_offs;
- const ptrdiff_t *sb_map;
- const oc_mb_map_plane *mb_map;
- const unsigned char *map_idxs;
- int map_nidxs;
- ogg_int64_t mask;
- unsigned uncoded_ssd;
- int uncoded_dc;
- unsigned dc_dequant;
- int dc_flag;
- int mapii;
- int mapi;
- int pli;
- int bi;
- ptrdiff_t fragi;
- ptrdiff_t frag_offs;
- int borderi;
- int pi;
+ unsigned _mbi,const unsigned _rd_scale[4],unsigned _ssd[12]){
+ const unsigned char *src;
+ const unsigned char *ref;
+ int ystride;
+ const oc_fragment *frags;
+ const ptrdiff_t *frag_buf_offs;
+ const ptrdiff_t *sb_map;
+ const oc_mb_map_plane *mb_map;
+ const unsigned char *map_idxs;
+ oc_mv *mvs;
+ int map_nidxs;
+ unsigned uncoded_ssd;
+ int mapii;
+ int mapi;
+ int pli;
+ int bi;
+ ptrdiff_t fragi;
+ ptrdiff_t frag_offs;
+ int borderi;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_PREV];
ystride=_enc->state.ref_ystride[0];
frags=_enc->state.frags;
frag_buf_offs=_enc->state.frag_buf_offs;
sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
- dc_dequant=_enc->state.dequant_tables[_enc->state.qis[0]][0][1][0];
+ mvs=_enc->mb_info[_mbi].block_mv;
for(bi=0;bi<4;bi++){
fragi=sb_map[bi];
- frag_offs=frag_buf_offs[fragi];
- oc_enc_frag_sub(_enc,buffer,src+frag_offs,ref+frag_offs,ystride);
borderi=frags[fragi].borderi;
- uncoded_ssd=uncoded_dc=0;
+ frag_offs=frag_buf_offs[fragi];
if(borderi<0){
- for(pi=0;pi<64;pi++){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_ssd(_enc,src+frag_offs,ref+frag_offs,ystride);
}
else{
- ogg_int64_t mask;
- mask=_enc->state.borders[borderi].mask;
- for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_border_ssd(_enc,
+ src+frag_offs,ref+frag_offs,ystride,_enc->state.borders[borderi].mask);
}
- /*Scale to match DCT domain.*/
- uncoded_ssd<<=4;
- /*We actually only want the AC contribution to the SSD.*/
- uncoded_ssd-=uncoded_dc*uncoded_dc>>2;
- /*DC is a special case; if there's more than a full-quantizer improvement
- in the effective DC component, always force-code the block.*/
- dc_flag=abs(uncoded_dc)>dc_dequant<<1;
- uncoded_ssd|=-dc_flag;
+ /*Scale to match DCT domain and RD.*/
+ uncoded_ssd=OC_RD_SKIP_SCALE(uncoded_ssd,_rd_scale[bi]);
+ /*Motion is a special case; if there is more than a full-pixel motion
+ against the prior frame, penalize skipping.
+ TODO: The factor of two here is a kludge, but it tested out better than a
+ hard limit.*/
+ if(mvs[bi]!=0)uncoded_ssd*=2;
_pipe->skip_ssd[0][fragi-_pipe->froffset[0]]=_ssd[bi]=uncoded_ssd;
}
mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
@@ -1556,96 +2018,52 @@ static void oc_skip_cost(oc_enc_ctx *_enc,oc_enc_pipeline_state *_pipe,
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
map_nidxs=(map_nidxs-4>>1)+4;
mapii=4;
+ mvs=_enc->mb_info[_mbi].unref_mv;
for(pli=1;pli<3;pli++){
ystride=_enc->state.ref_ystride[pli];
- dc_dequant=_enc->state.dequant_tables[_enc->state.qis[0]][pli][1][0];
for(;mapii<map_nidxs;mapii++){
mapi=map_idxs[mapii];
bi=mapi&3;
fragi=mb_map[pli][bi];
- frag_offs=frag_buf_offs[fragi];
- oc_enc_frag_sub(_enc,buffer,src+frag_offs,ref+frag_offs,ystride);
borderi=frags[fragi].borderi;
- uncoded_ssd=uncoded_dc=0;
+ frag_offs=frag_buf_offs[fragi];
if(borderi<0){
- for(pi=0;pi<64;pi++){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_ssd(_enc,src+frag_offs,ref+frag_offs,ystride);
}
else{
- mask=_enc->state.borders[borderi].mask;
- for(pi=0;pi<64;pi++,mask>>=1)if(mask&1){
- uncoded_ssd+=buffer[pi]*buffer[pi];
- uncoded_dc+=buffer[pi];
- }
+ uncoded_ssd=oc_enc_frag_border_ssd(_enc,
+ src+frag_offs,ref+frag_offs,ystride,_enc->state.borders[borderi].mask);
}
- /*Scale to match DCT domain.*/
- uncoded_ssd<<=4;
- /*We actually only want the AC contribution to the SSD.*/
- uncoded_ssd-=uncoded_dc*uncoded_dc>>2;
- /*DC is a special case; if there's more than a full-quantizer improvement
- in the effective DC component, always force-code the block.*/
- dc_flag=abs(uncoded_dc)>dc_dequant<<1;
- uncoded_ssd|=-dc_flag;
+ /*Scale to match DCT domain and RD.*/
+ uncoded_ssd=OC_RD_SKIP_SCALE(uncoded_ssd,_rd_scale[4]);
+ /*Motion is a special case; if there is more than a full-pixel motion
+ against the prior frame, penalize skipping.
+ TODO: The factor of two here is a kludge, but it tested out better than
+ a hard limit*/
+ if(mvs[OC_FRAME_PREV]!=0)uncoded_ssd*=2;
_pipe->skip_ssd[pli][fragi-_pipe->froffset[pli]]=_ssd[mapii]=uncoded_ssd;
}
map_nidxs=(map_nidxs-4<<1)+4;
}
}
-static void oc_mb_intra_satd(oc_enc_ctx *_enc,unsigned _mbi,
- unsigned _frag_satd[12]){
- const unsigned char *src;
- const ptrdiff_t *frag_buf_offs;
- const ptrdiff_t *sb_map;
- const oc_mb_map_plane *mb_map;
- const unsigned char *map_idxs;
- int map_nidxs;
- int mapii;
- int mapi;
- int ystride;
- int pli;
- int bi;
- ptrdiff_t fragi;
- ptrdiff_t frag_offs;
- frag_buf_offs=_enc->state.frag_buf_offs;
- sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
- src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ystride=_enc->state.ref_ystride[0];
- for(bi=0;bi<4;bi++){
- fragi=sb_map[bi];
- frag_offs=frag_buf_offs[fragi];
- _frag_satd[bi]=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
- }
- mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
- map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
- map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
- /*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
- ystride=_enc->state.ref_ystride[1];
- for(mapii=4;mapii<map_nidxs;mapii++){
- mapi=map_idxs[mapii];
- pli=mapi>>2;
- bi=mapi&3;
- fragi=mb_map[pli][bi];
- frag_offs=frag_buf_offs[fragi];
- _frag_satd[mapii]=oc_enc_frag_intra_satd(_enc,src+frag_offs,ystride);
- }
-}
static void oc_cost_intra(oc_enc_ctx *_enc,oc_mode_choice *_modec,
unsigned _mbi,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _frag_satd[12],const unsigned _skip_ssd[12]){
- oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,0);
- oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,0);
- _modec->overhead+=
+ const unsigned _frag_satd[12],const unsigned _skip_ssd[12],
+ const unsigned _rd_scale[5]){
+ oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,_frag_satd,_skip_ssd,_rd_scale,0);
+ oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,
+ _frag_satd,_skip_ssd,_rd_scale[4],0);
+ _modec->overhead=
oc_mode_scheme_chooser_cost(&_enc->chooser,OC_MODE_INTRA)<<OC_BIT_SCALE;
oc_mode_set_cost(_modec,_enc->lambda);
}
static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
- unsigned _mbi,int _mb_mode,const signed char *_mv,
- const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12]){
+ unsigned _mbi,int _mb_mode,oc_mv _mv,
+ const oc_fr_state *_fr,const oc_qii_state *_qs,
+ const unsigned _skip_ssd[12],const unsigned _rd_scale[5]){
unsigned frag_satd[12];
const unsigned char *src;
const unsigned char *ref;
@@ -1658,35 +2076,45 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int mapii;
int mapi;
int mv_offs[2];
- int dx;
- int dy;
int pli;
int bi;
ptrdiff_t fragi;
ptrdiff_t frag_offs;
+ int dc;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[
- _enc->state.ref_frame_idx[OC_FRAME_FOR_MODE(_mb_mode)]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_FOR_MODE(_mb_mode)];
ystride=_enc->state.ref_ystride[0];
frag_buf_offs=_enc->state.frag_buf_offs;
sb_map=_enc->state.sb_maps[_mbi>>2][_mbi&3];
- dx=_mv[0];
- dy=_mv[1];
_modec->rate=_modec->ssd=0;
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,dx,dy)>1){
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,_mv)>1){
for(bi=0;bi<4;bi++){
fragi=sb_map[bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[bi]=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[bi]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
+ frag_satd[bi]+=abs(dc);
+ }
+ else{
+ frag_satd[bi]=oc_enc_frag_sad2_thresh(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ }
}
}
else{
for(bi=0;bi<4;bi++){
fragi=sb_map[bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[bi]=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[bi]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ frag_satd[bi]+=abs(dc);
+ }
+ else{
+ frag_satd[bi]=oc_enc_frag_sad(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ }
}
}
mb_map=(const oc_mb_map_plane *)_enc->state.mb_maps[_mbi];
@@ -1694,15 +2122,22 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
/*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
ystride=_enc->state.ref_ystride[1];
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,1,dx,dy)>1){
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,1,_mv)>1){
for(mapii=4;mapii<map_nidxs;mapii++){
mapi=map_idxs[mapii];
pli=mapi>>2;
bi=mapi&3;
fragi=mb_map[pli][bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[mapii]=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[mapii]=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
+ frag_satd[mapii]+=abs(dc);
+ }
+ else{
+ frag_satd[mapii]=oc_enc_frag_sad2_thresh(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ }
}
}
else{
@@ -1712,30 +2147,38 @@ static void oc_cost_inter(oc_enc_ctx *_enc,oc_mode_choice *_modec,
bi=mapi&3;
fragi=mb_map[pli][bi];
frag_offs=frag_buf_offs[fragi];
- frag_satd[mapii]=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ frag_satd[mapii]=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ frag_satd[mapii]+=abs(dc);
+ }
+ else{
+ frag_satd[mapii]=oc_enc_frag_sad(_enc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
+ }
}
}
- oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1);
- oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1);
- _modec->overhead+=
+ oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,_rd_scale,1);
+ oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,
+ frag_satd,_skip_ssd,_rd_scale[4],1);
+ _modec->overhead=
oc_mode_scheme_chooser_cost(&_enc->chooser,_mb_mode)<<OC_BIT_SCALE;
oc_mode_set_cost(_modec,_enc->lambda);
}
static void oc_cost_inter_nomv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
unsigned _mbi,int _mb_mode,const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _skip_ssd[12]){
- static const oc_mv OC_MV_ZERO;
- oc_cost_inter(_enc,_modec,_mbi,_mb_mode,OC_MV_ZERO,_fr,_qs,_skip_ssd);
+ const unsigned _skip_ssd[12],const unsigned _rd_scale[4]){
+ oc_cost_inter(_enc,_modec,_mbi,_mb_mode,0,_fr,_qs,_skip_ssd,_rd_scale);
}
static int oc_cost_inter1mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
- unsigned _mbi,int _mb_mode,const signed char *_mv,
- const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12]){
+ unsigned _mbi,int _mb_mode,oc_mv _mv,
+ const oc_fr_state *_fr,const oc_qii_state *_qs,const unsigned _skip_ssd[12],
+ const unsigned _rd_scale[4]){
int bits0;
- oc_cost_inter(_enc,_modec,_mbi,_mb_mode,_mv,_fr,_qs,_skip_ssd);
- bits0=OC_MV_BITS[0][_mv[0]+31]+OC_MV_BITS[0][_mv[1]+31];
+ oc_cost_inter(_enc,_modec,_mbi,_mb_mode,_mv,_fr,_qs,_skip_ssd,_rd_scale);
+ bits0=OC_MV_BITS[0][OC_MV_X(_mv)+31]+OC_MV_BITS[0][OC_MV_Y(_mv)+31];
_modec->overhead+=OC_MINI(_enc->mv_bits[0]+bits0,_enc->mv_bits[1]+12)
-OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<<OC_BIT_SCALE;
oc_mode_set_cost(_modec,_enc->lambda);
@@ -1749,7 +2192,7 @@ static const unsigned char OC_MB_PHASE[4][4]={
static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
unsigned _mbi,oc_mv _mv[4],const oc_fr_state *_fr,const oc_qii_state *_qs,
- const unsigned _skip_ssd[12]){
+ const unsigned _skip_ssd[12],const unsigned _rd_scale[5]){
unsigned frag_satd[12];
oc_mv lbmvs[4];
oc_mv cbmvs[4];
@@ -1765,8 +2208,6 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int mapii;
int mapi;
int mv_offs[2];
- int dx;
- int dy;
int pli;
int bi;
ptrdiff_t fragi;
@@ -1774,8 +2215,9 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int bits0;
int bits1;
unsigned satd;
+ int dc;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_PREV];
ystride=_enc->state.ref_ystride[0];
frag_buf_offs=_enc->state.frag_buf_offs;
frag_mvs=_enc->state.frag_mvs;
@@ -1783,41 +2225,36 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
_modec->rate=_modec->ssd=0;
for(bi=0;bi<4;bi++){
fragi=mb_map[0][bi];
- dx=_mv[bi][0];
- dy=_mv[bi][1];
/*Save the block MVs as the current ones while we're here; we'll replace
them if we don't ultimately choose 4MV mode.*/
- frag_mvs[fragi][0]=(signed char)dx;
- frag_mvs[fragi][1]=(signed char)dy;
+ frag_mvs[fragi]=_mv[bi];
frag_offs=frag_buf_offs[fragi];
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,dx,dy)>1){
- satd=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,0,_mv[bi])>1){
+ satd=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
}
else{
- satd=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
}
- frag_satd[OC_MB_PHASE[_mbi&3][bi]]=satd;
+ frag_satd[OC_MB_PHASE[_mbi&3][bi]]=satd+abs(dc);
}
oc_analyze_mb_mode_luma(_enc,_modec,_fr,_qs,frag_satd,
- _enc->vp3_compatible?OC_NOSKIP:_skip_ssd,1);
+ _enc->vp3_compatible?OC_NOSKIP:_skip_ssd,_rd_scale,1);
/*Figure out which blocks are being skipped and give them (0,0) MVs.*/
bits0=0;
bits1=0;
nqis=_enc->state.nqis;
for(bi=0;bi<4;bi++){
- if(_modec->qii[OC_MB_PHASE[_mbi&3][bi]]>=nqis){
- memset(lbmvs+bi,0,sizeof(*lbmvs));
- }
+ if(_modec->qii[OC_MB_PHASE[_mbi&3][bi]]>=nqis)lbmvs[bi]=0;
else{
- memcpy(lbmvs+bi,_mv+bi,sizeof(*lbmvs));
- bits0+=OC_MV_BITS[0][_mv[bi][0]+31]+OC_MV_BITS[0][_mv[bi][1]+31];
+ lbmvs[bi]=_mv[bi];
+ bits0+=OC_MV_BITS[0][OC_MV_X(_mv[bi])+31]
+ +OC_MV_BITS[0][OC_MV_Y(_mv[bi])+31];
bits1+=12;
}
}
- (*OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt])(cbmvs,
- (const oc_mv *)lbmvs);
+ (*OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt])(cbmvs,lbmvs);
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
map_nidxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
/*Note: This assumes ref_ystride[1]==ref_ystride[2].*/
@@ -1827,23 +2264,22 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
pli=mapi>>2;
bi=mapi&3;
fragi=mb_map[pli][bi];
- dx=cbmvs[bi][0];
- dy=cbmvs[bi][1];
frag_offs=frag_buf_offs[fragi];
/*TODO: We could save half these calls by re-using the results for the Cb
and Cr planes; is it worth it?*/
- if(oc_state_get_mv_offsets(&_enc->state,mv_offs,pli,dx,dy)>1){
- satd=oc_enc_frag_satd2_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride,UINT_MAX);
+ if(oc_state_get_mv_offsets(&_enc->state,mv_offs,pli,cbmvs[bi])>1){
+ satd=oc_enc_frag_satd2(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ref+frag_offs+mv_offs[1],ystride);
}
else{
- satd=oc_enc_frag_satd_thresh(_enc,src+frag_offs,
- ref+frag_offs+mv_offs[0],ystride,UINT_MAX);
+ satd=oc_enc_frag_satd(_enc,&dc,src+frag_offs,
+ ref+frag_offs+mv_offs[0],ystride);
}
- frag_satd[mapii]=satd;
+ frag_satd[mapii]=satd+abs(dc);
}
- oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,frag_satd,_skip_ssd,1);
- _modec->overhead+=
+ oc_analyze_mb_mode_chroma(_enc,_modec,_fr,_qs,
+ frag_satd,_skip_ssd,_rd_scale[4],1);
+ _modec->overhead=
oc_mode_scheme_chooser_cost(&_enc->chooser,OC_MODE_INTER_MV_FOUR)
+OC_MINI(_enc->mv_bits[0]+bits0,_enc->mv_bits[1]+bits1)
-OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<<OC_BIT_SCALE;
@@ -1852,12 +2288,18 @@ static void oc_cost_inter4mv(oc_enc_ctx *_enc,oc_mode_choice *_modec,
int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
oc_set_chroma_mvs_func set_chroma_mvs;
- oc_enc_pipeline_state pipe;
oc_qii_state intra_luma_qs;
oc_mv last_mv;
oc_mv prior_mv;
ogg_int64_t interbits;
ogg_int64_t intrabits;
+ ogg_int64_t activity_sum;
+ ogg_int64_t luma_sum;
+ unsigned activity_avg;
+ unsigned luma_avg;
+ const ogg_uint16_t *chroma_rd_scale;
+ ogg_uint16_t *mcu_rd_scale;
+ ogg_uint16_t *mcu_rd_iscale;
const unsigned char *map_idxs;
int nmap_idxs;
unsigned *coded_mbis;
@@ -1871,30 +2313,36 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
oc_mb_enc_info *embs;
oc_fragment *frags;
oc_mv *frag_mvs;
- int qi;
unsigned stripe_sby;
unsigned mcu_nvsbs;
int notstart;
int notdone;
- int vdec;
unsigned sbi;
unsigned sbi_end;
int refi;
int pli;
+ int sp_level;
+ sp_level=_enc->sp_level;
set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_enc->state.info.pixel_fmt];
_enc->state.frame_type=OC_INTER_FRAME;
oc_mode_scheme_chooser_reset(&_enc->chooser);
oc_enc_tokenize_start(_enc);
- oc_enc_pipeline_init(_enc,&pipe);
+ oc_enc_pipeline_init(_enc,&_enc->pipe);
+ oc_enc_mode_rd_init(_enc);
if(_allow_keyframe)oc_qii_state_init(&intra_luma_qs);
_enc->mv_bits[0]=_enc->mv_bits[1]=0;
interbits=intrabits=0;
- last_mv[0]=last_mv[1]=prior_mv[0]=prior_mv[1]=0;
+ activity_sum=luma_sum=0;
+ activity_avg=_enc->activity_avg;
+ luma_avg=OC_CLAMPI(90<<8,_enc->luma_avg,160<<8);
+ chroma_rd_scale=_enc->chroma_rd_scale[OC_INTER_FRAME][_enc->state.qis[0]];
+ mcu_rd_scale=_enc->mcu_rd_scale;
+ mcu_rd_iscale=_enc->mcu_rd_iscale;
+ last_mv=prior_mv=0;
/*Choose MVs and MB modes and quantize and code luma.
Must be done in Hilbert order.*/
map_idxs=OC_MB_MAP_IDXS[_enc->state.info.pixel_fmt];
nmap_idxs=OC_MB_MAP_NIDXS[_enc->state.info.pixel_fmt];
- qi=_enc->state.qis[0];
coded_mbis=_enc->coded_mbis;
uncoded_mbis=coded_mbis+_enc->state.nmbs;
ncoded_mbis=0;
@@ -1909,37 +2357,51 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
embs=_enc->mb_info;
frags=_enc->state.frags;
frag_mvs=_enc->state.frag_mvs;
- vdec=!(_enc->state.info.pixel_fmt&2);
notstart=0;
notdone=1;
mcu_nvsbs=_enc->mcu_nvsbs;
for(stripe_sby=0;notdone;stripe_sby+=mcu_nvsbs){
- notdone=oc_enc_pipeline_set_stripe(_enc,&pipe,stripe_sby);
- sbi_end=pipe.sbi_end[0];
- for(sbi=pipe.sbi0[0];sbi<sbi_end;sbi++){
+ ptrdiff_t cfroffset;
+ notdone=oc_enc_pipeline_set_stripe(_enc,&_enc->pipe,stripe_sby);
+ sbi_end=_enc->pipe.sbi_end[0];
+ cfroffset=_enc->pipe.froffset[1];
+ for(sbi=_enc->pipe.sbi0[0];sbi<sbi_end;sbi++){
int quadi;
/*Mode addressing is through Y plane, always 4 MB per SB.*/
for(quadi=0;quadi<4;quadi++)if(sb_flags[sbi].quad_valid&1<<quadi){
oc_mode_choice modes[8];
+ unsigned activity[4];
+ unsigned rd_scale[5];
+ unsigned rd_iscale[5];
unsigned skip_ssd[12];
unsigned intra_satd[12];
+ unsigned luma;
int mb_mv_bits_0;
int mb_gmv_bits_0;
int inter_mv_pref;
int mb_mode;
- int dx;
- int dy;
+ int refi;
+ int mv;
unsigned mbi;
int mapii;
int mapi;
int bi;
ptrdiff_t fragi;
mbi=sbi<<2|quadi;
+ luma=oc_mb_intra_satd(_enc,mbi,intra_satd);
+ /*Activity masking.*/
+ if(sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ oc_mb_activity(_enc,mbi,activity);
+ }
+ else oc_mb_activity_fast(_enc,mbi,activity,intra_satd);
+ luma_sum+=luma;
+ activity_sum+=oc_mb_masking(rd_scale,rd_iscale,
+ chroma_rd_scale,activity,activity_avg,luma,luma_avg);
/*Motion estimation:
We always do a basic 1MV search for all macroblocks, coded or not,
keyframe or not.*/
- if(!_recode&&_enc->sp_level<OC_SP_LEVEL_NOMC)oc_mcenc_search(_enc,mbi);
- dx=dy=0;
+ if(!_recode&&sp_level<OC_SP_LEVEL_NOMC)oc_mcenc_search(_enc,mbi);
+ mv=0;
/*Find the block choice with the lowest estimated coding cost.
If a Cb or Cr block is coded but no Y' block from a macro block then
the mode MUST be OC_MODE_INTER_NOMV.
@@ -1948,15 +2410,16 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
/*Block coding cost is estimated from correlated SATD metrics.*/
/*At this point, all blocks that are in frame are still marked coded.*/
if(!_recode){
- memcpy(embs[mbi].unref_mv,
- embs[mbi].analysis_mv[0],sizeof(embs[mbi].unref_mv));
+ embs[mbi].unref_mv[OC_FRAME_GOLD]=
+ embs[mbi].analysis_mv[0][OC_FRAME_GOLD];
+ embs[mbi].unref_mv[OC_FRAME_PREV]=
+ embs[mbi].analysis_mv[0][OC_FRAME_PREV];
embs[mbi].refined=0;
}
- oc_mb_intra_satd(_enc,mbi,intra_satd);
/*Estimate the cost of coding this MB in a keyframe.*/
if(_allow_keyframe){
oc_cost_intra(_enc,modes+OC_MODE_INTRA,mbi,
- pipe.fr+0,&intra_luma_qs,intra_satd,OC_NOSKIP);
+ _enc->pipe.fr+0,&intra_luma_qs,intra_satd,OC_NOSKIP,rd_scale);
intrabits+=modes[OC_MODE_INTRA].rate;
for(bi=0;bi<4;bi++){
oc_qii_state_advance(&intra_luma_qs,&intra_luma_qs,
@@ -1964,26 +2427,28 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
}
/*Estimate the cost in a delta frame for various modes.*/
- oc_skip_cost(_enc,&pipe,mbi,skip_ssd);
- oc_cost_inter_nomv(_enc,modes+OC_MODE_INTER_NOMV,mbi,
- OC_MODE_INTER_NOMV,pipe.fr+0,pipe.qs+0,skip_ssd);
- if(_enc->sp_level<OC_SP_LEVEL_NOMC){
+ oc_skip_cost(_enc,&_enc->pipe,mbi,rd_scale,skip_ssd);
+ if(sp_level<OC_SP_LEVEL_NOMC){
+ oc_cost_inter_nomv(_enc,modes+OC_MODE_INTER_NOMV,mbi,
+ OC_MODE_INTER_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
oc_cost_intra(_enc,modes+OC_MODE_INTRA,mbi,
- pipe.fr+0,pipe.qs+0,intra_satd,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,intra_satd,skip_ssd,rd_scale);
mb_mv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_INTER_MV,mbi,
OC_MODE_INTER_MV,embs[mbi].unref_mv[OC_FRAME_PREV],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
oc_cost_inter(_enc,modes+OC_MODE_INTER_MV_LAST,mbi,
- OC_MODE_INTER_MV_LAST,last_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_INTER_MV_LAST,last_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
oc_cost_inter(_enc,modes+OC_MODE_INTER_MV_LAST2,mbi,
- OC_MODE_INTER_MV_LAST2,prior_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
- oc_cost_inter4mv(_enc,modes+OC_MODE_INTER_MV_FOUR,mbi,
- embs[mbi].block_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_INTER_MV_LAST2,prior_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
oc_cost_inter_nomv(_enc,modes+OC_MODE_GOLDEN_NOMV,mbi,
- OC_MODE_GOLDEN_NOMV,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_GOLDEN_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
mb_gmv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_GOLDEN_MV,mbi,
OC_MODE_GOLDEN_MV,embs[mbi].unref_mv[OC_FRAME_GOLD],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
/*The explicit MV modes (2,6,7) have not yet gone through halfpel
refinement.
We choose the explicit MV mode that's already furthest ahead on
@@ -1991,6 +2456,14 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
We have to be careful to remember which ones we've refined so that
we don't refine it again if we re-encode this frame.*/
inter_mv_pref=_enc->lambda*3;
+ if(sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
+ oc_cost_inter4mv(_enc,modes+OC_MODE_INTER_MV_FOUR,mbi,
+ embs[mbi].block_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
+ }
+ else{
+ modes[OC_MODE_INTER_MV_FOUR].cost=UINT_MAX;
+ }
if(modes[OC_MODE_INTER_MV_FOUR].cost<modes[OC_MODE_INTER_MV].cost&&
modes[OC_MODE_INTER_MV_FOUR].cost<modes[OC_MODE_GOLDEN_MV].cost){
if(!(embs[mbi].refined&0x80)){
@@ -1998,7 +2471,8 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
embs[mbi].refined|=0x80;
}
oc_cost_inter4mv(_enc,modes+OC_MODE_INTER_MV_FOUR,mbi,
- embs[mbi].ref_mv,pipe.fr+0,pipe.qs+0,skip_ssd);
+ embs[mbi].ref_mv,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
}
else if(modes[OC_MODE_GOLDEN_MV].cost+inter_mv_pref<
modes[OC_MODE_INTER_MV].cost){
@@ -2008,7 +2482,7 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
mb_gmv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_GOLDEN_MV,mbi,
OC_MODE_GOLDEN_MV,embs[mbi].analysis_mv[0][OC_FRAME_GOLD],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
}
if(!(embs[mbi].refined&0x04)){
oc_mcenc_refine1mv(_enc,mbi,OC_FRAME_PREV);
@@ -2016,7 +2490,7 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
mb_mv_bits_0=oc_cost_inter1mv(_enc,modes+OC_MODE_INTER_MV,mbi,
OC_MODE_INTER_MV,embs[mbi].analysis_mv[0][OC_FRAME_PREV],
- pipe.fr+0,pipe.qs+0,skip_ssd);
+ _enc->pipe.fr+0,_enc->pipe.qs+0,skip_ssd,rd_scale);
/*Finally, pick the mode with the cheapest estimated R-D cost.*/
mb_mode=OC_MODE_INTER_NOMV;
if(modes[OC_MODE_INTRA].cost<modes[OC_MODE_INTER_NOMV].cost){
@@ -2046,8 +2520,14 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
}
else{
+ oc_cost_inter_nomv(_enc,modes+OC_MODE_INTER_NOMV,mbi,
+ OC_MODE_INTER_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
+ oc_cost_intra(_enc,modes+OC_MODE_INTRA,mbi,
+ _enc->pipe.fr+0,_enc->pipe.qs+0,intra_satd,skip_ssd,rd_scale);
oc_cost_inter_nomv(_enc,modes+OC_MODE_GOLDEN_NOMV,mbi,
- OC_MODE_GOLDEN_NOMV,pipe.fr+0,pipe.qs+0,skip_ssd);
+ OC_MODE_GOLDEN_NOMV,_enc->pipe.fr+0,_enc->pipe.qs+0,
+ skip_ssd,rd_scale);
mb_mode=OC_MODE_INTER_NOMV;
if(modes[OC_MODE_INTRA].cost<modes[OC_MODE_INTER_NOMV].cost){
mb_mode=OC_MODE_INTRA;
@@ -2062,67 +2542,55 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
if(mb_mode!=OC_MODE_INTER_MV_FOUR){
switch(mb_mode){
case OC_MODE_INTER_MV:{
- dx=embs[mbi].analysis_mv[0][OC_FRAME_PREV][0];
- dy=embs[mbi].analysis_mv[0][OC_FRAME_PREV][1];
- }break;
- case OC_MODE_INTER_MV_LAST:{
- dx=last_mv[0];
- dy=last_mv[1];
- }break;
- case OC_MODE_INTER_MV_LAST2:{
- dx=prior_mv[0];
- dy=prior_mv[1];
+ mv=embs[mbi].analysis_mv[0][OC_FRAME_PREV];
}break;
+ case OC_MODE_INTER_MV_LAST:mv=last_mv;break;
+ case OC_MODE_INTER_MV_LAST2:mv=prior_mv;break;
case OC_MODE_GOLDEN_MV:{
- dx=embs[mbi].analysis_mv[0][OC_FRAME_GOLD][0];
- dy=embs[mbi].analysis_mv[0][OC_FRAME_GOLD][1];
+ mv=embs[mbi].analysis_mv[0][OC_FRAME_GOLD];
}break;
}
for(bi=0;bi<4;bi++){
fragi=mb_maps[mbi][0][bi];
- frag_mvs[fragi][0]=(signed char)dx;
- frag_mvs[fragi][1]=(signed char)dy;
+ frag_mvs[fragi]=mv;
}
}
for(bi=0;bi<4;bi++){
fragi=sb_maps[mbi>>2][mbi&3][bi];
frags[fragi].qii=modes[mb_mode].qii[bi];
}
- if(oc_enc_mb_transform_quantize_luma(_enc,&pipe,mbi,
- modes[mb_mode].overhead>>OC_BIT_SCALE)>0){
+ if(oc_enc_mb_transform_quantize_inter_luma(_enc,&_enc->pipe,mbi,
+ modes[mb_mode].overhead>>OC_BIT_SCALE,rd_scale,rd_iscale)>0){
int orig_mb_mode;
orig_mb_mode=mb_mode;
mb_mode=mb_modes[mbi];
+ refi=OC_FRAME_FOR_MODE(mb_mode);
switch(mb_mode){
case OC_MODE_INTER_MV:{
- memcpy(prior_mv,last_mv,sizeof(prior_mv));
+ prior_mv=last_mv;
/*If we're backing out from 4MV, find the MV we're actually
using.*/
if(orig_mb_mode==OC_MODE_INTER_MV_FOUR){
for(bi=0;;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- memcpy(last_mv,frag_mvs[fragi],sizeof(last_mv));
- dx=frag_mvs[fragi][0];
- dy=frag_mvs[fragi][1];
+ mv=last_mv=frag_mvs[fragi];
break;
}
}
- mb_mv_bits_0=OC_MV_BITS[0][dx+31]+OC_MV_BITS[0][dy+31];
+ mb_mv_bits_0=OC_MV_BITS[0][OC_MV_X(mv)+31]
+ +OC_MV_BITS[0][OC_MV_Y(mv)+31];
}
/*Otherwise we used the original analysis MV.*/
- else{
- memcpy(last_mv,
- embs[mbi].analysis_mv[0][OC_FRAME_PREV],sizeof(last_mv));
- }
+ else last_mv=embs[mbi].analysis_mv[0][OC_FRAME_PREV];
_enc->mv_bits[0]+=mb_mv_bits_0;
_enc->mv_bits[1]+=12;
}break;
case OC_MODE_INTER_MV_LAST2:{
oc_mv tmp_mv;
- memcpy(tmp_mv,prior_mv,sizeof(tmp_mv));
- memcpy(prior_mv,last_mv,sizeof(prior_mv));
- memcpy(last_mv,tmp_mv,sizeof(last_mv));
+ tmp_mv=prior_mv;
+ prior_mv=last_mv;
+ last_mv=tmp_mv;
}break;
case OC_MODE_GOLDEN_MV:{
_enc->mv_bits[0]+=mb_gmv_bits_0;
@@ -2131,28 +2599,28 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
case OC_MODE_INTER_MV_FOUR:{
oc_mv lbmvs[4];
oc_mv cbmvs[4];
- memcpy(prior_mv,last_mv,sizeof(prior_mv));
+ prior_mv=last_mv;
for(bi=0;bi<4;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- memcpy(last_mv,frag_mvs[fragi],sizeof(last_mv));
- memcpy(lbmvs[bi],frag_mvs[fragi],sizeof(lbmvs[bi]));
- _enc->mv_bits[0]+=OC_MV_BITS[0][frag_mvs[fragi][0]+31]
- +OC_MV_BITS[0][frag_mvs[fragi][1]+31];
+ lbmvs[bi]=last_mv=frag_mvs[fragi];
+ _enc->mv_bits[0]+=OC_MV_BITS[0][OC_MV_X(last_mv)+31]
+ +OC_MV_BITS[0][OC_MV_Y(last_mv)+31];
_enc->mv_bits[1]+=12;
}
/*Replace the block MVs for not-coded blocks with (0,0).*/
- else memset(lbmvs[bi],0,sizeof(lbmvs[bi]));
+ else lbmvs[bi]=0;
}
- (*set_chroma_mvs)(cbmvs,(const oc_mv *)lbmvs);
+ (*set_chroma_mvs)(cbmvs,lbmvs);
for(mapii=4;mapii<nmap_idxs;mapii++){
mapi=map_idxs[mapii];
pli=mapi>>2;
bi=mapi&3;
fragi=mb_maps[mbi][pli][bi];
- frags[fragi].mb_mode=mb_mode;
frags[fragi].qii=modes[OC_MODE_INTER_MV_FOUR].qii[mapii];
- memcpy(frag_mvs[fragi],cbmvs[bi],sizeof(frag_mvs[fragi]));
+ frags[fragi].refi=refi;
+ frags[fragi].mb_mode=mb_mode;
+ frag_mvs[fragi]=cbmvs[bi];
}
}break;
}
@@ -2163,7 +2631,8 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
else{
*(uncoded_mbis-++nuncoded_mbis)=mbi;
mb_mode=OC_MODE_INTER_NOMV;
- dx=dy=0;
+ refi=OC_FRAME_PREV;
+ mv=0;
}
/*Propagate final MB mode and MVs to the chroma blocks.
This has already been done for 4MV mode, since it requires individual
@@ -2174,43 +2643,56 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
pli=mapi>>2;
bi=mapi&3;
fragi=mb_maps[mbi][pli][bi];
- frags[fragi].mb_mode=mb_mode;
/*If we switched from 4MV mode to INTER_MV mode, then the qii
values won't have been chosen with the right MV, but it's
probaby not worth re-estimating them.*/
frags[fragi].qii=modes[mb_mode].qii[mapii];
- frag_mvs[fragi][0]=(signed char)dx;
- frag_mvs[fragi][1]=(signed char)dy;
+ frags[fragi].refi=refi;
+ frags[fragi].mb_mode=mb_mode;
+ frag_mvs[fragi]=mv;
}
}
+ /*Save masking scale factors for chroma blocks.*/
+ for(mapii=4;mapii<(nmap_idxs-4>>1)+4;mapii++){
+ mapi=map_idxs[mapii];
+ bi=mapi&3;
+ fragi=mb_maps[mbi][1][bi];
+ mcu_rd_scale[fragi-cfroffset]=(ogg_uint16_t)rd_scale[4];
+ mcu_rd_iscale[fragi-cfroffset]=(ogg_uint16_t)rd_iscale[4];
+ }
}
- oc_fr_state_flush_sb(pipe.fr+0);
- sb_flags[sbi].coded_fully=pipe.fr[0].sb_full;
- sb_flags[sbi].coded_partially=pipe.fr[0].sb_partial;
+ oc_fr_state_flush_sb(_enc->pipe.fr+0);
+ sb_flags[sbi].coded_fully=_enc->pipe.fr[0].sb_full;
+ sb_flags[sbi].coded_partially=_enc->pipe.fr[0].sb_partial;
}
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,0,notstart,notdone);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,0,notstart,notdone);
/*Code chroma planes.*/
for(pli=1;pli<3;pli++){
- oc_enc_sb_transform_quantize_chroma(_enc,&pipe,
- pli,pipe.sbi0[pli],pipe.sbi_end[pli]);
- oc_enc_pipeline_finish_mcu_plane(_enc,&pipe,pli,notstart,notdone);
+ oc_enc_sb_transform_quantize_inter_chroma(_enc,&_enc->pipe,
+ pli,_enc->pipe.sbi0[pli],_enc->pipe.sbi_end[pli]);
+ oc_enc_pipeline_finish_mcu_plane(_enc,&_enc->pipe,pli,notstart,notdone);
}
notstart=1;
}
+ /*Update the average block activity and MB luma score for the frame.
+ We could use a Bessel follower here, but fast reaction is probably almost
+ always best.*/
+ _enc->activity_avg=OC_MAXI(OC_ACTIVITY_AVG_MIN,
+ (unsigned)((activity_sum+(_enc->state.fplanes[0].nfrags>>1))/
+ _enc->state.fplanes[0].nfrags));
+ _enc->luma_avg=(unsigned)((luma_sum+(_enc->state.nmbs>>1))/_enc->state.nmbs);
/*Finish filling in the reference frame borders.*/
refi=_enc->state.ref_frame_idx[OC_FRAME_SELF];
for(pli=0;pli<3;pli++)oc_state_borders_fill_caps(&_enc->state,refi,pli);
/*Finish adding flagging overhead costs to inter bit counts to determine if
we should have coded a key frame instead.*/
if(_allow_keyframe){
- if(interbits>intrabits)return 1;
/*Technically the chroma plane counts are over-estimations, because they
don't account for continuing runs from the luma planes, but the
- inaccuracy is small.*/
- for(pli=0;pli<3;pli++)interbits+=pipe.fr[pli].bits<<OC_BIT_SCALE;
- interbits+=OC_MINI(_enc->mv_bits[0],_enc->mv_bits[1])<<OC_BIT_SCALE;
- interbits+=
- _enc->chooser.scheme_bits[_enc->chooser.scheme_list[0]]<<OC_BIT_SCALE;
+ inaccuracy is small.
+ We don't need to add the luma plane coding flag costs, because they are
+ already included in the MB rate estimates.*/
+ for(pli=1;pli<3;pli++)interbits+=_enc->pipe.fr[pli].bits<<OC_BIT_SCALE;
if(interbits>intrabits)return 1;
}
_enc->ncoded_mbis=ncoded_mbis;
@@ -2228,482 +2710,3 @@ int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode){
}
return 0;
}
-
-#if defined(OC_COLLECT_METRICS)
-# include <stdio.h>
-# include <math.h>
-
-/*TODO: It may be helpful (for block-level quantizers especially) to separate
- out the contributions from AC and DC into separate tables.*/
-
-# define OC_ZWEIGHT (0.25)
-
-static void oc_mode_metrics_add(oc_mode_metrics *_metrics,
- double _w,int _satd,int _rate,double _rmse){
- double rate;
- /*Accumulate statistics without the scaling; this lets us change the scale
- factor yet still use old data.*/
- rate=ldexp(_rate,-OC_BIT_SCALE);
- if(_metrics->fragw>0){
- double dsatd;
- double drate;
- double drmse;
- double w;
- dsatd=_satd-_metrics->satd/_metrics->fragw;
- drate=rate-_metrics->rate/_metrics->fragw;
- drmse=_rmse-_metrics->rmse/_metrics->fragw;
- w=_metrics->fragw*_w/(_metrics->fragw+_w);
- _metrics->satd2+=dsatd*dsatd*w;
- _metrics->satdrate+=dsatd*drate*w;
- _metrics->rate2+=drate*drate*w;
- _metrics->satdrmse+=dsatd*drmse*w;
- _metrics->rmse2+=drmse*drmse*w;
- }
- _metrics->fragw+=_w;
- _metrics->satd+=_satd*_w;
- _metrics->rate+=rate*_w;
- _metrics->rmse+=_rmse*_w;
-}
-
-static void oc_mode_metrics_merge(oc_mode_metrics *_dst,
- const oc_mode_metrics *_src,int _n){
- int i;
- /*Find a non-empty set of metrics.*/
- for(i=0;i<_n&&_src[i].fragw<=0;i++);
- if(i>=_n){
- memset(_dst,0,sizeof(*_dst));
- return;
- }
- memcpy(_dst,_src+i,sizeof(*_dst));
- /*And iterate over the remaining non-empty sets of metrics.*/
- for(i++;i<_n;i++)if(_src[i].fragw>0){
- double wa;
- double wb;
- double dsatd;
- double drate;
- double drmse;
- double w;
- wa=_dst->fragw;
- wb=_src[i].fragw;
- dsatd=_src[i].satd/wb-_dst->satd/wa;
- drate=_src[i].rate/wb-_dst->rate/wa;
- drmse=_src[i].rmse/wb-_dst->rmse/wa;
- w=wa*wb/(wa+wb);
- _dst->fragw+=_src[i].fragw;
- _dst->satd+=_src[i].satd;
- _dst->rate+=_src[i].rate;
- _dst->rmse+=_src[i].rmse;
- _dst->satd2+=_src[i].satd2+dsatd*dsatd*w;
- _dst->satdrate+=_src[i].satdrate+dsatd*drate*w;
- _dst->rate2+=_src[i].rate2+drate*drate*w;
- _dst->satdrmse+=_src[i].satdrmse+dsatd*drmse*w;
- _dst->rmse2+=_src[i].rmse2+drmse*drmse*w;
- }
-}
-
-/*Compile collected SATD/rate/RMSE metrics into a form that's immediately
- useful for mode decision.*/
-static void oc_enc_mode_metrics_update(oc_enc_ctx *_enc,int _qi){
- int pli;
- int qti;
- oc_restore_fpu(&_enc->state);
- /*Convert raw collected data into cleaned up sample points.*/
- for(pli=0;pli<3;pli++){
- for(qti=0;qti<2;qti++){
- double fragw;
- int bin0;
- int bin1;
- int bin;
- fragw=0;
- bin0=bin1=0;
- for(bin=0;bin<OC_SAD_BINS;bin++){
- oc_mode_metrics metrics;
- OC_MODE_RD[_qi][pli][qti][bin].rate=0;
- OC_MODE_RD[_qi][pli][qti][bin].rmse=0;
- /*Find some points on either side of the current bin.*/
- while((bin1<bin+1||fragw<OC_ZWEIGHT)&&bin1<OC_SAD_BINS-1){
- fragw+=OC_MODE_METRICS[_qi][pli][qti][bin1++].fragw;
- }
- while(bin0+1<bin&&bin0+1<bin1&&
- fragw-OC_MODE_METRICS[_qi][pli][qti][bin0].fragw>=OC_ZWEIGHT){
- fragw-=OC_MODE_METRICS[_qi][pli][qti][bin0++].fragw;
- }
- /*Merge statistics and fit lines.*/
- oc_mode_metrics_merge(&metrics,
- OC_MODE_METRICS[_qi][pli][qti]+bin0,bin1-bin0);
- if(metrics.fragw>0&&metrics.satd2>0){
- double a;
- double b;
- double msatd;
- double mrate;
- double mrmse;
- double rate;
- double rmse;
- msatd=metrics.satd/metrics.fragw;
- mrate=metrics.rate/metrics.fragw;
- mrmse=metrics.rmse/metrics.fragw;
- /*Compute the points on these lines corresponding to the actual bin
- value.*/
- b=metrics.satdrate/metrics.satd2;
- a=mrate-b*msatd;
- rate=ldexp(a+b*(bin<<OC_SAD_SHIFT),OC_BIT_SCALE);
- OC_MODE_RD[_qi][pli][qti][bin].rate=
- (ogg_int16_t)OC_CLAMPI(-32768,(int)(rate+0.5),32767);
- b=metrics.satdrmse/metrics.satd2;
- a=mrmse-b*msatd;
- rmse=ldexp(a+b*(bin<<OC_SAD_SHIFT),OC_RMSE_SCALE);
- OC_MODE_RD[_qi][pli][qti][bin].rmse=
- (ogg_int16_t)OC_CLAMPI(-32768,(int)(rmse+0.5),32767);
- }
- }
- }
- }
-}
-
-
-
-/*The following token skipping code used to also be used in the decoder (and
- even at one point other places in the encoder).
- However, it was obsoleted by other optimizations, and is now only used here.
- It has been moved here to avoid generating the code when it's not needed.*/
-
-/*Determines the number of blocks or coefficients to be skipped for a given
- token value.
- _token: The token value to skip.
- _extra_bits: The extra bits attached to this token.
- Return: A positive value indicates that number of coefficients are to be
- skipped in the current block.
- Otherwise, the negative of the return value indicates that number of
- blocks are to be ended.*/
-typedef ptrdiff_t (*oc_token_skip_func)(int _token,int _extra_bits);
-
-/*Handles the simple end of block tokens.*/
-static ptrdiff_t oc_token_skip_eob(int _token,int _extra_bits){
- int nblocks_adjust;
- nblocks_adjust=OC_UNIBBLE_TABLE32(0,1,2,3,7,15,0,0,_token)+1;
- return -_extra_bits-nblocks_adjust;
-}
-
-/*The last EOB token has a special case, where an EOB run of size zero ends all
- the remaining blocks in the frame.*/
-static ptrdiff_t oc_token_skip_eob6(int _token,int _extra_bits){
- /*Note: We want to return -PTRDIFF_MAX, but that requires C99, which is not
- yet available everywhere; this should be equivalent.*/
- if(!_extra_bits)return -(~(size_t)0>>1);
- return -_extra_bits;
-}
-
-/*Handles the pure zero run tokens.*/
-static ptrdiff_t oc_token_skip_zrl(int _token,int _extra_bits){
- return _extra_bits+1;
-}
-
-/*Handles a normal coefficient value token.*/
-static ptrdiff_t oc_token_skip_val(void){
- return 1;
-}
-
-/*Handles a category 1A zero run/coefficient value combo token.*/
-static ptrdiff_t oc_token_skip_run_cat1a(int _token){
- return _token-OC_DCT_RUN_CAT1A+2;
-}
-
-/*Handles category 1b, 1c, 2a, and 2b zero run/coefficient value combo tokens.*/
-static ptrdiff_t oc_token_skip_run(int _token,int _extra_bits){
- int run_cati;
- int ncoeffs_mask;
- int ncoeffs_adjust;
- run_cati=_token-OC_DCT_RUN_CAT1B;
- ncoeffs_mask=OC_BYTE_TABLE32(3,7,0,1,run_cati);
- ncoeffs_adjust=OC_BYTE_TABLE32(7,11,2,3,run_cati);
- return (_extra_bits&ncoeffs_mask)+ncoeffs_adjust;
-}
-
-/*A jump table for computing the number of coefficients or blocks to skip for
- a given token value.
- This reduces all the conditional branches, etc., needed to parse these token
- values down to one indirect jump.*/
-static const oc_token_skip_func OC_TOKEN_SKIP_TABLE[TH_NDCT_TOKENS]={
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob,
- oc_token_skip_eob6,
- oc_token_skip_zrl,
- oc_token_skip_zrl,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_val,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- (oc_token_skip_func)oc_token_skip_run_cat1a,
- oc_token_skip_run,
- oc_token_skip_run,
- oc_token_skip_run,
- oc_token_skip_run
-};
-
-/*Determines the number of blocks or coefficients to be skipped for a given
- token value.
- _token: The token value to skip.
- _extra_bits: The extra bits attached to this token.
- Return: A positive value indicates that number of coefficients are to be
- skipped in the current block.
- Otherwise, the negative of the return value indicates that number of
- blocks are to be ended.
- 0 will never be returned, so that at least one coefficient in one
- block will always be decoded for every token.*/
-static ptrdiff_t oc_dct_token_skip(int _token,int _extra_bits){
- return (*OC_TOKEN_SKIP_TABLE[_token])(_token,_extra_bits);
-}
-
-
-
-void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
- static const unsigned char OC_ZZI_HUFF_OFFSET[64]={
- 0,16,16,16,16,16,32,32,
- 32,32,32,32,32,32,32,48,
- 48,48,48,48,48,48,48,48,
- 48,48,48,48,64,64,64,64,
- 64,64,64,64,64,64,64,64,
- 64,64,64,64,64,64,64,64,
- 64,64,64,64,64,64,64,64
- };
- const oc_fragment *frags;
- const unsigned *frag_satd;
- const unsigned *frag_ssd;
- const ptrdiff_t *coded_fragis;
- ptrdiff_t ncoded_fragis;
- ptrdiff_t fragii;
- double fragw;
- int qti;
- int qii;
- int qi;
- int pli;
- int zzi;
- int token;
- int eb;
- oc_restore_fpu(&_enc->state);
- /*Load any existing mode metrics if we haven't already.*/
- if(!oc_has_mode_metrics){
- FILE *fmetrics;
- memset(OC_MODE_METRICS,0,sizeof(OC_MODE_METRICS));
- fmetrics=fopen("modedec.stats","rb");
- if(fmetrics!=NULL){
- fread(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics);
- fclose(fmetrics);
- }
- for(qi=0;qi<64;qi++)oc_enc_mode_metrics_update(_enc,qi);
- oc_has_mode_metrics=1;
- }
- qti=_enc->state.frame_type;
- frags=_enc->state.frags;
- frag_satd=_enc->frag_satd;
- frag_ssd=_enc->frag_ssd;
- coded_fragis=_enc->state.coded_fragis;
- ncoded_fragis=fragii=0;
- /*Weight the fragments by the inverse frame size; this prevents HD content
- from dominating the statistics.*/
- fragw=1.0/_enc->state.nfrags;
- for(pli=0;pli<3;pli++){
- ptrdiff_t ti[64];
- int eob_token[64];
- int eob_run[64];
- /*Set up token indices and eob run counts.
- We don't bother trying to figure out the real cost of the runs that span
- coefficients; instead we use the costs that were available when R-D
- token optimization was done.*/
- for(zzi=0;zzi<64;zzi++){
- ti[zzi]=_enc->dct_token_offs[pli][zzi];
- if(ti[zzi]>0){
- token=_enc->dct_tokens[pli][zzi][0];
- eb=_enc->extra_bits[pli][zzi][0];
- eob_token[zzi]=token;
- eob_run[zzi]=-oc_dct_token_skip(token,eb);
- }
- else{
- eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
- eob_run[zzi]=0;
- }
- }
- /*Scan the list of coded fragments for this plane.*/
- ncoded_fragis+=_enc->state.ncoded_fragis[pli];
- for(;fragii<ncoded_fragis;fragii++){
- ptrdiff_t fragi;
- ogg_uint32_t frag_bits;
- int huffi;
- int skip;
- int mb_mode;
- unsigned satd;
- int bin;
- fragi=coded_fragis[fragii];
- frag_bits=0;
- for(zzi=0;zzi<64;){
- if(eob_run[zzi]>0){
- /*We've reached the end of the block.*/
- eob_run[zzi]--;
- break;
- }
- huffi=_enc->huff_idxs[qti][zzi>0][pli+1>>1]
- +OC_ZZI_HUFF_OFFSET[zzi];
- if(eob_token[zzi]<OC_NDCT_EOB_TOKEN_MAX){
- /*This token caused an EOB run to be flushed.
- Therefore it gets the bits associated with it.*/
- frag_bits+=_enc->huff_codes[huffi][eob_token[zzi]].nbits
- +OC_DCT_TOKEN_EXTRA_BITS[eob_token[zzi]];
- eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
- }
- token=_enc->dct_tokens[pli][zzi][ti[zzi]];
- eb=_enc->extra_bits[pli][zzi][ti[zzi]];
- ti[zzi]++;
- skip=oc_dct_token_skip(token,eb);
- if(skip<0){
- eob_token[zzi]=token;
- eob_run[zzi]=-skip;
- }
- else{
- /*A regular DCT value token; accumulate the bits for it.*/
- frag_bits+=_enc->huff_codes[huffi][token].nbits
- +OC_DCT_TOKEN_EXTRA_BITS[token];
- zzi+=skip;
- }
- }
- mb_mode=frags[fragi].mb_mode;
- qi=_enc->state.qis[frags[fragi].qii];
- satd=frag_satd[fragi]<<(pli+1&2);
- bin=OC_MINI(satd>>OC_SAD_SHIFT,OC_SAD_BINS-1);
- oc_mode_metrics_add(OC_MODE_METRICS[qi][pli][mb_mode!=OC_MODE_INTRA]+bin,
- fragw,satd,frag_bits<<OC_BIT_SCALE,sqrt(frag_ssd[fragi]));
- }
- }
- /*Update global SATD/rate/RMSE estimation matrix.*/
- for(qii=0;qii<_enc->state.nqis;qii++){
- oc_enc_mode_metrics_update(_enc,_enc->state.qis[qii]);
- }
-}
-
-void oc_enc_mode_metrics_dump(oc_enc_ctx *_enc){
- FILE *fmetrics;
- int qi;
- /*Generate sample points for complete list of QI values.*/
- for(qi=0;qi<64;qi++)oc_enc_mode_metrics_update(_enc,qi);
- fmetrics=fopen("modedec.stats","wb");
- if(fmetrics!=NULL){
- fwrite(OC_MODE_METRICS,sizeof(OC_MODE_METRICS),1,fmetrics);
- fclose(fmetrics);
- }
- fprintf(stdout,
- "/*File generated by libtheora with OC_COLLECT_METRICS"
- " defined at compile time.*/\n"
- "#if !defined(_modedec_H)\n"
- "# define _modedec_H (1)\n"
- "\n"
- "\n"
- "\n"
- "# if defined(OC_COLLECT_METRICS)\n"
- "typedef struct oc_mode_metrics oc_mode_metrics;\n"
- "# endif\n"
- "typedef struct oc_mode_rd oc_mode_rd;\n"
- "\n"
- "\n"
- "\n"
- "/*The number of extra bits of precision at which to store rate"
- " metrics.*/\n"
- "# define OC_BIT_SCALE (%i)\n"
- "/*The number of extra bits of precision at which to store RMSE metrics.\n"
- " This must be at least half OC_BIT_SCALE (rounded up).*/\n"
- "# define OC_RMSE_SCALE (%i)\n"
- "/*The number of bins to partition statistics into.*/\n"
- "# define OC_SAD_BINS (%i)\n"
- "/*The number of bits of precision to drop"
- " from SAD scores to assign them to a\n"
- " bin.*/\n"
- "# define OC_SAD_SHIFT (%i)\n"
- "\n"
- "\n"
- "\n"
- "# if defined(OC_COLLECT_METRICS)\n"
- "struct oc_mode_metrics{\n"
- " double fragw;\n"
- " double satd;\n"
- " double rate;\n"
- " double rmse;\n"
- " double satd2;\n"
- " double satdrate;\n"
- " double rate2;\n"
- " double satdrmse;\n"
- " double rmse2;\n"
- "};\n"
- "\n"
- "\n"
- "int oc_has_mode_metrics;\n"
- "oc_mode_metrics OC_MODE_METRICS[64][3][2][OC_SAD_BINS];\n"
- "# endif\n"
- "\n"
- "\n"
- "\n"
- "struct oc_mode_rd{\n"
- " ogg_int16_t rate;\n"
- " ogg_int16_t rmse;\n"
- "};\n"
- "\n"
- "\n"
- "# if !defined(OC_COLLECT_METRICS)\n"
- "static const\n"
- "# endif\n"
- "oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={\n",
- OC_BIT_SCALE,OC_RMSE_SCALE,OC_SAD_BINS,OC_SAD_SHIFT);
- for(qi=0;qi<64;qi++){
- int pli;
- fprintf(stdout," {\n");
- for(pli=0;pli<3;pli++){
- int qti;
- fprintf(stdout," {\n");
- for(qti=0;qti<2;qti++){
- int bin;
- static const char *pl_names[3]={"Y'","Cb","Cr"};
- static const char *qti_names[2]={"INTRA","INTER"};
- fprintf(stdout," /*%s qi=%i %s*/\n",
- pl_names[pli],qi,qti_names[qti]);
- fprintf(stdout," {\n");
- fprintf(stdout," ");
- for(bin=0;bin<OC_SAD_BINS;bin++){
- if(bin&&!(bin&0x3))fprintf(stdout,"\n ");
- fprintf(stdout,"{%5i,%5i}",
- OC_MODE_RD[qi][pli][qti][bin].rate,
- OC_MODE_RD[qi][pli][qti][bin].rmse);
- if(bin+1<OC_SAD_BINS)fprintf(stdout,",");
- }
- fprintf(stdout,"\n }");
- if(qti<1)fprintf(stdout,",");
- fprintf(stdout,"\n");
- }
- fprintf(stdout," }");
- if(pli<2)fprintf(stdout,",");
- fprintf(stdout,"\n");
- }
- fprintf(stdout," }");
- if(qi<63)fprintf(stdout,",");
- fprintf(stdout,"\n");
- }
- fprintf(stdout,
- "};\n"
- "\n"
- "#endif\n");
-}
-#endif
diff --git a/thirdparty/libtheora/apiwrapper.c b/thirdparty/libtheora/apiwrapper.c
index dc959b8d13..87b4e939f2 100644
--- a/thirdparty/libtheora/apiwrapper.c
+++ b/thirdparty/libtheora/apiwrapper.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: apiwrapper.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/apiwrapper.h b/thirdparty/libtheora/apiwrapper.h
index 93454d7bda..ff45e0a4d6 100644
--- a/thirdparty/libtheora/apiwrapper.h
+++ b/thirdparty/libtheora/apiwrapper.h
@@ -21,7 +21,7 @@
# include <theora/theora.h>
# include "theora/theoradec.h"
# include "theora/theoraenc.h"
-# include "internal.h"
+# include "state.h"
typedef struct th_api_wrapper th_api_wrapper;
typedef struct th_api_info th_api_info;
diff --git a/thirdparty/libtheora/bitpack.c b/thirdparty/libtheora/bitpack.c
index 8195003bad..5125dde6b0 100644
--- a/thirdparty/libtheora/bitpack.c
+++ b/thirdparty/libtheora/bitpack.c
@@ -11,7 +11,7 @@
********************************************************************
function: packing variable sized words into an octet stream
- last mod: $Id: bitpack.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <string.h>
@@ -32,15 +32,18 @@ static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){
const unsigned char *stop;
oc_pb_window window;
int available;
+ unsigned shift;
+ stop=_b->stop;
+ ptr=_b->ptr;
window=_b->window;
available=_b->bits;
- ptr=_b->ptr;
- stop=_b->stop;
- while(available<=OC_PB_WINDOW_SIZE-8&&ptr<stop){
- available+=8;
- window|=(oc_pb_window)*ptr++<<OC_PB_WINDOW_SIZE-available;
+ shift=OC_PB_WINDOW_SIZE-available;
+ while(7<shift&&ptr<stop){
+ shift-=8;
+ window|=(oc_pb_window)*ptr++<<shift;
}
_b->ptr=ptr;
+ available=OC_PB_WINDOW_SIZE-shift;
if(_bits>available){
if(ptr>=stop){
_b->eof=1;
@@ -67,7 +70,7 @@ void oc_pack_adv1(oc_pack_buf *_b){
}
/*Here we assume that 0<=_bits&&_bits<=32.*/
-long oc_pack_read(oc_pack_buf *_b,int _bits){
+long oc_pack_read_c(oc_pack_buf *_b,int _bits){
oc_pb_window window;
int available;
long result;
@@ -82,12 +85,12 @@ long oc_pack_read(oc_pack_buf *_b,int _bits){
available-=_bits;
window<<=1;
window<<=_bits-1;
- _b->bits=available;
_b->window=window;
+ _b->bits=available;
return result;
}
-int oc_pack_read1(oc_pack_buf *_b){
+int oc_pack_read1_c(oc_pack_buf *_b){
oc_pb_window window;
int available;
int result;
@@ -100,8 +103,8 @@ int oc_pack_read1(oc_pack_buf *_b){
result=window>>OC_PB_WINDOW_SIZE-1;
available--;
window<<=1;
- _b->bits=available;
_b->window=window;
+ _b->bits=available;
return result;
}
diff --git a/thirdparty/libtheora/bitpack.h b/thirdparty/libtheora/bitpack.h
index a020a292f5..237b584055 100644
--- a/thirdparty/libtheora/bitpack.h
+++ b/thirdparty/libtheora/bitpack.h
@@ -16,15 +16,32 @@
********************************************************************/
#if !defined(_bitpack_H)
# define _bitpack_H (1)
+# include <stddef.h>
# include <limits.h>
+# include "internal.h"
-typedef unsigned long oc_pb_window;
+typedef size_t oc_pb_window;
typedef struct oc_pack_buf oc_pack_buf;
+/*Custom bitpacker implementations.*/
+# if defined(OC_ARM_ASM)
+# include "arm/armbits.h"
+# endif
+
+# if !defined(oc_pack_read)
+# define oc_pack_read oc_pack_read_c
+# endif
+# if !defined(oc_pack_read1)
+# define oc_pack_read1 oc_pack_read1_c
+# endif
+# if !defined(oc_huff_token_decode)
+# define oc_huff_token_decode oc_huff_token_decode_c
+# endif
+
# define OC_PB_WINDOW_SIZE ((int)sizeof(oc_pb_window)*CHAR_BIT)
/*This is meant to be a large, positive constant that can still be efficiently
loaded as an immediate (on platforms like ARM, for example).
@@ -34,9 +51,9 @@ typedef struct oc_pack_buf oc_pack_buf;
struct oc_pack_buf{
- oc_pb_window window;
- const unsigned char *ptr;
const unsigned char *stop;
+ const unsigned char *ptr;
+ oc_pb_window window;
int bits;
int eof;
};
@@ -45,8 +62,8 @@ void oc_pack_readinit(oc_pack_buf *_b,unsigned char *_buf,long _bytes);
int oc_pack_look1(oc_pack_buf *_b);
void oc_pack_adv1(oc_pack_buf *_b);
/*Here we assume 0<=_bits&&_bits<=32.*/
-long oc_pack_read(oc_pack_buf *_b,int _bits);
-int oc_pack_read1(oc_pack_buf *_b);
+long oc_pack_read_c(oc_pack_buf *_b,int _bits);
+int oc_pack_read1_c(oc_pack_buf *_b);
/* returns -1 for read beyond EOF, or the number of whole bytes available */
long oc_pack_bytes_left(oc_pack_buf *_b);
diff --git a/thirdparty/libtheora/collect.c b/thirdparty/libtheora/collect.c
new file mode 100644
index 0000000000..c0d8a2733f
--- /dev/null
+++ b/thirdparty/libtheora/collect.c
@@ -0,0 +1,974 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2011 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: mode selection code
+ last mod: $Id$
+
+ ********************************************************************/
+#include <stdio.h>
+#include <limits.h>
+#include <math.h>
+#include <string.h>
+#include "collect.h"
+
+#if defined(OC_COLLECT_METRICS)
+
+int OC_HAS_MODE_METRICS;
+double OC_MODE_RD_WEIGHT_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+double OC_MODE_RD_WEIGHT_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SATD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+oc_mode_metrics OC_MODE_METRICS_SAD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+const char *OC_MODE_METRICS_FILENAME="modedec.stats";
+
+void oc_mode_metrics_add(oc_mode_metrics *_metrics,
+ double _w,int _s,int _q,int _r,double _d){
+ if(_metrics->w>0){
+ double ds;
+ double dq;
+ double dr;
+ double dd;
+ double ds2;
+ double dq2;
+ double s2;
+ double sq;
+ double q2;
+ double sr;
+ double qr;
+ double sd;
+ double qd;
+ double s2q;
+ double sq2;
+ double w;
+ double wa;
+ double rwa;
+ double rwa2;
+ double rwb;
+ double rwb2;
+ double rw2;
+ double rw3;
+ double rw4;
+ wa=_metrics->w;
+ ds=_s-_metrics->s/wa;
+ dq=_q-_metrics->q/wa;
+ dr=_r-_metrics->r/wa;
+ dd=_d-_metrics->d/wa;
+ ds2=ds*ds;
+ dq2=dq*dq;
+ s2=_metrics->s2;
+ sq=_metrics->sq;
+ q2=_metrics->q2;
+ sr=_metrics->sr;
+ qr=_metrics->qr;
+ sd=_metrics->sd;
+ qd=_metrics->qd;
+ s2q=_metrics->s2q;
+ sq2=_metrics->sq2;
+ w=wa+_w;
+ rwa=wa/w;
+ rwb=_w/w;
+ rwa2=rwa*rwa;
+ rwb2=rwb*rwb;
+ rw2=wa*rwb;
+ rw3=rw2*(rwa2-rwb2);
+ rw4=_w*rwa2*rwa2+wa*rwb2*rwb2;
+ _metrics->s2q2+=-2*(ds*sq2+dq*s2q)*rwb
+ +(ds2*q2+4*ds*dq*sq+dq2*s2)*rwb2+ds2*dq2*rw4;
+ _metrics->s2q+=(-2*ds*sq-dq*s2)*rwb+ds2*dq*rw3;
+ _metrics->sq2+=(-ds*q2-2*dq*sq)*rwb+ds*dq2*rw3;
+ _metrics->sqr+=(-ds*qr-dq*sr-dr*sq)*rwb+ds*dq*dr*rw3;
+ _metrics->sqd+=(-ds*qd-dq*sd-dd*sq)*rwb+ds*dq*dd*rw3;
+ _metrics->s2+=ds2*rw2;
+ _metrics->sq+=ds*dq*rw2;
+ _metrics->q2+=dq2*rw2;
+ _metrics->sr+=ds*dr*rw2;
+ _metrics->qr+=dq*dr*rw2;
+ _metrics->r2+=dr*dr*rw2;
+ _metrics->sd+=ds*dd*rw2;
+ _metrics->qd+=dq*dd*rw2;
+ _metrics->d2+=dd*dd*rw2;
+ }
+ _metrics->w+=_w;
+ _metrics->s+=_s*_w;
+ _metrics->q+=_q*_w;
+ _metrics->r+=_r*_w;
+ _metrics->d+=_d*_w;
+}
+
+void oc_mode_metrics_merge(oc_mode_metrics *_dst,
+ const oc_mode_metrics *_src,int _n){
+ int i;
+ /*Find a non-empty set of metrics.*/
+ for(i=0;i<_n&&_src[i].w==0;i++);
+ if(i>=_n){
+ memset(_dst,0,sizeof(*_dst));
+ return;
+ }
+ memcpy(_dst,_src+i,sizeof(*_dst));
+ /*And iterate over the remaining non-empty sets of metrics.*/
+ for(i++;i<_n;i++)if(_src[i].w!=0){
+ double ds;
+ double dq;
+ double dr;
+ double dd;
+ double ds2;
+ double dq2;
+ double s2a;
+ double s2b;
+ double sqa;
+ double sqb;
+ double q2a;
+ double q2b;
+ double sra;
+ double srb;
+ double qra;
+ double qrb;
+ double sda;
+ double sdb;
+ double qda;
+ double qdb;
+ double s2qa;
+ double s2qb;
+ double sq2a;
+ double sq2b;
+ double w;
+ double wa;
+ double wb;
+ double rwa;
+ double rwb;
+ double rwa2;
+ double rwb2;
+ double rw2;
+ double rw3;
+ double rw4;
+ wa=_dst->w;
+ wb=_src[i].w;
+ ds=_src[i].s/wb-_dst->s/wa;
+ dq=_src[i].q/wb-_dst->q/wa;
+ dr=_src[i].r/wb-_dst->r/wa;
+ dd=_src[i].d/wb-_dst->d/wa;
+ ds2=ds*ds;
+ dq2=dq*dq;
+ s2a=_dst->s2;
+ sqa=_dst->sq;
+ q2a=_dst->q2;
+ sra=_dst->sr;
+ qra=_dst->qr;
+ sda=_dst->sd;
+ qda=_dst->qd;
+ s2qa=_dst->s2q;
+ sq2a=_dst->sq2;
+ s2b=_src[i].s2;
+ sqb=_src[i].sq;
+ q2b=_src[i].q2;
+ srb=_src[i].sr;
+ qrb=_src[i].qr;
+ sdb=_src[i].sd;
+ qdb=_src[i].qd;
+ s2qb=_src[i].s2q;
+ sq2b=_src[i].sq2;
+ w=wa+wb;
+ if(w==0)rwa=rwb=0;
+ else{
+ rwa=wa/w;
+ rwb=wb/w;
+ }
+ rwa2=rwa*rwa;
+ rwb2=rwb*rwb;
+ rw2=wa*rwb;
+ rw3=rw2*(rwa2-rwb2);
+ rw4=wb*rwa2*rwa2+wa*rwb2*rwb2;
+ /*
+ (1,1,1) ->
+ (0,0,0)#
+ (1,0,0) C(1,1)*C(1,0)*C(1,0)-> d^{1,0,0}*(rwa*B_{0,1,1}-rwb*A_{0,1,1})
+ (0,1,0) C(1,0)*C(1,1)*C(1,0)-> d^{0,1,0}*(rwa*B_{1,0,1}-rwb*A_{1,0,1})
+ (0,0,1) C(1,0)*C(1,0)*C(1,1)-> d^{0,0,1}*(rwa*B_{1,1,0}-rwb*A_{1,1,0})
+ (1,1,0)*
+ (1,0,1)*
+ (0,1,1)*
+ (1,1,1) C(1,1)*C(1,1)*C(1,1)-> d^{1,1,1}*(rwa^3*wb-rwb^3*wa)
+ (2,1) ->
+ (0,0)#
+ (1,0) C(2,1)*C(1,1)->2*d^{1,0}*(rwa*B_{1,1}-rwb*A_{1,1})
+ (0,1) C(2,0)*C(1,1)-> d^{0,1}*(rwa*B_{2,0}-rwb*A_{2,0})
+ (2,0)*
+ (1,1)*
+ (2,1) C(2,2)*C(1,1)-> d^{2,1}*(rwa^3*wb-rwb^3*wa)
+ (2,2) ->
+ (0,0)#
+ (1,0) C(2,1)*C(2,0)->2*d^{1,0}*(rwa*B_{1,2}-rwb*A_{1,2})
+ (0,1) C(2,0)*C(2,1)->2*d^{0,1}*(rwa*B_{2,1}-rwb*A_{2,1})
+ (2,0) C(2,2)*C(2,0)-> d^{2,0}*(rwa^2*B_{0,2}+rwb^2*A_{0,2})
+ (1,1) C(2,1)*C(2,1)->4*d^{1,1}*(rwa^2*B_{1,1}+rwb^2*A_{1,1})
+ (0,2) C(2,0)*C(2,2)-> d^{0,2}*(rwa^2*B_{2,0}+rwb^2*A_{2,0})
+ (1,2)*
+ (2,1)*
+ (2,2) C(2,2)*C(2,2)*d^{2,2}*(rwa^4*wb+rwb^4*wa)
+ */
+ _dst->s2q2+=_src[i].s2q2+2*(ds*(rwa*sq2b-rwb*sq2a)+dq*(rwa*s2qb-rwb*s2qa))
+ +ds2*(rwa2*q2b+rwb2*q2a)+4*ds*dq*(rwa2*sqb+rwb2*sqa)
+ +dq2*(rwa2*s2b+rwb2*s2a)+ds2*dq2*rw4;
+ _dst->s2q+=_src[i].s2q+2*ds*(rwa*sqb-rwb*sqa)
+ +dq*(rwa*s2b-rwb*s2a)+ds2*dq*rw3;
+ _dst->sq2+=_src[i].sq2+ds*(rwa*q2b-rwb*q2a)
+ +2*dq*(rwa*sqb-rwb*sqa)+ds*dq2*rw3;
+ _dst->sqr+=_src[i].sqr+ds*(rwa*qrb-rwb*qra)+dq*(rwa*srb-rwb*sra)
+ +dr*(rwa*sqb-rwb*sqa)+ds*dq*dr*rw3;
+ _dst->sqd+=_src[i].sqd+ds*(rwa*qdb-rwb*qda)+dq*(rwa*sdb-rwb*sda)
+ +dd*(rwa*sqb-rwb*sqa)+ds*dq*dd*rw3;
+ _dst->s2+=_src[i].s2+ds2*rw2;
+ _dst->sq+=_src[i].sq+ds*dq*rw2;
+ _dst->q2+=_src[i].q2+dq2*rw2;
+ _dst->sr+=_src[i].sr+ds*dr*rw2;
+ _dst->qr+=_src[i].qr+dq*dr*rw2;
+ _dst->r2+=_src[i].r2+dr*dr*rw2;
+ _dst->sd+=_src[i].sd+ds*dd*rw2;
+ _dst->qd+=_src[i].qd+dq*dd*rw2;
+ _dst->d2+=_src[i].d2+dd*dd*rw2;
+ _dst->w+=_src[i].w;
+ _dst->s+=_src[i].s;
+ _dst->q+=_src[i].q;
+ _dst->r+=_src[i].r;
+ _dst->d+=_src[i].d;
+ }
+}
+
+/*Adjust a single corner of a set of metric bins to minimize the squared
+ prediction error of R and D.
+ Each bin is assumed to cover a quad like so:
+ (s0,q0) (s1,q0)
+ A----------B
+ | |
+ | |
+ | |
+ | |
+ C----------Z
+ (s0,q1) (s1,q1)
+ The values A, B, and C are fixed, and Z is the free parameter.
+ Then, for example, R_i is predicted via bilinear interpolation as
+ x_i=(s_i-s0)/(s1-s0)
+ y_i=(q_i-q0)/(q1-q0)
+ dRds1_i=A+(B-A)*x_i
+ dRds2_i=C+(Z-C)*x_i
+ R_i=dRds1_i+(dRds2_i-dRds1_i)*y_i
+ To find the Z that minimizes the squared prediction error over i, this can
+ be rewritten as
+ R_i-(A+(B-A)*x_i+(C-A)*y_i+(A-B-C)*x_i*y_i)=x_i*y_i*Z
+ Letting X={...,x_i*y_i,...}^T and
+ Y={...,R_i-(A+(B-A)*x_i+(C-A)*y_i+(A-B-C)*x_i*y_i),...}^T,
+ the optimal Z is given by Z=(X^T.Y)/(X^T.X).
+ Now, we need to compute these dot products without actually storing data for
+ each sample.
+ Starting with X^T.X, we have
+ X^T.X = sum(x_i^2*y_i^2) = sum((s_i-s0)^2*(q_i-q0)^2)/((s1-s0)^2*(q1-q0)^2).
+ Expanding the interior of the sum in a monomial basis of s_i and q_i gives
+ s0^2*q0^2 *(1)
+ -2*s0*q0^2*(s_i)
+ -2*s0^2*q0*(q_i)
+ +q0^2 *(s_i^2)
+ +4*s0*q0 *(s_i*q_i)
+ +s0^2 *(q_i^2)
+ -2*q0 *(s_i^2*q_i)
+ -2*s0 *(s_i*q_i^2)
+ +1 *(s_i^2*q_i^2).
+ However, computing things directly in this basis leads to gross numerical
+ errors, as most of the terms will have similar size and destructive
+ cancellation results.
+ A much better basis is the central (co-)moment basis:
+ {1,s_i-sbar,q_i-qbar,(s_i-sbar)^2,(s_i-sbar)*(q_i-qbar),(q_i-qbar)^2,
+ (s_i-sbar)^2*(q_i-qbar),(s_i-sbar)*(q_i-qbar)^2,(s_i-sbar)^2*(q_i-qbar)^2},
+ where sbar and qbar are the average s and q values over the bin,
+ respectively.
+ In that basis, letting ds=sbar-s0 and dq=qbar-q0, (s_i-s0)^2*(q_i-q0)^2 is
+ ds^2*dq^2*(1)
+ +dq^2 *((s_i-sbar)^2)
+ +4*ds*dq*((s_i-sbar)*(q_i-qbar))
+ +ds^2 *((q_i-qbar)^2)
+ +2*dq *((s_i-sbar)^2*(q_i-qbar))
+ +2*ds *((s_i-sbar)*(q_i-qbar)^2)
+ +1 *((s_i-sbar)^2*(q_i-qbar)^2).
+ With these expressions in the central (co-)moment bases, all we need to do
+ is compute sums over the (co-)moment terms, which can be done
+ incrementally (see oc_mode_metrics_add() and oc_mode_metrics_merge()),
+ with no need to store the individual samples.
+ Now, for X^T.Y, we have
+ X^T.Y = sum((R_i-A-((B-A)/(s1-s0))*(s_i-s0)-((C-A)/(q1-q0))*(q_i-q0)
+ -((A-B-C)/((s1-s0)*(q1-q0)))*(s_i-s0)*(q_i-q0))*(s_i-s0)*(q_i-q0))/
+ ((s1-s0)*(q1-q0)),
+ or, rewriting the constants to simplify notation,
+ X^T.Y = sum((C0+C1*(s_i-s0)+C2*(q_i-q0)
+ +C3*(s_i-s0)*(q_i-q0)+R_i)*(s_i-s0)*(q_i-q0))/((s1-s0)*(q1-q0)).
+ Again, converting to the central (co-)moment basis, the interior of the
+ above sum is
+ ds*dq*(rbar+C0+C1*ds+C2*dq+C3*ds*dq) *(1)
+ +(C1*dq+C3*dq^2) *((s_i-sbar)^2)
+ +(rbar+C0+2*C1*ds+2*C2*dq+4*C3*ds*dq)*((s_i-sbar)*(q_i-qbar))
+ +(C2*ds+C3*ds^2) *((q_i-qbar)^2)
+ +dq *((s_i-sbar)*(r_i-rbar))
+ +ds *((q_i-qbar)*(r_i-rbar))
+ +(C1+2*C3*dq) *((s_i-sbar)^2*(q_i-qbar))
+ +(C2+2*C3*ds) *((s_i-sbar)*(q_i-qbar)^2)
+ +1 *((s_i-sbar)*(q_i-qbar)*(r_i-rbar))
+ +C3 *((s_i-sbar)^2*(q_i-qbar)^2).
+ You might think it would be easier (if perhaps slightly less robust) to
+ accumulate terms directly around s0 and q0.
+ However, we update each corner of the bins in turn, so we would have to
+ change basis to move the sums from corner to corner anyway.*/
+double oc_mode_metrics_solve(double *_r,double *_d,
+ const oc_mode_metrics *_metrics,const int *_s0,const int *_s1,
+ const int *_q0,const int *_q1,
+ const double *_ra,const double *_rb,const double *_rc,
+ const double *_da,const double *_db,const double *_dc,int _n){
+ double xx;
+ double rxy;
+ double dxy;
+ double wt;
+ int i;
+ xx=rxy=dxy=wt=0;
+ for(i=0;i<_n;i++)if(_metrics[i].w>0){
+ double s10;
+ double q10;
+ double sq10;
+ double ds;
+ double dq;
+ double ds2;
+ double dq2;
+ double r;
+ double d;
+ double s2;
+ double sq;
+ double q2;
+ double sr;
+ double qr;
+ double sd;
+ double qd;
+ double s2q;
+ double sq2;
+ double sqr;
+ double sqd;
+ double s2q2;
+ double c0;
+ double c1;
+ double c2;
+ double c3;
+ double w;
+ w=_metrics[i].w;
+ wt+=w;
+ s10=_s1[i]-_s0[i];
+ q10=_q1[i]-_q0[i];
+ sq10=s10*q10;
+ ds=_metrics[i].s/w-_s0[i];
+ dq=_metrics[i].q/w-_q0[i];
+ ds2=ds*ds;
+ dq2=dq*dq;
+ s2=_metrics[i].s2;
+ sq=_metrics[i].sq;
+ q2=_metrics[i].q2;
+ s2q=_metrics[i].s2q;
+ sq2=_metrics[i].sq2;
+ s2q2=_metrics[i].s2q2;
+ xx+=(dq2*(ds2*w+s2)+4*ds*dq*sq+ds2*q2+2*(dq*s2q+ds*sq2)+s2q2)/(sq10*sq10);
+ r=_metrics[i].r/w;
+ sr=_metrics[i].sr;
+ qr=_metrics[i].qr;
+ sqr=_metrics[i].sqr;
+ c0=-_ra[i];
+ c1=-(_rb[i]-_ra[i])/s10;
+ c2=-(_rc[i]-_ra[i])/q10;
+ c3=-(_ra[i]-_rb[i]-_rc[i])/sq10;
+ rxy+=(ds*dq*(r+c0+c1*ds+c2*dq+c3*ds*dq)*w+(c1*dq+c3*dq2)*s2
+ +(r+c0+2*(c1*ds+(c2+2*c3*ds)*dq))*sq+(c2*ds+c3*ds2)*q2+dq*sr+ds*qr
+ +(c1+2*c3*dq)*s2q+(c2+2*c3*ds)*sq2+sqr+c3*s2q2)/sq10;
+ d=_metrics[i].d/w;
+ sd=_metrics[i].sd;
+ qd=_metrics[i].qd;
+ sqd=_metrics[i].sqd;
+ c0=-_da[i];
+ c1=-(_db[i]-_da[i])/s10;
+ c2=-(_dc[i]-_da[i])/q10;
+ c3=-(_da[i]-_db[i]-_dc[i])/sq10;
+ dxy+=(ds*dq*(d+c0+c1*ds+c2*dq+c3*ds*dq)*w+(c1*dq+c3*dq2)*s2
+ +(d+c0+2*(c1*ds+(c2+2*c3*ds)*dq))*sq+(c2*ds+c3*ds2)*q2+dq*sd+ds*qd
+ +(c1+2*c3*dq)*s2q+(c2+2*c3*ds)*sq2+sqd+c3*s2q2)/sq10;
+ }
+ if(xx>1E-3){
+ *_r=rxy/xx;
+ *_d=dxy/xx;
+ }
+ else{
+ *_r=0;
+ *_d=0;
+ }
+ return wt;
+}
+
+/*Compile collected SATD/logq/rate/RMSE metrics into a form that's immediately
+ useful for mode decision.*/
+void oc_mode_metrics_update(oc_mode_metrics (*_metrics)[3][2][OC_COMP_BINS],
+ int _niters_min,int _reweight,oc_mode_rd (*_table)[3][2][OC_COMP_BINS],
+ int _shift,double (*_weight)[3][2][OC_COMP_BINS]){
+ int niters;
+ int prevdr;
+ int prevdd;
+ int dr;
+ int dd;
+ int pli;
+ int qti;
+ int qi;
+ int si;
+ dd=dr=INT_MAX;
+ niters=0;
+ /*The encoder interpolates rate and RMSE terms bilinearly from an
+ OC_LOGQ_BINS by OC_COMP_BINS grid of sample points in _table.
+ To find the sample values at the grid points that minimize the total
+ squared prediction error actually requires solving a relatively sparse
+ linear system with a number of variables equal to the number of grid
+ points.
+ Instead of writing a general sparse linear system solver, we just use
+ Gauss-Seidel iteration, i.e., we update one grid point at time until
+ they stop changing.*/
+ do{
+ prevdr=dr;
+ prevdd=dd;
+ dd=dr=0;
+ for(pli=0;pli<3;pli++){
+ for(qti=0;qti<2;qti++){
+ for(qi=0;qi<OC_LOGQ_BINS;qi++){
+ for(si=0;si<OC_COMP_BINS;si++){
+ oc_mode_metrics m[4];
+ int s0[4];
+ int s1[4];
+ int q0[4];
+ int q1[4];
+ double ra[4];
+ double rb[4];
+ double rc[4];
+ double da[4];
+ double db[4];
+ double dc[4];
+ double r;
+ double d;
+ int rate;
+ int rmse;
+ int ds;
+ int n;
+ n=0;
+ /*Collect the statistics for the (up to) four bins grid point
+ (si,qi) touches.*/
+ if(qi>0&&si>0){
+ q0[n]=OC_MODE_LOGQ[qi-1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si-1<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi-1][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ da[n]=ldexp(_table[qi-1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi-1][pli][qti]+si-1);
+ }
+ if(qi>0){
+ ds=si+1<OC_COMP_BINS?1:-1;
+ q0[n]=OC_MODE_LOGQ[qi-1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si+ds<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi-1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ da[n]=
+ ldexp(_table[qi-1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi-1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi-1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi-1][pli][qti]+si);
+ }
+ if(qi+1<OC_LOGQ_BINS&&si>0){
+ q0[n]=OC_MODE_LOGQ[qi+1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si-1<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi+1][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ da[n]=ldexp(_table[qi+1][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si-1].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si-1].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi][pli][qti]+si-1);
+ }
+ if(qi+1<OC_LOGQ_BINS){
+ ds=si+1<OC_COMP_BINS?1:-1;
+ q0[n]=OC_MODE_LOGQ[qi+1][pli][qti];
+ q1[n]=OC_MODE_LOGQ[qi][pli][qti];
+ s0[n]=si+ds<<_shift;
+ s1[n]=si<<_shift;
+ ra[n]=ldexp(_table[qi+1][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ da[n]=
+ ldexp(_table[qi+1][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ rb[n]=ldexp(_table[qi+1][pli][qti][si].rate,-OC_BIT_SCALE);
+ db[n]=ldexp(_table[qi+1][pli][qti][si].rmse,-OC_RMSE_SCALE);
+ rc[n]=ldexp(_table[qi][pli][qti][si+ds].rate,-OC_BIT_SCALE);
+ dc[n]=ldexp(_table[qi][pli][qti][si+ds].rmse,-OC_RMSE_SCALE);
+ *(m+n++)=*(_metrics[qi][pli][qti]+si);
+ }
+ /*On the first pass, initialize with a simple weighted average of
+ the neighboring bins.*/
+ if(!OC_HAS_MODE_METRICS&&niters==0){
+ double w;
+ w=r=d=0;
+ while(n-->0){
+ w+=m[n].w;
+ r+=m[n].r;
+ d+=m[n].d;
+ }
+ r=w>1E-3?r/w:0;
+ d=w>1E-3?d/w:0;
+ _weight[qi][pli][qti][si]=w;
+ }
+ else{
+ /*Update the grid point and save the weight for later.*/
+ _weight[qi][pli][qti][si]=
+ oc_mode_metrics_solve(&r,&d,m,s0,s1,q0,q1,ra,rb,rc,da,db,dc,n);
+ }
+ rate=OC_CLAMPI(-32768,(int)(ldexp(r,OC_BIT_SCALE)+0.5),32767);
+ rmse=OC_CLAMPI(-32768,(int)(ldexp(d,OC_RMSE_SCALE)+0.5),32767);
+ dr+=abs(rate-_table[qi][pli][qti][si].rate);
+ dd+=abs(rmse-_table[qi][pli][qti][si].rmse);
+ _table[qi][pli][qti][si].rate=(ogg_int16_t)rate;
+ _table[qi][pli][qti][si].rmse=(ogg_int16_t)rmse;
+ }
+ }
+ }
+ }
+ }
+ /*After a fixed number of initial iterations, only iterate so long as the
+ total change is decreasing.
+ This ensures we don't oscillate forever, which is a danger, as all of our
+ results are rounded fairly coarsely.*/
+ while((dr>0||dd>0)&&(niters++<_niters_min||(dr<prevdr&&dd<prevdd)));
+ if(_reweight){
+ /*Now, reduce the values of the optimal solution until we get enough
+ samples in each bin to overcome the constant OC_ZWEIGHT factor.
+ This encourages sampling under-populated bins and prevents a single large
+ sample early on from discouraging coding in that bin ever again.*/
+ for(pli=0;pli<3;pli++){
+ for(qti=0;qti<2;qti++){
+ for(qi=0;qi<OC_LOGQ_BINS;qi++){
+ for(si=0;si<OC_COMP_BINS;si++){
+ double wt;
+ wt=_weight[qi][pli][qti][si];
+ wt/=OC_ZWEIGHT+wt;
+ _table[qi][pli][qti][si].rate=(ogg_int16_t)
+ (_table[qi][pli][qti][si].rate*wt+0.5);
+ _table[qi][pli][qti][si].rmse=(ogg_int16_t)
+ (_table[qi][pli][qti][si].rmse*wt+0.5);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*Dump the in memory mode metrics to a file.
+ Note this data format isn't portable between different platforms.*/
+void oc_mode_metrics_dump(void){
+ FILE *fmetrics;
+ fmetrics=fopen(OC_MODE_METRICS_FILENAME,"wb");
+ if(fmetrics!=NULL){
+ (void)fwrite(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics);
+ (void)fwrite(OC_MODE_METRICS_SATD,sizeof(OC_MODE_METRICS_SATD),1,fmetrics);
+ (void)fwrite(OC_MODE_METRICS_SAD,sizeof(OC_MODE_METRICS_SAD),1,fmetrics);
+ fclose(fmetrics);
+ }
+}
+
+void oc_mode_metrics_print_rd(FILE *_fout,const char *_table_name,
+#if !defined(OC_COLLECT_METRICS)
+ const oc_mode_rd (*_mode_rd_table)[3][2][OC_COMP_BINS]){
+#else
+ oc_mode_rd (*_mode_rd_table)[3][2][OC_COMP_BINS]){
+#endif
+ int qii;
+ fprintf(_fout,
+ "# if !defined(OC_COLLECT_METRICS)\n"
+ "static const\n"
+ "# endif\n"
+ "oc_mode_rd %s[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={\n",_table_name);
+ for(qii=0;qii<OC_LOGQ_BINS;qii++){
+ int pli;
+ fprintf(_fout," {\n");
+ for(pli=0;pli<3;pli++){
+ int qti;
+ fprintf(_fout," {\n");
+ for(qti=0;qti<2;qti++){
+ int bin;
+ int qi;
+ static const char *pl_names[3]={"Y'","Cb","Cr"};
+ static const char *qti_names[2]={"INTRA","INTER"};
+ qi=(63*qii+(OC_LOGQ_BINS-1>>1))/(OC_LOGQ_BINS-1);
+ fprintf(_fout," /*%s qi=%i %s*/\n",
+ pl_names[pli],qi,qti_names[qti]);
+ fprintf(_fout," {\n");
+ fprintf(_fout," ");
+ for(bin=0;bin<OC_COMP_BINS;bin++){
+ if(bin&&!(bin&0x3))fprintf(_fout,"\n ");
+ fprintf(_fout,"{%5i,%5i}",
+ _mode_rd_table[qii][pli][qti][bin].rate,
+ _mode_rd_table[qii][pli][qti][bin].rmse);
+ if(bin+1<OC_COMP_BINS)fprintf(_fout,",");
+ }
+ fprintf(_fout,"\n }");
+ if(qti<1)fprintf(_fout,",");
+ fprintf(_fout,"\n");
+ }
+ fprintf(_fout," }");
+ if(pli<2)fprintf(_fout,",");
+ fprintf(_fout,"\n");
+ }
+ fprintf(_fout," }");
+ if(qii+1<OC_LOGQ_BINS)fprintf(_fout,",");
+ fprintf(_fout,"\n");
+ }
+ fprintf(_fout,
+ "};\n"
+ "\n");
+}
+
+void oc_mode_metrics_print(FILE *_fout){
+ int qii;
+ fprintf(_fout,
+ "/*File generated by libtheora with OC_COLLECT_METRICS"
+ " defined at compile time.*/\n"
+ "#if !defined(_modedec_H)\n"
+ "# define _modedec_H (1)\n"
+ "# include \"encint.h\"\n"
+ "\n"
+ "\n"
+ "\n"
+ "/*The log of the average quantizer for each of the OC_MODE_RD table rows\n"
+ " (e.g., for the represented qi's, and each pli and qti), in Q10 format.\n"
+ " The actual statistics used by the encoder will be interpolated from\n"
+ " that table based on log_plq for the actual quantization matrix used.*/\n"
+ "# if !defined(OC_COLLECT_METRICS)\n"
+ "static const\n"
+ "# endif\n"
+ "ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2]={\n");
+ for(qii=0;qii<OC_LOGQ_BINS;qii++){
+ fprintf(_fout," { {0x%04X,0x%04X},{0x%04X,0x%04X},{0x%04X,0x%04X} }%s\n",
+ OC_MODE_LOGQ[qii][0][0],OC_MODE_LOGQ[qii][0][1],OC_MODE_LOGQ[qii][1][0],
+ OC_MODE_LOGQ[qii][1][1],OC_MODE_LOGQ[qii][2][0],OC_MODE_LOGQ[qii][2][1],
+ qii+1<OC_LOGQ_BINS?",":"");
+ }
+ fprintf(_fout,
+ "};\n"
+ "\n");
+ oc_mode_metrics_print_rd(_fout,"OC_MODE_RD_SATD",OC_MODE_RD_SATD);
+ oc_mode_metrics_print_rd(_fout,"OC_MODE_RD_SAD",OC_MODE_RD_SAD);
+ fprintf(_fout,
+ "#endif\n");
+}
+
+
+# if !defined(OC_COLLECT_NO_ENC_FUNCS)
+void oc_enc_mode_metrics_load(oc_enc_ctx *_enc){
+ oc_restore_fpu(&_enc->state);
+ /*Load any existing mode metrics if we haven't already.*/
+ if(!OC_HAS_MODE_METRICS){
+ FILE *fmetrics;
+ memset(OC_MODE_METRICS_SATD,0,sizeof(OC_MODE_METRICS_SATD));
+ memset(OC_MODE_METRICS_SAD,0,sizeof(OC_MODE_METRICS_SAD));
+ fmetrics=fopen(OC_MODE_METRICS_FILENAME,"rb");
+ if(fmetrics!=NULL){
+ /*Read in the binary structures as written my oc_mode_metrics_dump().
+ Note this format isn't portable between different platforms.*/
+ (void)fread(OC_MODE_LOGQ,sizeof(OC_MODE_LOGQ),1,fmetrics);
+ (void)fread(OC_MODE_METRICS_SATD,sizeof(OC_MODE_METRICS_SATD),1,fmetrics);
+ (void)fread(OC_MODE_METRICS_SAD,sizeof(OC_MODE_METRICS_SAD),1,fmetrics);
+ fclose(fmetrics);
+ }
+ else{
+ int qii;
+ int qi;
+ int pli;
+ int qti;
+ for(qii=0;qii<OC_LOGQ_BINS;qii++){
+ qi=(63*qii+(OC_LOGQ_BINS-1>>1))/(OC_LOGQ_BINS-1);
+ for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ OC_MODE_LOGQ[qii][pli][qti]=_enc->log_plq[qi][pli][qti];
+ }
+ }
+ }
+ oc_mode_metrics_update(OC_MODE_METRICS_SATD,100,1,
+ OC_MODE_RD_SATD,OC_SATD_SHIFT,OC_MODE_RD_WEIGHT_SATD);
+ oc_mode_metrics_update(OC_MODE_METRICS_SAD,100,1,
+ OC_MODE_RD_SAD,OC_SAD_SHIFT,OC_MODE_RD_WEIGHT_SAD);
+ OC_HAS_MODE_METRICS=1;
+ }
+}
+
+/*The following token skipping code used to also be used in the decoder (and
+ even at one point other places in the encoder).
+ However, it was obsoleted by other optimizations, and is now only used here.
+ It has been moved here to avoid generating the code when it's not needed.*/
+
+/*Determines the number of blocks or coefficients to be skipped for a given
+ token value.
+ _token: The token value to skip.
+ _extra_bits: The extra bits attached to this token.
+ Return: A positive value indicates that number of coefficients are to be
+ skipped in the current block.
+ Otherwise, the negative of the return value indicates that number of
+ blocks are to be ended.*/
+typedef ptrdiff_t (*oc_token_skip_func)(int _token,int _extra_bits);
+
+/*Handles the simple end of block tokens.*/
+static ptrdiff_t oc_token_skip_eob(int _token,int _extra_bits){
+ int nblocks_adjust;
+ nblocks_adjust=OC_UNIBBLE_TABLE32(0,1,2,3,7,15,0,0,_token)+1;
+ return -_extra_bits-nblocks_adjust;
+}
+
+/*The last EOB token has a special case, where an EOB run of size zero ends all
+ the remaining blocks in the frame.*/
+static ptrdiff_t oc_token_skip_eob6(int _token,int _extra_bits){
+ /*Note: We want to return -PTRDIFF_MAX, but that requires C99, which is not
+ yet available everywhere; this should be equivalent.*/
+ if(!_extra_bits)return -(~(size_t)0>>1);
+ return -_extra_bits;
+}
+
+/*Handles the pure zero run tokens.*/
+static ptrdiff_t oc_token_skip_zrl(int _token,int _extra_bits){
+ return _extra_bits+1;
+}
+
+/*Handles a normal coefficient value token.*/
+static ptrdiff_t oc_token_skip_val(void){
+ return 1;
+}
+
+/*Handles a category 1A zero run/coefficient value combo token.*/
+static ptrdiff_t oc_token_skip_run_cat1a(int _token){
+ return _token-OC_DCT_RUN_CAT1A+2;
+}
+
+/*Handles category 1b, 1c, 2a, and 2b zero run/coefficient value combo tokens.*/
+static ptrdiff_t oc_token_skip_run(int _token,int _extra_bits){
+ int run_cati;
+ int ncoeffs_mask;
+ int ncoeffs_adjust;
+ run_cati=_token-OC_DCT_RUN_CAT1B;
+ ncoeffs_mask=OC_BYTE_TABLE32(3,7,0,1,run_cati);
+ ncoeffs_adjust=OC_BYTE_TABLE32(7,11,2,3,run_cati);
+ return (_extra_bits&ncoeffs_mask)+ncoeffs_adjust;
+}
+
+/*A jump table for computing the number of coefficients or blocks to skip for
+ a given token value.
+ This reduces all the conditional branches, etc., needed to parse these token
+ values down to one indirect jump.*/
+static const oc_token_skip_func OC_TOKEN_SKIP_TABLE[TH_NDCT_TOKENS]={
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob,
+ oc_token_skip_eob6,
+ oc_token_skip_zrl,
+ oc_token_skip_zrl,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_val,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ (oc_token_skip_func)oc_token_skip_run_cat1a,
+ oc_token_skip_run,
+ oc_token_skip_run,
+ oc_token_skip_run,
+ oc_token_skip_run
+};
+
+/*Determines the number of blocks or coefficients to be skipped for a given
+ token value.
+ _token: The token value to skip.
+ _extra_bits: The extra bits attached to this token.
+ Return: A positive value indicates that number of coefficients are to be
+ skipped in the current block.
+ Otherwise, the negative of the return value indicates that number of
+ blocks are to be ended.
+ 0 will never be returned, so that at least one coefficient in one
+ block will always be decoded for every token.*/
+static ptrdiff_t oc_dct_token_skip(int _token,int _extra_bits){
+ return (*OC_TOKEN_SKIP_TABLE[_token])(_token,_extra_bits);
+}
+
+
+void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc){
+ static const unsigned char OC_ZZI_HUFF_OFFSET[64]={
+ 0,16,16,16,16,16,32,32,
+ 32,32,32,32,32,32,32,48,
+ 48,48,48,48,48,48,48,48,
+ 48,48,48,48,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64
+ };
+ const oc_fragment *frags;
+ const unsigned *frag_sad;
+ const unsigned *frag_satd;
+ const unsigned *frag_ssd;
+ const ptrdiff_t *coded_fragis;
+ ptrdiff_t ncoded_fragis;
+ ptrdiff_t fragii;
+ double fragw;
+ int modelines[3][3][2];
+ int qti;
+ int qii;
+ int qi;
+ int pli;
+ int zzi;
+ int token;
+ int eb;
+ oc_restore_fpu(&_enc->state);
+ /*Figure out which metric bins to use for this frame's quantizers.*/
+ for(qii=0;qii<_enc->state.nqis;qii++){
+ for(pli=0;pli<3;pli++){
+ for(qti=0;qti<2;qti++){
+ int log_plq;
+ int modeline;
+ log_plq=_enc->log_plq[_enc->state.qis[qii]][pli][qti];
+ for(modeline=0;modeline<OC_LOGQ_BINS-1&&
+ OC_MODE_LOGQ[modeline+1][pli][qti]>log_plq;modeline++);
+ modelines[qii][pli][qti]=modeline;
+ }
+ }
+ }
+ qti=_enc->state.frame_type;
+ frags=_enc->state.frags;
+ frag_sad=_enc->frag_sad;
+ frag_satd=_enc->frag_satd;
+ frag_ssd=_enc->frag_ssd;
+ coded_fragis=_enc->state.coded_fragis;
+ ncoded_fragis=fragii=0;
+ /*Weight the fragments by the inverse frame size; this prevents HD content
+ from dominating the statistics.*/
+ fragw=1.0/_enc->state.nfrags;
+ for(pli=0;pli<3;pli++){
+ ptrdiff_t ti[64];
+ int eob_token[64];
+ int eob_run[64];
+ /*Set up token indices and eob run counts.
+ We don't bother trying to figure out the real cost of the runs that span
+ coefficients; instead we use the costs that were available when R-D
+ token optimization was done.*/
+ for(zzi=0;zzi<64;zzi++){
+ ti[zzi]=_enc->dct_token_offs[pli][zzi];
+ if(ti[zzi]>0){
+ token=_enc->dct_tokens[pli][zzi][0];
+ eb=_enc->extra_bits[pli][zzi][0];
+ eob_token[zzi]=token;
+ eob_run[zzi]=-oc_dct_token_skip(token,eb);
+ }
+ else{
+ eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
+ eob_run[zzi]=0;
+ }
+ }
+ /*Scan the list of coded fragments for this plane.*/
+ ncoded_fragis+=_enc->state.ncoded_fragis[pli];
+ for(;fragii<ncoded_fragis;fragii++){
+ ptrdiff_t fragi;
+ int frag_bits;
+ int huffi;
+ int skip;
+ int mb_mode;
+ unsigned sad;
+ unsigned satd;
+ double sqrt_ssd;
+ int bin;
+ int qtj;
+ fragi=coded_fragis[fragii];
+ frag_bits=0;
+ for(zzi=0;zzi<64;){
+ if(eob_run[zzi]>0){
+ /*We've reached the end of the block.*/
+ eob_run[zzi]--;
+ break;
+ }
+ huffi=_enc->huff_idxs[qti][zzi>0][pli+1>>1]
+ +OC_ZZI_HUFF_OFFSET[zzi];
+ if(eob_token[zzi]<OC_NDCT_EOB_TOKEN_MAX){
+ /*This token caused an EOB run to be flushed.
+ Therefore it gets the bits associated with it.*/
+ frag_bits+=_enc->huff_codes[huffi][eob_token[zzi]].nbits
+ +OC_DCT_TOKEN_EXTRA_BITS[eob_token[zzi]];
+ eob_token[zzi]=OC_NDCT_EOB_TOKEN_MAX;
+ }
+ token=_enc->dct_tokens[pli][zzi][ti[zzi]];
+ eb=_enc->extra_bits[pli][zzi][ti[zzi]];
+ ti[zzi]++;
+ skip=oc_dct_token_skip(token,eb);
+ if(skip<0){
+ eob_token[zzi]=token;
+ eob_run[zzi]=-skip;
+ }
+ else{
+ /*A regular DCT value token; accumulate the bits for it.*/
+ frag_bits+=_enc->huff_codes[huffi][token].nbits
+ +OC_DCT_TOKEN_EXTRA_BITS[token];
+ zzi+=skip;
+ }
+ }
+ mb_mode=frags[fragi].mb_mode;
+ qii=frags[fragi].qii;
+ qi=_enc->state.qis[qii];
+ sad=frag_sad[fragi]<<(pli+1&2);
+ satd=frag_satd[fragi]<<(pli+1&2);
+ sqrt_ssd=sqrt(frag_ssd[fragi]);
+ qtj=mb_mode!=OC_MODE_INTRA;
+ /*Accumulate statistics.
+ The rate (frag_bits) and RMSE (sqrt(frag_ssd)) are not scaled by
+ OC_BIT_SCALE and OC_RMSE_SCALE; this lets us change the scale factor
+ yet still use old data.*/
+ bin=OC_MINI(satd>>OC_SATD_SHIFT,OC_COMP_BINS-1);
+ oc_mode_metrics_add(
+ OC_MODE_METRICS_SATD[modelines[qii][pli][qtj]][pli][qtj]+bin,
+ fragw,satd,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt_ssd);
+ bin=OC_MINI(sad>>OC_SAD_SHIFT,OC_COMP_BINS-1);
+ oc_mode_metrics_add(
+ OC_MODE_METRICS_SAD[modelines[qii][pli][qtj]][pli][qtj]+bin,
+ fragw,sad,_enc->log_plq[qi][pli][qtj],frag_bits,sqrt_ssd);
+ }
+ }
+ /*Update global SA(T)D/logq/rate/RMSE estimation matrix.*/
+ oc_mode_metrics_update(OC_MODE_METRICS_SATD,4,1,
+ OC_MODE_RD_SATD,OC_SATD_SHIFT,OC_MODE_RD_WEIGHT_SATD);
+ oc_mode_metrics_update(OC_MODE_METRICS_SAD,4,1,
+ OC_MODE_RD_SAD,OC_SAD_SHIFT,OC_MODE_RD_WEIGHT_SAD);
+}
+# endif
+
+#endif
diff --git a/thirdparty/libtheora/collect.h b/thirdparty/libtheora/collect.h
new file mode 100644
index 0000000000..9458b84e3f
--- /dev/null
+++ b/thirdparty/libtheora/collect.h
@@ -0,0 +1,109 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: mode selection code
+ last mod: $Id$
+
+ ********************************************************************/
+#if !defined(_collect_H)
+# define _collect_H (1)
+# include "encint.h"
+# if defined(OC_COLLECT_METRICS)
+# include <stdio.h>
+
+
+
+typedef struct oc_mode_metrics oc_mode_metrics;
+
+
+
+/**Sets the file name to load/store mode metrics from/to.
+ * The file name string is stored by reference, and so must be valid for the
+ * lifetime of the encoder.
+ * Mode metric collection uses global tables; do not attempt to perform
+ * multiple collections at once.
+ * \param[in] _buf <tt>char[]</tt> The file name.
+ * \retval TH_EIMPL Not supported by this implementation.*/
+#define TH_ENCCTL_SET_METRICS_FILE (0x8000)
+
+
+
+/*Accumulates various weighted sums of the measurements.
+ w -> weight
+ s -> SATD
+ q -> log quantizer
+ r -> rate (in bits)
+ d -> RMSE
+ All of the single letters correspond to direct, weighted sums, e.g.,
+ w=sum(w_i), s=sum(s_i*w_i), etc.
+ The others correspond to central moments (or co-moments) of the given order,
+ e.g., sq=sum((s_i-s/w)*(q_i-q/w)*w_i).
+ Because we need some moments up to fourth order, we use central moments to
+ minimize the dynamic range and prevent rounding error from dominating the
+ calculations.*/
+struct oc_mode_metrics{
+ double w;
+ double s;
+ double q;
+ double r;
+ double d;
+ double s2;
+ double sq;
+ double q2;
+ double sr;
+ double qr;
+ double r2;
+ double sd;
+ double qd;
+ double d2;
+ double s2q;
+ double sq2;
+ double sqr;
+ double sqd;
+ double s2q2;
+};
+
+
+# define OC_ZWEIGHT (0.25)
+
+/*TODO: It may be helpful (for block-level quantizers especially) to separate
+ out the contributions from AC and DC into separate tables.*/
+
+extern ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2];
+extern oc_mode_rd OC_MODE_RD_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+extern oc_mode_rd OC_MODE_RD_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS];
+
+extern int OC_HAS_MODE_METRICS;
+extern oc_mode_metrics OC_MODE_METRICS_SATD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+extern oc_mode_metrics OC_MODE_METRICS_SAD[OC_LOGQ_BINS-1][3][2][OC_COMP_BINS];
+extern const char *OC_MODE_METRICS_FILENAME;
+
+void oc_mode_metrics_dump();
+void oc_mode_metrics_print(FILE *_fout);
+
+void oc_mode_metrics_add(oc_mode_metrics *_metrics,
+ double _w,int _s,int _q,int _r,double _d);
+void oc_mode_metrics_merge(oc_mode_metrics *_dst,
+ const oc_mode_metrics *_src,int _n);
+double oc_mode_metrics_solve(double *_r,double *_d,
+ const oc_mode_metrics *_metrics,const int *_s0,const int *_s1,
+ const int *_q0,const int *_q1,
+ const double *_ra,const double *_rb,const double *_rc,
+ const double *_da,const double *_db,const double *_dc,int _n);
+void oc_mode_metrics_update(oc_mode_metrics (*_metrics)[3][2][OC_COMP_BINS],
+ int _niters_min,int _reweight,oc_mode_rd (*_table)[3][2][OC_COMP_BINS],
+ int shift,double (*_weight)[3][2][OC_COMP_BINS]);
+void oc_enc_mode_metrics_load(oc_enc_ctx *_enc);
+void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc);
+
+# endif
+#endif
diff --git a/thirdparty/libtheora/dct.h b/thirdparty/libtheora/dct.h
index 24ba6f111a..8052ea6bc1 100644
--- a/thirdparty/libtheora/dct.h
+++ b/thirdparty/libtheora/dct.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: dct.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/decinfo.c b/thirdparty/libtheora/decinfo.c
index 845eb1361c..a91e740b15 100644
--- a/thirdparty/libtheora/decinfo.c
+++ b/thirdparty/libtheora/decinfo.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: decinfo.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -20,6 +20,11 @@
#include <limits.h>
#include "decint.h"
+/*Only used for fuzzing.*/
+#if defined(HAVE_MEMORY_CONSTRAINT)
+static const int MAX_FUZZING_WIDTH = 16384;
+static const int MAX_FUZZING_HEIGHT = 16384;
+#endif
/*Unpacks a series of octets from a given byte array into the pack buffer.
@@ -55,8 +60,8 @@ static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
/*verify we can parse this bitstream version.
We accept earlier minors and all subminors, by spec*/
if(_info->version_major>TH_VERSION_MAJOR||
- _info->version_major==TH_VERSION_MAJOR&&
- _info->version_minor>TH_VERSION_MINOR){
+ (_info->version_major==TH_VERSION_MAJOR&&
+ _info->version_minor>TH_VERSION_MINOR)){
return TH_EVERSION;
}
/*Read the encoded frame description.*/
@@ -82,6 +87,11 @@ static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
_info->fps_numerator==0||_info->fps_denominator==0){
return TH_EBADHEADER;
}
+#if defined(HAVE_MEMORY_CONSTRAINT)
+ if(_info->frame_width>=MAX_FUZZING_WIDTH&&_info->frame_height>=MAX_FUZZING_HEIGHT){
+ return TH_EBADHEADER;
+ }
+#endif
/*Note: The sense of pic_y is inverted in what we pass back to the
application compared to how it is stored in the bitstream.
This is because the bitstream uses a right-handed coordinate system, while
@@ -128,6 +138,10 @@ static int oc_comment_unpack(oc_pack_buf *_opb,th_comment *_tc){
_tc->comments*sizeof(_tc->comment_lengths[0]));
_tc->user_comments=(char **)_ogg_malloc(
_tc->comments*sizeof(_tc->user_comments[0]));
+ if(_tc->comment_lengths==NULL||_tc->user_comments==NULL){
+ _tc->comments=0;
+ return TH_EFAULT;
+ }
for(i=0;i<_tc->comments;i++){
len=oc_unpack_length(_opb);
if(len<0||len>oc_pack_bytes_left(_opb)){
@@ -168,9 +182,23 @@ static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info,
int ret;
val=oc_pack_read(_opb,8);
packtype=(int)val;
- /*If we're at a data packet and we have received all three headers, we're
- done.*/
- if(!(packtype&0x80)&&_info->frame_width>0&&_tc->vendor!=NULL&&*_setup!=NULL){
+ /*If we're at a data packet...*/
+ if(!(packtype&0x80)){
+ /*Check to make sure we received all three headers...
+ If we haven't seen any valid headers, assume this is not actually
+ Theora.*/
+ if(_info->frame_width<=0)return TH_ENOTFORMAT;
+ /*Follow our documentation, which says we'll return TH_EFAULT if this
+ are NULL (_info was checked by our caller).*/
+ if(_tc==NULL)return TH_EFAULT;
+ /*And if any other headers were missing, declare this packet "out of
+ sequence" instead.*/
+ if(_tc->vendor==NULL)return TH_EBADHEADER;
+ /*Don't check this until it's needed, since we allow passing NULL for the
+ arguments that we're not expecting the next header to fill in yet.*/
+ if(_setup==NULL)return TH_EFAULT;
+ if(*_setup==NULL)return TH_EBADHEADER;
+ /*If we got everything, we're done.*/
return 0;
}
/*Check the codec string.*/
diff --git a/thirdparty/libtheora/decint.h b/thirdparty/libtheora/decint.h
index 261b67631a..3cea6b1439 100644
--- a/thirdparty/libtheora/decint.h
+++ b/thirdparty/libtheora/decint.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: decint.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,15 +19,39 @@
#if !defined(_decint_H)
# define _decint_H (1)
# include "theora/theoradec.h"
-# include "internal.h"
+# include "state.h"
# include "bitpack.h"
-
-typedef struct th_setup_info oc_setup_info;
-typedef struct th_dec_ctx oc_dec_ctx;
-
# include "huffdec.h"
# include "dequant.h"
+typedef struct th_setup_info oc_setup_info;
+typedef struct oc_dec_opt_vtable oc_dec_opt_vtable;
+typedef struct oc_dec_pipeline_state oc_dec_pipeline_state;
+typedef struct th_dec_ctx oc_dec_ctx;
+
+
+
+/*Decoder-specific accelerated functions.*/
+# if defined(OC_C64X_ASM)
+# include "c64x/c64xdec.h"
+# endif
+
+# if !defined(oc_dec_accel_init)
+# define oc_dec_accel_init oc_dec_accel_init_c
+# endif
+# if defined(OC_DEC_USE_VTABLE)
+# if !defined(oc_dec_dc_unpredict_mcu_plane)
+# define oc_dec_dc_unpredict_mcu_plane(_dec,_pipe,_pli) \
+ ((*(_dec)->opt_vtable.dc_unpredict_mcu_plane)(_dec,_pipe,_pli))
+# endif
+# else
+# if !defined(oc_dec_dc_unpredict_mcu_plane)
+# define oc_dec_dc_unpredict_mcu_plane oc_dec_dc_unpredict_mcu_plane_c
+# endif
+# endif
+
+
+
/*Constants for the packet-in state machine specific to the decoder.*/
/*Next packet to read: Data packet.*/
@@ -37,71 +61,125 @@ typedef struct th_dec_ctx oc_dec_ctx;
struct th_setup_info{
/*The Huffman codes.*/
- oc_huff_node *huff_tables[TH_NHUFFMAN_TABLES];
+ ogg_int16_t *huff_tables[TH_NHUFFMAN_TABLES];
/*The quantization parameters.*/
th_quant_info qinfo;
};
+/*Decoder specific functions with accelerated variants.*/
+struct oc_dec_opt_vtable{
+ void (*dc_unpredict_mcu_plane)(oc_dec_ctx *_dec,
+ oc_dec_pipeline_state *_pipe,int _pli);
+};
+
+
+
+struct oc_dec_pipeline_state{
+ /*Decoded DCT coefficients.
+ These are placed here instead of on the stack so that they can persist
+ between blocks, which makes clearing them back to zero much faster when
+ only a few non-zero coefficients were decoded.
+ It requires at least 65 elements because the zig-zag index array uses the
+ 65th element as a dumping ground for out-of-range indices to protect us
+ from buffer overflow.
+ We make it fully twice as large so that the second half can serve as the
+ reconstruction buffer, which saves passing another parameter to all the
+ acceleration functios.
+ It also solves problems with 16-byte alignment for NEON on ARM.
+ gcc (as of 4.2.1) only seems to be able to give stack variables 8-byte
+ alignment, and silently produces incorrect results if you ask for 16.
+ Finally, keeping it off the stack means there's less likely to be a data
+ hazard beween the NEON co-processor and the regular ARM core, which avoids
+ unnecessary stalls.*/
+ OC_ALIGN16(ogg_int16_t dct_coeffs[128]);
+ OC_ALIGN16(signed char bounding_values[256]);
+ ptrdiff_t ti[3][64];
+ ptrdiff_t ebi[3][64];
+ ptrdiff_t eob_runs[3][64];
+ const ptrdiff_t *coded_fragis[3];
+ const ptrdiff_t *uncoded_fragis[3];
+ ptrdiff_t ncoded_fragis[3];
+ ptrdiff_t nuncoded_fragis[3];
+ const ogg_uint16_t *dequant[3][3][2];
+ int fragy0[3];
+ int fragy_end[3];
+ int pred_last[3][4];
+ int mcu_nvfrags;
+ int loop_filter;
+ int pp_level;
+};
+
+
struct th_dec_ctx{
/*Shared encoder/decoder state.*/
- oc_theora_state state;
+ oc_theora_state state;
/*Whether or not packets are ready to be emitted.
This takes on negative values while there are remaining header packets to
be emitted, reaches 0 when the codec is ready for input, and goes to 1
when a frame has been processed and a data packet is ready.*/
- int packet_state;
+ int packet_state;
/*Buffer in which to assemble packets.*/
- oc_pack_buf opb;
+ oc_pack_buf opb;
/*Huffman decode trees.*/
- oc_huff_node *huff_tables[TH_NHUFFMAN_TABLES];
+ ogg_int16_t *huff_tables[TH_NHUFFMAN_TABLES];
/*The index of the first token in each plane for each coefficient.*/
- ptrdiff_t ti0[3][64];
+ ptrdiff_t ti0[3][64];
/*The number of outstanding EOB runs at the start of each coefficient in each
plane.*/
- ptrdiff_t eob_runs[3][64];
+ ptrdiff_t eob_runs[3][64];
/*The DCT token lists.*/
- unsigned char *dct_tokens;
+ unsigned char *dct_tokens;
/*The extra bits associated with DCT tokens.*/
- unsigned char *extra_bits;
+ unsigned char *extra_bits;
/*The number of dct tokens unpacked so far.*/
- int dct_tokens_count;
+ int dct_tokens_count;
/*The out-of-loop post-processing level.*/
- int pp_level;
+ int pp_level;
/*The DC scale used for out-of-loop deblocking.*/
- int pp_dc_scale[64];
+ int pp_dc_scale[64];
/*The sharpen modifier used for out-of-loop deringing.*/
- int pp_sharp_mod[64];
+ int pp_sharp_mod[64];
/*The DC quantization index of each block.*/
- unsigned char *dc_qis;
+ unsigned char *dc_qis;
/*The variance of each block.*/
- int *variances;
+ int *variances;
/*The storage for the post-processed frame buffer.*/
- unsigned char *pp_frame_data;
+ unsigned char *pp_frame_data;
/*Whether or not the post-processsed frame buffer has space for chroma.*/
- int pp_frame_state;
+ int pp_frame_state;
/*The buffer used for the post-processed frame.
Note that this is _not_ guaranteed to have the same strides and offsets as
the reference frame buffers.*/
- th_ycbcr_buffer pp_frame_buf;
+ th_ycbcr_buffer pp_frame_buf;
/*The striped decode callback function.*/
- th_stripe_callback stripe_cb;
+ th_stripe_callback stripe_cb;
+ oc_dec_pipeline_state pipe;
+# if defined(OC_DEC_USE_VTABLE)
+ /*Table for decoder acceleration functions.*/
+ oc_dec_opt_vtable opt_vtable;
+# endif
# if defined(HAVE_CAIRO)
/*Output metrics for debugging.*/
- int telemetry;
- int telemetry_mbmode;
- int telemetry_mv;
- int telemetry_qi;
- int telemetry_bits;
- int telemetry_frame_bytes;
- int telemetry_coding_bytes;
- int telemetry_mode_bytes;
- int telemetry_mv_bytes;
- int telemetry_qi_bytes;
- int telemetry_dc_bytes;
- unsigned char *telemetry_frame_data;
+ int telemetry_mbmode;
+ int telemetry_mv;
+ int telemetry_qi;
+ int telemetry_bits;
+ int telemetry_frame_bytes;
+ int telemetry_coding_bytes;
+ int telemetry_mode_bytes;
+ int telemetry_mv_bytes;
+ int telemetry_qi_bytes;
+ int telemetry_dc_bytes;
+ unsigned char *telemetry_frame_data;
# endif
};
+/*Default pure-C implementations of decoder-specific accelerated functions.*/
+void oc_dec_accel_init_c(oc_dec_ctx *_dec);
+
+void oc_dec_dc_unpredict_mcu_plane_c(oc_dec_ctx *_dec,
+ oc_dec_pipeline_state *_pipe,int _pli);
+
#endif
diff --git a/thirdparty/libtheora/decode.c b/thirdparty/libtheora/decode.c
index bde967b794..fad26e0927 100644
--- a/thirdparty/libtheora/decode.c
+++ b/thirdparty/libtheora/decode.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: decode.c 16581 2009-09-25 22:56:16Z gmaxwell $
+ last mod: $Id$
********************************************************************/
@@ -118,7 +118,7 @@ static const unsigned char OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[15]={
/*Whether or not an internal token needs any additional extra bits.*/
#define OC_DCT_TOKEN_NEEDS_MORE(token) \
- (token<(sizeof(OC_INTERNAL_DCT_TOKEN_EXTRA_BITS)/ \
+ (token<(int)(sizeof(OC_INTERNAL_DCT_TOKEN_EXTRA_BITS)/ \
sizeof(*OC_INTERNAL_DCT_TOKEN_EXTRA_BITS)))
/*This token (OC_DCT_REPEAT_RUN3_TOKEN) requires more than 8 extra bits.*/
@@ -129,7 +129,7 @@ static const unsigned char OC_INTERNAL_DCT_TOKEN_EXTRA_BITS[15]={
is not yet available everywhere; this should be equivalent.*/
#define OC_DCT_EOB_FINISH (~(size_t)0>>1)
-/*The location of the (6) run legth bits in the code word.
+/*The location of the (6) run length bits in the code word.
These are placed at index 0 and given 8 bits (even though 6 would suffice)
because it may be faster to extract the lower byte on some platforms.*/
#define OC_DCT_CW_RLEN_SHIFT (0)
@@ -297,8 +297,6 @@ static const ogg_int32_t OC_DCT_CODE_WORD[92]={
static int oc_sb_run_unpack(oc_pack_buf *_opb){
- long bits;
- int ret;
/*Coding scheme:
Codeword Run Length
0 1
@@ -308,32 +306,26 @@ static int oc_sb_run_unpack(oc_pack_buf *_opb){
11110xxx 10-17
111110xxxx 18-33
111111xxxxxxxxxxxx 34-4129*/
- bits=oc_pack_read1(_opb);
- if(bits==0)return 1;
- bits=oc_pack_read(_opb,2);
- if((bits&2)==0)return 2+(int)bits;
- else if((bits&1)==0){
- bits=oc_pack_read1(_opb);
- return 4+(int)bits;
- }
- bits=oc_pack_read(_opb,3);
- if((bits&4)==0)return 6+(int)bits;
- else if((bits&2)==0){
- ret=10+((bits&1)<<2);
- bits=oc_pack_read(_opb,2);
- return ret+(int)bits;
- }
- else if((bits&1)==0){
- bits=oc_pack_read(_opb,4);
- return 18+(int)bits;
+ static const ogg_int16_t OC_SB_RUN_TREE[22]={
+ 4,
+ -(1<<8|1),-(1<<8|1),-(1<<8|1),-(1<<8|1),
+ -(1<<8|1),-(1<<8|1),-(1<<8|1),-(1<<8|1),
+ -(3<<8|2),-(3<<8|2),-(3<<8|3),-(3<<8|3),
+ -(4<<8|4),-(4<<8|5),-(4<<8|2<<4|6-6),17,
+ 2,
+ -(2<<8|2<<4|10-6),-(2<<8|2<<4|14-6),-(2<<8|4<<4|18-6),-(2<<8|12<<4|34-6)
+ };
+ int ret;
+ ret=oc_huff_token_decode(_opb,OC_SB_RUN_TREE);
+ if(ret>=0x10){
+ int offs;
+ offs=ret&0x1F;
+ ret=6+offs+(int)oc_pack_read(_opb,ret-offs>>4);
}
- bits=oc_pack_read(_opb,12);
- return 34+(int)bits;
+ return ret;
}
static int oc_block_run_unpack(oc_pack_buf *_opb){
- long bits;
- long bits2;
/*Coding scheme:
Codeword Run Length
0x 1-2
@@ -342,26 +334,37 @@ static int oc_block_run_unpack(oc_pack_buf *_opb){
1110xx 7-10
11110xx 11-14
11111xxxx 15-30*/
- bits=oc_pack_read(_opb,2);
- if((bits&2)==0)return 1+(int)bits;
- else if((bits&1)==0){
- bits=oc_pack_read1(_opb);
- return 3+(int)bits;
- }
- bits=oc_pack_read(_opb,2);
- if((bits&2)==0)return 5+(int)bits;
- else if((bits&1)==0){
- bits=oc_pack_read(_opb,2);
- return 7+(int)bits;
- }
- bits=oc_pack_read(_opb,3);
- if((bits&4)==0)return 11+bits;
- bits2=oc_pack_read(_opb,2);
- return 15+((bits&3)<<2)+bits2;
+ static const ogg_int16_t OC_BLOCK_RUN_TREE[61]={
+ 5,
+ -(2<<8|1),-(2<<8|1),-(2<<8|1),-(2<<8|1),
+ -(2<<8|1),-(2<<8|1),-(2<<8|1),-(2<<8|1),
+ -(2<<8|2),-(2<<8|2),-(2<<8|2),-(2<<8|2),
+ -(2<<8|2),-(2<<8|2),-(2<<8|2),-(2<<8|2),
+ -(3<<8|3),-(3<<8|3),-(3<<8|3),-(3<<8|3),
+ -(3<<8|4),-(3<<8|4),-(3<<8|4),-(3<<8|4),
+ -(4<<8|5),-(4<<8|5),-(4<<8|6),-(4<<8|6),
+ 33, 36, 39, 44,
+ 1,-(1<<8|7),-(1<<8|8),
+ 1,-(1<<8|9),-(1<<8|10),
+ 2,-(2<<8|11),-(2<<8|12),-(2<<8|13),-(2<<8|14),
+ 4,
+ -(4<<8|15),-(4<<8|16),-(4<<8|17),-(4<<8|18),
+ -(4<<8|19),-(4<<8|20),-(4<<8|21),-(4<<8|22),
+ -(4<<8|23),-(4<<8|24),-(4<<8|25),-(4<<8|26),
+ -(4<<8|27),-(4<<8|28),-(4<<8|29),-(4<<8|30)
+ };
+ return oc_huff_token_decode(_opb,OC_BLOCK_RUN_TREE);
}
+void oc_dec_accel_init_c(oc_dec_ctx *_dec){
+# if defined(OC_DEC_USE_VTABLE)
+ _dec->opt_vtable.dc_unpredict_mcu_plane=
+ oc_dec_dc_unpredict_mcu_plane_c;
+# endif
+}
+
static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
const th_setup_info *_setup){
int qti;
@@ -371,7 +374,7 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
ret=oc_state_init(&_dec->state,_info,3);
if(ret<0)return ret;
ret=oc_huff_trees_copy(_dec->huff_tables,
- (const oc_huff_node *const *)_setup->huff_tables);
+ (const ogg_int16_t *const *)_setup->huff_tables);
if(ret<0){
oc_state_clear(&_dec->state);
return ret;
@@ -406,6 +409,7 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
}
memcpy(_dec->state.loop_filter_limits,_setup->qinfo.loop_filter_limits,
sizeof(_dec->state.loop_filter_limits));
+ oc_dec_accel_init(_dec);
_dec->pp_level=OC_PP_LEVEL_DISABLED;
_dec->dc_qis=NULL;
_dec->variances=NULL;
@@ -413,7 +417,6 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
_dec->stripe_cb.ctx=NULL;
_dec->stripe_cb.stripe_decoded=NULL;
#if defined(HAVE_CAIRO)
- _dec->telemetry=0;
_dec->telemetry_bits=0;
_dec->telemetry_qi=0;
_dec->telemetry_mbmode=0;
@@ -504,6 +507,7 @@ static void oc_dec_mark_all_intra(oc_dec_ctx *_dec){
fragi=sb_maps[sbi][quadi][bi];
if(fragi>=0){
frags[fragi].coded=1;
+ frags[fragi].refi=OC_FRAME_SELF;
frags[fragi].mb_mode=OC_MODE_INTRA;
coded_fragis[ncoded_fragis++]=fragi;
}
@@ -595,6 +599,7 @@ static void oc_dec_coded_sb_flags_unpack(oc_dec_ctx *_dec){
static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
const oc_sb_map *sb_maps;
const oc_sb_flags *sb_flags;
+ signed char *mb_modes;
oc_fragment *frags;
unsigned nsbs;
unsigned sbi;
@@ -617,6 +622,7 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
else flag=0;
sb_maps=(const oc_sb_map *)_dec->state.sb_maps;
sb_flags=_dec->state.sb_flags;
+ mb_modes=_dec->state.mb_modes;
frags=_dec->state.frags;
sbi=nsbs=run_count=0;
coded_fragis=_dec->state.coded_fragis;
@@ -627,7 +633,9 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
for(;sbi<nsbs;sbi++){
int quadi;
for(quadi=0;quadi<4;quadi++)if(sb_flags[sbi].quad_valid&1<<quadi){
+ int quad_coded;
int bi;
+ quad_coded=0;
for(bi=0;bi<4;bi++){
ptrdiff_t fragi;
fragi=sb_maps[sbi][quadi][bi];
@@ -645,9 +653,13 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
}
if(coded)coded_fragis[ncoded_fragis++]=fragi;
else *(uncoded_fragis-++nuncoded_fragis)=fragi;
+ quad_coded|=coded;
frags[fragi].coded=coded;
+ frags[fragi].refi=OC_FRAME_NONE;
}
}
+ /*Remember if there's a coded luma block in this macro block.*/
+ if(!pli)mb_modes[sbi<<2|quadi]=quad_coded;
}
}
_dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis;
@@ -659,33 +671,39 @@ static void oc_dec_coded_flags_unpack(oc_dec_ctx *_dec){
}
+/*Coding scheme:
+ Codeword Mode Index
+ 0 0
+ 10 1
+ 110 2
+ 1110 3
+ 11110 4
+ 111110 5
+ 1111110 6
+ 1111111 7*/
+static const ogg_int16_t OC_VLC_MODE_TREE[26]={
+ 4,
+ -(1<<8|0),-(1<<8|0),-(1<<8|0),-(1<<8|0),
+ -(1<<8|0),-(1<<8|0),-(1<<8|0),-(1<<8|0),
+ -(2<<8|1),-(2<<8|1),-(2<<8|1),-(2<<8|1),
+ -(3<<8|2),-(3<<8|2),-(4<<8|3),17,
+ 3,
+ -(1<<8|4),-(1<<8|4),-(1<<8|4),-(1<<8|4),
+ -(2<<8|5),-(2<<8|5),-(3<<8|6),-(3<<8|7)
+};
-typedef int (*oc_mode_unpack_func)(oc_pack_buf *_opb);
-
-static int oc_vlc_mode_unpack(oc_pack_buf *_opb){
- long val;
- int i;
- for(i=0;i<7;i++){
- val=oc_pack_read1(_opb);
- if(!val)break;
- }
- return i;
-}
-
-static int oc_clc_mode_unpack(oc_pack_buf *_opb){
- long val;
- val=oc_pack_read(_opb,3);
- return (int)val;
-}
+static const ogg_int16_t OC_CLC_MODE_TREE[9]={
+ 3,
+ -(3<<8|0),-(3<<8|1),-(3<<8|2),-(3<<8|3),
+ -(3<<8|4),-(3<<8|5),-(3<<8|6),-(3<<8|7)
+};
/*Unpacks the list of macro block modes for INTER frames.*/
static void oc_dec_mb_modes_unpack(oc_dec_ctx *_dec){
- const oc_mb_map *mb_maps;
signed char *mb_modes;
- const oc_fragment *frags;
const unsigned char *alphabet;
unsigned char scheme0_alphabet[8];
- oc_mode_unpack_func mode_unpack;
+ const ogg_int16_t *mode_tree;
size_t nmbs;
size_t mbi;
long val;
@@ -707,65 +725,80 @@ static void oc_dec_mb_modes_unpack(oc_dec_ctx *_dec){
alphabet=scheme0_alphabet;
}
else alphabet=OC_MODE_ALPHABETS[mode_scheme-1];
- if(mode_scheme==7)mode_unpack=oc_clc_mode_unpack;
- else mode_unpack=oc_vlc_mode_unpack;
+ mode_tree=mode_scheme==7?OC_CLC_MODE_TREE:OC_VLC_MODE_TREE;
mb_modes=_dec->state.mb_modes;
- mb_maps=(const oc_mb_map *)_dec->state.mb_maps;
nmbs=_dec->state.nmbs;
- frags=_dec->state.frags;
for(mbi=0;mbi<nmbs;mbi++){
- if(mb_modes[mbi]!=OC_MODE_INVALID){
- int bi;
- /*Check for a coded luma block in this macro block.*/
- for(bi=0;bi<4&&!frags[mb_maps[mbi][0][bi]].coded;bi++);
- /*We found one, decode a mode.*/
- if(bi<4)mb_modes[mbi]=alphabet[(*mode_unpack)(&_dec->opb)];
- /*There were none: INTER_NOMV is forced.*/
- else mb_modes[mbi]=OC_MODE_INTER_NOMV;
+ if(mb_modes[mbi]>0){
+ /*We have a coded luma block; decode a mode.*/
+ mb_modes[mbi]=alphabet[oc_huff_token_decode(&_dec->opb,mode_tree)];
}
+ /*For other valid macro blocks, INTER_NOMV is forced, but we rely on the
+ fact that OC_MODE_INTER_NOMV is already 0.*/
}
}
-typedef int (*oc_mv_comp_unpack_func)(oc_pack_buf *_opb);
+static const ogg_int16_t OC_VLC_MV_COMP_TREE[101]={
+ 5,
+ -(3<<8|32+0),-(3<<8|32+0),-(3<<8|32+0),-(3<<8|32+0),
+ -(3<<8|32+1),-(3<<8|32+1),-(3<<8|32+1),-(3<<8|32+1),
+ -(3<<8|32-1),-(3<<8|32-1),-(3<<8|32-1),-(3<<8|32-1),
+ -(4<<8|32+2),-(4<<8|32+2),-(4<<8|32-2),-(4<<8|32-2),
+ -(4<<8|32+3),-(4<<8|32+3),-(4<<8|32-3),-(4<<8|32-3),
+ 33, 36, 39, 42,
+ 45, 50, 55, 60,
+ 65, 74, 83, 92,
+ 1,-(1<<8|32+4),-(1<<8|32-4),
+ 1,-(1<<8|32+5),-(1<<8|32-5),
+ 1,-(1<<8|32+6),-(1<<8|32-6),
+ 1,-(1<<8|32+7),-(1<<8|32-7),
+ 2,-(2<<8|32+8),-(2<<8|32-8),-(2<<8|32+9),-(2<<8|32-9),
+ 2,-(2<<8|32+10),-(2<<8|32-10),-(2<<8|32+11),-(2<<8|32-11),
+ 2,-(2<<8|32+12),-(2<<8|32-12),-(2<<8|32+13),-(2<<8|32-13),
+ 2,-(2<<8|32+14),-(2<<8|32-14),-(2<<8|32+15),-(2<<8|32-15),
+ 3,
+ -(3<<8|32+16),-(3<<8|32-16),-(3<<8|32+17),-(3<<8|32-17),
+ -(3<<8|32+18),-(3<<8|32-18),-(3<<8|32+19),-(3<<8|32-19),
+ 3,
+ -(3<<8|32+20),-(3<<8|32-20),-(3<<8|32+21),-(3<<8|32-21),
+ -(3<<8|32+22),-(3<<8|32-22),-(3<<8|32+23),-(3<<8|32-23),
+ 3,
+ -(3<<8|32+24),-(3<<8|32-24),-(3<<8|32+25),-(3<<8|32-25),
+ -(3<<8|32+26),-(3<<8|32-26),-(3<<8|32+27),-(3<<8|32-27),
+ 3,
+ -(3<<8|32+28),-(3<<8|32-28),-(3<<8|32+29),-(3<<8|32-29),
+ -(3<<8|32+30),-(3<<8|32-30),-(3<<8|32+31),-(3<<8|32-31)
+};
+
+static const ogg_int16_t OC_CLC_MV_COMP_TREE[65]={
+ 6,
+ -(6<<8|32 +0),-(6<<8|32 -0),-(6<<8|32 +1),-(6<<8|32 -1),
+ -(6<<8|32 +2),-(6<<8|32 -2),-(6<<8|32 +3),-(6<<8|32 -3),
+ -(6<<8|32 +4),-(6<<8|32 -4),-(6<<8|32 +5),-(6<<8|32 -5),
+ -(6<<8|32 +6),-(6<<8|32 -6),-(6<<8|32 +7),-(6<<8|32 -7),
+ -(6<<8|32 +8),-(6<<8|32 -8),-(6<<8|32 +9),-(6<<8|32 -9),
+ -(6<<8|32+10),-(6<<8|32-10),-(6<<8|32+11),-(6<<8|32-11),
+ -(6<<8|32+12),-(6<<8|32-12),-(6<<8|32+13),-(6<<8|32-13),
+ -(6<<8|32+14),-(6<<8|32-14),-(6<<8|32+15),-(6<<8|32-15),
+ -(6<<8|32+16),-(6<<8|32-16),-(6<<8|32+17),-(6<<8|32-17),
+ -(6<<8|32+18),-(6<<8|32-18),-(6<<8|32+19),-(6<<8|32-19),
+ -(6<<8|32+20),-(6<<8|32-20),-(6<<8|32+21),-(6<<8|32-21),
+ -(6<<8|32+22),-(6<<8|32-22),-(6<<8|32+23),-(6<<8|32-23),
+ -(6<<8|32+24),-(6<<8|32-24),-(6<<8|32+25),-(6<<8|32-25),
+ -(6<<8|32+26),-(6<<8|32-26),-(6<<8|32+27),-(6<<8|32-27),
+ -(6<<8|32+28),-(6<<8|32-28),-(6<<8|32+29),-(6<<8|32-29),
+ -(6<<8|32+30),-(6<<8|32-30),-(6<<8|32+31),-(6<<8|32-31)
+};
-static int oc_vlc_mv_comp_unpack(oc_pack_buf *_opb){
- long bits;
- int mask;
- int mv;
- bits=oc_pack_read(_opb,3);
- switch(bits){
- case 0:return 0;
- case 1:return 1;
- case 2:return -1;
- case 3:
- case 4:{
- mv=(int)(bits-1);
- bits=oc_pack_read1(_opb);
- }break;
- /*case 5:
- case 6:
- case 7:*/
- default:{
- mv=1<<bits-3;
- bits=oc_pack_read(_opb,bits-2);
- mv+=(int)(bits>>1);
- bits&=1;
- }break;
- }
- mask=-(int)bits;
- return mv+mask^mask;
-}
-static int oc_clc_mv_comp_unpack(oc_pack_buf *_opb){
- long bits;
- int mask;
- int mv;
- bits=oc_pack_read(_opb,6);
- mv=(int)bits>>1;
- mask=-((int)bits&1);
- return mv+mask^mask;
+static oc_mv oc_mv_unpack(oc_pack_buf *_opb,const ogg_int16_t *_tree){
+ int dx;
+ int dy;
+ dx=oc_huff_token_decode(_opb,_tree)-32;
+ dy=oc_huff_token_decode(_opb,_tree)-32;
+ return OC_MV(dx,dy);
}
/*Unpacks the list of motion vectors for INTER frames, and propagtes the macro
@@ -774,105 +807,93 @@ static void oc_dec_mv_unpack_and_frag_modes_fill(oc_dec_ctx *_dec){
const oc_mb_map *mb_maps;
const signed char *mb_modes;
oc_set_chroma_mvs_func set_chroma_mvs;
- oc_mv_comp_unpack_func mv_comp_unpack;
+ const ogg_int16_t *mv_comp_tree;
oc_fragment *frags;
oc_mv *frag_mvs;
const unsigned char *map_idxs;
int map_nidxs;
- oc_mv last_mv[2];
+ oc_mv last_mv;
+ oc_mv prior_mv;
oc_mv cbmvs[4];
size_t nmbs;
size_t mbi;
long val;
set_chroma_mvs=OC_SET_CHROMA_MVS_TABLE[_dec->state.info.pixel_fmt];
val=oc_pack_read1(&_dec->opb);
- mv_comp_unpack=val?oc_clc_mv_comp_unpack:oc_vlc_mv_comp_unpack;
+ mv_comp_tree=val?OC_CLC_MV_COMP_TREE:OC_VLC_MV_COMP_TREE;
map_idxs=OC_MB_MAP_IDXS[_dec->state.info.pixel_fmt];
map_nidxs=OC_MB_MAP_NIDXS[_dec->state.info.pixel_fmt];
- memset(last_mv,0,sizeof(last_mv));
+ prior_mv=last_mv=0;
frags=_dec->state.frags;
frag_mvs=_dec->state.frag_mvs;
mb_maps=(const oc_mb_map *)_dec->state.mb_maps;
mb_modes=_dec->state.mb_modes;
nmbs=_dec->state.nmbs;
for(mbi=0;mbi<nmbs;mbi++){
- int mb_mode;
+ int mb_mode;
mb_mode=mb_modes[mbi];
if(mb_mode!=OC_MODE_INVALID){
- oc_mv mbmv;
- ptrdiff_t fragi;
- int coded[13];
- int codedi;
- int ncoded;
- int mapi;
- int mapii;
- /*Search for at least one coded fragment.*/
- ncoded=mapii=0;
- do{
- mapi=map_idxs[mapii];
- fragi=mb_maps[mbi][mapi>>2][mapi&3];
- if(frags[fragi].coded)coded[ncoded++]=mapi;
- }
- while(++mapii<map_nidxs);
- if(ncoded<=0)continue;
- switch(mb_mode){
- case OC_MODE_INTER_MV_FOUR:{
- oc_mv lbmvs[4];
- int bi;
- /*Mark the tail of the list, so we don't accidentally go past it.*/
- coded[ncoded]=-1;
- for(bi=codedi=0;bi<4;bi++){
- if(coded[codedi]==bi){
- codedi++;
- fragi=mb_maps[mbi][0][bi];
- frags[fragi].mb_mode=mb_mode;
- lbmvs[bi][0]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- lbmvs[bi][1]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- memcpy(frag_mvs[fragi],lbmvs[bi],sizeof(lbmvs[bi]));
- }
- else lbmvs[bi][0]=lbmvs[bi][1]=0;
- }
- if(codedi>0){
- memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1]));
- memcpy(last_mv[0],lbmvs[coded[codedi-1]],sizeof(last_mv[0]));
+ oc_mv mbmv;
+ ptrdiff_t fragi;
+ int mapi;
+ int mapii;
+ int refi;
+ if(mb_mode==OC_MODE_INTER_MV_FOUR){
+ oc_mv lbmvs[4];
+ int bi;
+ prior_mv=last_mv;
+ for(bi=0;bi<4;bi++){
+ fragi=mb_maps[mbi][0][bi];
+ if(frags[fragi].coded){
+ frags[fragi].refi=OC_FRAME_PREV;
+ frags[fragi].mb_mode=OC_MODE_INTER_MV_FOUR;
+ lbmvs[bi]=last_mv=oc_mv_unpack(&_dec->opb,mv_comp_tree);
+ frag_mvs[fragi]=lbmvs[bi];
}
- if(codedi<ncoded){
- (*set_chroma_mvs)(cbmvs,(const oc_mv *)lbmvs);
- for(;codedi<ncoded;codedi++){
- mapi=coded[codedi];
- bi=mapi&3;
- fragi=mb_maps[mbi][mapi>>2][bi];
- frags[fragi].mb_mode=mb_mode;
- memcpy(frag_mvs[fragi],cbmvs[bi],sizeof(cbmvs[bi]));
- }
+ else lbmvs[bi]=0;
+ }
+ (*set_chroma_mvs)(cbmvs,lbmvs);
+ for(mapii=4;mapii<map_nidxs;mapii++){
+ mapi=map_idxs[mapii];
+ bi=mapi&3;
+ fragi=mb_maps[mbi][mapi>>2][bi];
+ if(frags[fragi].coded){
+ frags[fragi].refi=OC_FRAME_PREV;
+ frags[fragi].mb_mode=OC_MODE_INTER_MV_FOUR;
+ frag_mvs[fragi]=cbmvs[bi];
}
- }break;
- case OC_MODE_INTER_MV:{
- memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1]));
- mbmv[0]=last_mv[0][0]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- mbmv[1]=last_mv[0][1]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- }break;
- case OC_MODE_INTER_MV_LAST:memcpy(mbmv,last_mv[0],sizeof(mbmv));break;
- case OC_MODE_INTER_MV_LAST2:{
- memcpy(mbmv,last_mv[1],sizeof(mbmv));
- memcpy(last_mv[1],last_mv[0],sizeof(last_mv[1]));
- memcpy(last_mv[0],mbmv,sizeof(last_mv[0]));
- }break;
- case OC_MODE_GOLDEN_MV:{
- mbmv[0]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- mbmv[1]=(signed char)(*mv_comp_unpack)(&_dec->opb);
- }break;
- default:memset(mbmv,0,sizeof(mbmv));break;
+ }
}
- /*4MV mode fills in the fragments itself.
- For all other modes we can use this common code.*/
- if(mb_mode!=OC_MODE_INTER_MV_FOUR){
- for(codedi=0;codedi<ncoded;codedi++){
- mapi=coded[codedi];
+ else{
+ switch(mb_mode){
+ case OC_MODE_INTER_MV:{
+ prior_mv=last_mv;
+ last_mv=mbmv=oc_mv_unpack(&_dec->opb,mv_comp_tree);
+ }break;
+ case OC_MODE_INTER_MV_LAST:mbmv=last_mv;break;
+ case OC_MODE_INTER_MV_LAST2:{
+ mbmv=prior_mv;
+ prior_mv=last_mv;
+ last_mv=mbmv;
+ }break;
+ case OC_MODE_GOLDEN_MV:{
+ mbmv=oc_mv_unpack(&_dec->opb,mv_comp_tree);
+ }break;
+ default:mbmv=0;break;
+ }
+ /*Fill in the MVs for the fragments.*/
+ refi=OC_FRAME_FOR_MODE(mb_mode);
+ mapii=0;
+ do{
+ mapi=map_idxs[mapii];
fragi=mb_maps[mbi][mapi>>2][mapi&3];
- frags[fragi].mb_mode=mb_mode;
- memcpy(frag_mvs[fragi],mbmv,sizeof(mbmv));
+ if(frags[fragi].coded){
+ frags[fragi].refi=refi;
+ frags[fragi].mb_mode=mb_mode;
+ frag_mvs[fragi]=mbmv;
+ }
}
+ while(++mapii<map_nidxs);
}
}
}
@@ -1181,6 +1202,9 @@ static void oc_dec_residual_tokens_unpack(oc_dec_ctx *_dec){
static int oc_dec_postprocess_init(oc_dec_ctx *_dec){
+ /*musl libc malloc()/realloc() calls might use floating point, so make sure
+ we've cleared the MMX state for them.*/
+ oc_restore_fpu(&_dec->state);
/*pp_level 0: disabled; free any memory used and return*/
if(_dec->pp_level<=OC_PP_LEVEL_DISABLED){
if(_dec->dc_qis!=NULL){
@@ -1301,34 +1325,16 @@ static int oc_dec_postprocess_init(oc_dec_ctx *_dec){
}
-
-typedef struct{
- int bounding_values[256];
- ptrdiff_t ti[3][64];
- ptrdiff_t eob_runs[3][64];
- const ptrdiff_t *coded_fragis[3];
- const ptrdiff_t *uncoded_fragis[3];
- ptrdiff_t ncoded_fragis[3];
- ptrdiff_t nuncoded_fragis[3];
- const ogg_uint16_t *dequant[3][3][2];
- int fragy0[3];
- int fragy_end[3];
- int pred_last[3][3];
- int mcu_nvfrags;
- int loop_filter;
- int pp_level;
-}oc_dec_pipeline_state;
-
-
-
/*Initialize the main decoding pipeline.*/
static void oc_dec_pipeline_init(oc_dec_ctx *_dec,
oc_dec_pipeline_state *_pipe){
const ptrdiff_t *coded_fragis;
const ptrdiff_t *uncoded_fragis;
+ int flimit;
int pli;
int qii;
int qti;
+ int zzi;
/*If chroma is sub-sampled in the vertical direction, we have to decode two
super block rows of Y' for each super block row of Cb and Cr.*/
_pipe->mcu_nvfrags=4<<!(_dec->state.info.pixel_fmt&2);
@@ -1360,8 +1366,9 @@ static void oc_dec_pipeline_init(oc_dec_ctx *_dec,
/*Set the previous DC predictor to 0 for all color planes and frame types.*/
memset(_pipe->pred_last,0,sizeof(_pipe->pred_last));
/*Initialize the bounding value array for the loop filter.*/
- _pipe->loop_filter=!oc_state_loop_filter_init(&_dec->state,
- _pipe->bounding_values);
+ flimit=_dec->state.loop_filter_limits[_dec->state.qis[0]];
+ _pipe->loop_filter=flimit!=0;
+ if(flimit!=0)oc_loop_filter_init(&_dec->state,_pipe->bounding_values,flimit);
/*Initialize any buffers needed for post-processing.
We also save the current post-processing level, to guard against the user
changing it from a callback.*/
@@ -1374,13 +1381,15 @@ static void oc_dec_pipeline_init(oc_dec_ctx *_dec,
_dec->state.ref_frame_bufs[_dec->state.ref_frame_idx[OC_FRAME_SELF]],
sizeof(_dec->pp_frame_buf[0])*3);
}
+ /*Clear down the DCT coefficient buffer for the first block.*/
+ for(zzi=0;zzi<64;zzi++)_pipe->dct_coeffs[zzi]=0;
}
/*Undo the DC prediction in a single plane of an MCU (one or two super block
rows).
As a side effect, the number of coded and uncoded fragments in this plane of
the MCU is also computed.*/
-static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
+void oc_dec_dc_unpredict_mcu_plane_c(oc_dec_ctx *_dec,
oc_dec_pipeline_state *_pipe,int _pli){
const oc_fragment_plane *fplane;
oc_fragment *frags;
@@ -1408,9 +1417,9 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
predictor for the same reference frame.*/
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
if(frags[fragi].coded){
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
- pred_last[ref]=frags[fragi].dc+=pred_last[ref];
+ int refi;
+ refi=frags[fragi].refi;
+ pred_last[refi]=frags[fragi].dc+=pred_last[refi];
ncoded_fragis++;
}
}
@@ -1423,27 +1432,24 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
u_frags=frags-nhfrags;
l_ref=-1;
ul_ref=-1;
- u_ref=u_frags[fragi].coded?OC_FRAME_FOR_MODE(u_frags[fragi].mb_mode):-1;
+ u_ref=u_frags[fragi].refi;
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
int ur_ref;
if(fragx+1>=nhfrags)ur_ref=-1;
- else{
- ur_ref=u_frags[fragi+1].coded?
- OC_FRAME_FOR_MODE(u_frags[fragi+1].mb_mode):-1;
- }
+ else ur_ref=u_frags[fragi+1].refi;
if(frags[fragi].coded){
int pred;
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
+ int refi;
+ refi=frags[fragi].refi;
/*We break out a separate case based on which of our neighbors use
the same reference frames.
This is somewhat faster than trying to make a generic case which
handles all of them, since it reduces lots of poorly predicted
jumps to one switch statement, and also lets a number of the
multiplications be optimized out by strength reduction.*/
- switch((l_ref==ref)|(ul_ref==ref)<<1|
- (u_ref==ref)<<2|(ur_ref==ref)<<3){
- default:pred=pred_last[ref];break;
+ switch((l_ref==refi)|(ul_ref==refi)<<1|
+ (u_ref==refi)<<2|(ur_ref==refi)<<3){
+ default:pred=pred_last[refi];break;
case 1:
case 3:pred=frags[fragi-1].dc;break;
case 2:pred=u_frags[fragi-1].dc;break;
@@ -1455,6 +1461,7 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
case 9:
case 11:
case 13:{
+ /*The TI compiler mis-compiles this line.*/
pred=(75*frags[fragi-1].dc+53*u_frags[fragi+1].dc)/128;
}break;
case 10:pred=(u_frags[fragi-1].dc+u_frags[fragi+1].dc)/2;break;
@@ -1476,9 +1483,9 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
else if(abs(pred-p1)>128)pred=p1;
}break;
}
- pred_last[ref]=frags[fragi].dc+=pred;
+ pred_last[refi]=frags[fragi].dc+=pred;
ncoded_fragis++;
- l_ref=ref;
+ l_ref=refi;
}
else l_ref=-1;
ul_ref=u_ref;
@@ -1495,7 +1502,7 @@ static void oc_dec_dc_unpredict_mcu_plane(oc_dec_ctx *_dec,
/*Reconstructs all coded fragments in a single MCU (one or two super block
rows).
This requires that each coded fragment have a proper macro block mode and
- motion vector (if not in INTRA mode), and have it's DC value decoded, with
+ motion vector (if not in INTRA mode), and have its DC value decoded, with
the DC prediction process reversed, and the number of coded and uncoded
fragments in this plane of the MCU be counted.
The token lists for each color plane and coefficient should also be filled
@@ -1522,16 +1529,11 @@ static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec,
eob_runs=_pipe->eob_runs[_pli];
for(qti=0;qti<2;qti++)dc_quant[qti]=_pipe->dequant[_pli][0][qti][0];
for(fragii=0;fragii<ncoded_fragis;fragii++){
- /*This array is made one element larger because the zig-zag index array
- uses the final element as a dumping ground for out-of-range indices
- to protect us from buffer overflow.*/
- OC_ALIGN8(ogg_int16_t dct_coeffs[65]);
const ogg_uint16_t *ac_quant;
ptrdiff_t fragi;
int last_zzi;
int zzi;
fragi=coded_fragis[fragii];
- for(zzi=0;zzi<64;zzi++)dct_coeffs[zzi]=0;
qti=frags[fragi].mb_mode!=OC_MODE_INTRA;
ac_quant=_pipe->dequant[_pli][frags[fragi].qii][qti];
/*Decode the AC coefficients.*/
@@ -1568,18 +1570,19 @@ static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec,
eob_runs[zzi]=eob;
ti[zzi]=lti;
zzi+=rlen;
- dct_coeffs[dct_fzig_zag[zzi]]=(ogg_int16_t)(coeff*(int)ac_quant[zzi]);
+ _pipe->dct_coeffs[dct_fzig_zag[zzi]]=
+ (ogg_int16_t)(coeff*(int)ac_quant[zzi]);
zzi+=!eob;
}
}
/*TODO: zzi should be exactly 64 here.
If it's not, we should report some kind of warning.*/
zzi=OC_MINI(zzi,64);
- dct_coeffs[0]=(ogg_int16_t)frags[fragi].dc;
+ _pipe->dct_coeffs[0]=(ogg_int16_t)frags[fragi].dc;
/*last_zzi is always initialized.
If your compiler thinks otherwise, it is dumb.*/
oc_state_frag_recon(&_dec->state,fragi,_pli,
- dct_coeffs,last_zzi,dc_quant[qti]);
+ _pipe->dct_coeffs,last_zzi,dc_quant[qti]);
}
_pipe->coded_fragis[_pli]+=ncoded_fragis;
/*Right now the reconstructed MCU has only the coded blocks in it.*/
@@ -1593,9 +1596,14 @@ static void oc_dec_frags_recon_mcu_plane(oc_dec_ctx *_dec,
code, and the hard case (high bitrate, high resolution) is handled
correctly.*/
/*Copy the uncoded blocks from the previous reference frame.*/
- _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
- oc_state_frag_copy_list(&_dec->state,_pipe->uncoded_fragis[_pli],
- _pipe->nuncoded_fragis[_pli],OC_FRAME_SELF,OC_FRAME_PREV,_pli);
+ if(_pipe->nuncoded_fragis[_pli]>0){
+ _pipe->uncoded_fragis[_pli]-=_pipe->nuncoded_fragis[_pli];
+ oc_frag_copy_list(&_dec->state,
+ _dec->state.ref_frame_data[OC_FRAME_SELF],
+ _dec->state.ref_frame_data[OC_FRAME_PREV],
+ _dec->state.ref_ystride[_pli],_pipe->uncoded_fragis[_pli],
+ _pipe->nuncoded_fragis[_pli],_dec->state.frag_buf_offs);
+ }
}
/*Filter a horizontal block edge.*/
@@ -1953,9 +1961,9 @@ static void oc_dec_dering_frag_rows(oc_dec_ctx *_dec,th_img_plane *_img,
th_dec_ctx *th_decode_alloc(const th_info *_info,const th_setup_info *_setup){
oc_dec_ctx *dec;
if(_info==NULL||_setup==NULL)return NULL;
- dec=_ogg_malloc(sizeof(*dec));
+ dec=oc_aligned_malloc(sizeof(*dec),16);
if(dec==NULL||oc_dec_init(dec,_info,_setup)<0){
- _ogg_free(dec);
+ oc_aligned_free(dec);
return NULL;
}
dec->state.curframe_num=0;
@@ -1965,7 +1973,7 @@ th_dec_ctx *th_decode_alloc(const th_info *_info,const th_setup_info *_setup){
void th_decode_free(th_dec_ctx *_dec){
if(_dec!=NULL){
oc_dec_clear(_dec);
- _ogg_free(_dec);
+ oc_aligned_free(_dec);
}
}
@@ -2013,28 +2021,24 @@ int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
case TH_DECCTL_SET_TELEMETRY_MBMODE:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_mbmode=*(int *)_buf;
return 0;
}break;
case TH_DECCTL_SET_TELEMETRY_MV:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_mv=*(int *)_buf;
return 0;
}break;
case TH_DECCTL_SET_TELEMETRY_QI:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_qi=*(int *)_buf;
return 0;
}break;
case TH_DECCTL_SET_TELEMETRY_BITS:{
if(_dec==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(int))return TH_EINVAL;
- _dec->telemetry=1;
_dec->telemetry_bits=*(int *)_buf;
return 0;
}break;
@@ -2047,63 +2051,751 @@ int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
buffers (i.e., decoding did not start on a key frame).
We initialize them to a solid gray here.*/
static void oc_dec_init_dummy_frame(th_dec_ctx *_dec){
- th_info *info;
- size_t yplane_sz;
- size_t cplane_sz;
- int yhstride;
- int yheight;
- int chstride;
- int cheight;
+ th_info *info;
+ size_t yplane_sz;
+ size_t cplane_sz;
+ ptrdiff_t yoffset;
+ int yhstride;
+ int yheight;
+ int chstride;
+ int cheight;
_dec->state.ref_frame_idx[OC_FRAME_GOLD]=0;
_dec->state.ref_frame_idx[OC_FRAME_PREV]=0;
- _dec->state.ref_frame_idx[OC_FRAME_SELF]=1;
+ _dec->state.ref_frame_idx[OC_FRAME_SELF]=0;
+ _dec->state.ref_frame_data[OC_FRAME_GOLD]=
+ _dec->state.ref_frame_data[OC_FRAME_PREV]=
+ _dec->state.ref_frame_data[OC_FRAME_SELF]=
+ _dec->state.ref_frame_bufs[0][0].data;
+ memcpy(_dec->pp_frame_buf,_dec->state.ref_frame_bufs[0],
+ sizeof(_dec->pp_frame_buf[0])*3);
info=&_dec->state.info;
- yhstride=info->frame_width+2*OC_UMV_PADDING;
+ yhstride=abs(_dec->state.ref_ystride[0]);
yheight=info->frame_height+2*OC_UMV_PADDING;
- chstride=yhstride>>!(info->pixel_fmt&1);
+ chstride=abs(_dec->state.ref_ystride[1]);
cheight=yheight>>!(info->pixel_fmt&2);
- yplane_sz=yhstride*(size_t)yheight;
+ yplane_sz=yhstride*(size_t)yheight+16;
cplane_sz=chstride*(size_t)cheight;
- memset(_dec->state.ref_frame_data[0],0x80,yplane_sz+2*cplane_sz);
+ yoffset=yhstride*(ptrdiff_t)(yheight-OC_UMV_PADDING-1)+OC_UMV_PADDING;
+ memset(_dec->state.ref_frame_data[0]-yoffset,0x80,yplane_sz+2*cplane_sz);
+}
+
+#if defined(HAVE_CAIRO)
+static void oc_render_telemetry(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr,
+ int _telemetry){
+ /*Stuff the plane into cairo.*/
+ cairo_surface_t *cs;
+ unsigned char *data;
+ unsigned char *y_row;
+ unsigned char *u_row;
+ unsigned char *v_row;
+ unsigned char *rgb_row;
+ int cstride;
+ int w;
+ int h;
+ int x;
+ int y;
+ int hdec;
+ int vdec;
+ w=_ycbcr[0].width;
+ h=_ycbcr[0].height;
+ hdec=!(_dec->state.info.pixel_fmt&1);
+ vdec=!(_dec->state.info.pixel_fmt&2);
+ /*Lazy data buffer init.
+ We could try to re-use the post-processing buffer, which would save
+ memory, but complicate the allocation logic there.
+ I don't think anyone cares about memory usage when using telemetry; it is
+ not meant for embedded devices.*/
+ if(_dec->telemetry_frame_data==NULL){
+ _dec->telemetry_frame_data=_ogg_malloc(
+ (w*h+2*(w>>hdec)*(h>>vdec))*sizeof(*_dec->telemetry_frame_data));
+ if(_dec->telemetry_frame_data==NULL)return;
+ }
+ cs=cairo_image_surface_create(CAIRO_FORMAT_RGB24,w,h);
+ /*Sadly, no YUV support in Cairo (yet); convert into the RGB buffer.*/
+ data=cairo_image_surface_get_data(cs);
+ if(data==NULL){
+ cairo_surface_destroy(cs);
+ return;
+ }
+ cstride=cairo_image_surface_get_stride(cs);
+ y_row=_ycbcr[0].data;
+ u_row=_ycbcr[1].data;
+ v_row=_ycbcr[2].data;
+ rgb_row=data;
+ for(y=0;y<h;y++){
+ for(x=0;x<w;x++){
+ int r;
+ int g;
+ int b;
+ r=(1904000*y_row[x]+2609823*v_row[x>>hdec]-363703744)/1635200;
+ g=(3827562*y_row[x]-1287801*u_row[x>>hdec]
+ -2672387*v_row[x>>hdec]+447306710)/3287200;
+ b=(952000*y_row[x]+1649289*u_row[x>>hdec]-225932192)/817600;
+ rgb_row[4*x+0]=OC_CLAMP255(b);
+ rgb_row[4*x+1]=OC_CLAMP255(g);
+ rgb_row[4*x+2]=OC_CLAMP255(r);
+ }
+ y_row+=_ycbcr[0].stride;
+ u_row+=_ycbcr[1].stride&-((y&1)|!vdec);
+ v_row+=_ycbcr[2].stride&-((y&1)|!vdec);
+ rgb_row+=cstride;
+ }
+ /*Draw coded identifier for each macroblock (stored in Hilbert order).*/
+ {
+ cairo_t *c;
+ const oc_fragment *frags;
+ oc_mv *frag_mvs;
+ const signed char *mb_modes;
+ oc_mb_map *mb_maps;
+ size_t nmbs;
+ size_t mbi;
+ int row2;
+ int col2;
+ int qim[3]={0,0,0};
+ if(_dec->state.nqis==2){
+ int bqi;
+ bqi=_dec->state.qis[0];
+ if(_dec->state.qis[1]>bqi)qim[1]=1;
+ if(_dec->state.qis[1]<bqi)qim[1]=-1;
+ }
+ if(_dec->state.nqis==3){
+ int bqi;
+ int cqi;
+ int dqi;
+ bqi=_dec->state.qis[0];
+ cqi=_dec->state.qis[1];
+ dqi=_dec->state.qis[2];
+ if(cqi>bqi&&dqi>bqi){
+ if(dqi>cqi){
+ qim[1]=1;
+ qim[2]=2;
+ }
+ else{
+ qim[1]=2;
+ qim[2]=1;
+ }
+ }
+ else if(cqi<bqi&&dqi<bqi){
+ if(dqi<cqi){
+ qim[1]=-1;
+ qim[2]=-2;
+ }
+ else{
+ qim[1]=-2;
+ qim[2]=-1;
+ }
+ }
+ else{
+ if(cqi<bqi)qim[1]=-1;
+ else qim[1]=1;
+ if(dqi<bqi)qim[2]=-1;
+ else qim[2]=1;
+ }
+ }
+ c=cairo_create(cs);
+ frags=_dec->state.frags;
+ frag_mvs=_dec->state.frag_mvs;
+ mb_modes=_dec->state.mb_modes;
+ mb_maps=_dec->state.mb_maps;
+ nmbs=_dec->state.nmbs;
+ row2=0;
+ col2=0;
+ for(mbi=0;mbi<nmbs;mbi++){
+ float x;
+ float y;
+ int bi;
+ y=h-(row2+((col2+1>>1)&1))*16-16;
+ x=(col2>>1)*16;
+ cairo_set_line_width(c,1.);
+ /*Keyframe (all intra) red box.*/
+ if(_dec->state.frame_type==OC_INTRA_FRAME){
+ if(_dec->telemetry_mbmode&0x02){
+ cairo_set_source_rgba(c,1.,0,0,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,0,0,.25);
+ cairo_fill(c);
+ }
+ }
+ else{
+ ptrdiff_t fragi;
+ int frag_mvx;
+ int frag_mvy;
+ for(bi=0;bi<4;bi++){
+ fragi=mb_maps[mbi][0][bi];
+ if(fragi>=0&&frags[fragi].coded){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvy=OC_MV_Y(frag_mvs[fragi]);
+ break;
+ }
+ }
+ if(bi<4){
+ switch(mb_modes[mbi]){
+ case OC_MODE_INTRA:{
+ if(_dec->telemetry_mbmode&0x02){
+ cairo_set_source_rgba(c,1.,0,0,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,0,0,.25);
+ cairo_fill(c);
+ }
+ }break;
+ case OC_MODE_INTER_NOMV:{
+ if(_dec->telemetry_mbmode&0x01){
+ cairo_set_source_rgba(c,0,0,1.,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,0,0,1.,.25);
+ cairo_fill(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV:{
+ if(_dec->telemetry_mbmode&0x04){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x04){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV_LAST:{
+ if(_dec->telemetry_mbmode&0x08){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_move_to(c,x+13.5,y+2.5);
+ cairo_line_to(c,x+2.5,y+8);
+ cairo_line_to(c,x+13.5,y+13.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x08){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV_LAST2:{
+ if(_dec->telemetry_mbmode&0x10){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_move_to(c,x+8,y+2.5);
+ cairo_line_to(c,x+2.5,y+8);
+ cairo_line_to(c,x+8,y+13.5);
+ cairo_move_to(c,x+13.5,y+2.5);
+ cairo_line_to(c,x+8,y+8);
+ cairo_line_to(c,x+13.5,y+13.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x10){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_GOLDEN_NOMV:{
+ if(_dec->telemetry_mbmode&0x20){
+ cairo_set_source_rgba(c,1.,1.,0,.5);
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,1.,0,.25);
+ cairo_fill(c);
+ }
+ }break;
+ case OC_MODE_GOLDEN_MV:{
+ if(_dec->telemetry_mbmode&0x40){
+ cairo_rectangle(c,x+2.5,y+2.5,11,11);
+ cairo_set_source_rgba(c,1.,1.,0,.5);
+ cairo_stroke(c);
+ }
+ if(_dec->telemetry_mv&0x40){
+ cairo_move_to(c,x+8+frag_mvx,y+8-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+8+frag_mvx*.66,y+8-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+8+frag_mvx*.33,y+8-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+8,y+8);
+ cairo_stroke(c);
+ }
+ }break;
+ case OC_MODE_INTER_MV_FOUR:{
+ if(_dec->telemetry_mbmode&0x80){
+ cairo_rectangle(c,x+2.5,y+2.5,4,4);
+ cairo_rectangle(c,x+9.5,y+2.5,4,4);
+ cairo_rectangle(c,x+2.5,y+9.5,4,4);
+ cairo_rectangle(c,x+9.5,y+9.5,4,4);
+ cairo_set_source_rgba(c,0,1.,0,.5);
+ cairo_stroke(c);
+ }
+ /*4mv is odd, coded in raster order.*/
+ fragi=mb_maps[mbi][0][0];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+4+frag_mvx,y+12-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+4+frag_mvx*.66,y+12-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+4+frag_mvx*.33,y+12-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+4,y+12);
+ cairo_stroke(c);
+ }
+ fragi=mb_maps[mbi][0][1];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+12+frag_mvx,y+12-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+12+frag_mvx*.66,y+12-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+12+frag_mvx*.33,y+12-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+12,y+12);
+ cairo_stroke(c);
+ }
+ fragi=mb_maps[mbi][0][2];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+4+frag_mvx,y+4-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+4+frag_mvx*.66,y+4-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+4+frag_mvx*.33,y+4-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+4,y+4);
+ cairo_stroke(c);
+ }
+ fragi=mb_maps[mbi][0][3];
+ if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
+ frag_mvx=OC_MV_X(frag_mvs[fragi]);
+ frag_mvx=OC_MV_Y(frag_mvs[fragi]);
+ cairo_move_to(c,x+12+frag_mvx,y+4-frag_mvy);
+ cairo_set_source_rgba(c,1.,1.,1.,.9);
+ cairo_set_line_width(c,3.);
+ cairo_line_to(c,x+12+frag_mvx*.66,y+4-frag_mvy*.66);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,2.);
+ cairo_line_to(c,x+12+frag_mvx*.33,y+4-frag_mvy*.33);
+ cairo_stroke_preserve(c);
+ cairo_set_line_width(c,1.);
+ cairo_line_to(c,x+12,y+4);
+ cairo_stroke(c);
+ }
+ }break;
+ }
+ }
+ }
+ /*qii illustration.*/
+ if(_dec->telemetry_qi&0x2){
+ cairo_set_line_cap(c,CAIRO_LINE_CAP_SQUARE);
+ for(bi=0;bi<4;bi++){
+ ptrdiff_t fragi;
+ int qiv;
+ int xp;
+ int yp;
+ xp=x+(bi&1)*8;
+ yp=y+8-(bi&2)*4;
+ fragi=mb_maps[mbi][0][bi];
+ if(fragi>=0&&frags[fragi].coded){
+ qiv=qim[frags[fragi].qii];
+ cairo_set_line_width(c,3.);
+ cairo_set_source_rgba(c,0.,0.,0.,.5);
+ switch(qiv){
+ /*Double plus:*/
+ case 2:{
+ if((bi&1)^((bi&2)>>1)){
+ cairo_move_to(c,xp+2.5,yp+1.5);
+ cairo_line_to(c,xp+2.5,yp+3.5);
+ cairo_move_to(c,xp+1.5,yp+2.5);
+ cairo_line_to(c,xp+3.5,yp+2.5);
+ cairo_move_to(c,xp+5.5,yp+4.5);
+ cairo_line_to(c,xp+5.5,yp+6.5);
+ cairo_move_to(c,xp+4.5,yp+5.5);
+ cairo_line_to(c,xp+6.5,yp+5.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,0.,1.,1.,1.);
+ }
+ else{
+ cairo_move_to(c,xp+5.5,yp+1.5);
+ cairo_line_to(c,xp+5.5,yp+3.5);
+ cairo_move_to(c,xp+4.5,yp+2.5);
+ cairo_line_to(c,xp+6.5,yp+2.5);
+ cairo_move_to(c,xp+2.5,yp+4.5);
+ cairo_line_to(c,xp+2.5,yp+6.5);
+ cairo_move_to(c,xp+1.5,yp+5.5);
+ cairo_line_to(c,xp+3.5,yp+5.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,0.,1.,1.,1.);
+ }
+ }break;
+ /*Double minus:*/
+ case -2:{
+ cairo_move_to(c,xp+2.5,yp+2.5);
+ cairo_line_to(c,xp+5.5,yp+2.5);
+ cairo_move_to(c,xp+2.5,yp+5.5);
+ cairo_line_to(c,xp+5.5,yp+5.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,1.,1.,1.);
+ }break;
+ /*Plus:*/
+ case 1:{
+ if((bi&2)==0)yp-=2;
+ if((bi&1)==0)xp-=2;
+ cairo_move_to(c,xp+4.5,yp+2.5);
+ cairo_line_to(c,xp+4.5,yp+6.5);
+ cairo_move_to(c,xp+2.5,yp+4.5);
+ cairo_line_to(c,xp+6.5,yp+4.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,.1,1.,.3,1.);
+ break;
+ }
+ /*Fall through.*/
+ /*Minus:*/
+ case -1:{
+ cairo_move_to(c,xp+2.5,yp+4.5);
+ cairo_line_to(c,xp+6.5,yp+4.5);
+ cairo_stroke_preserve(c);
+ cairo_set_source_rgba(c,1.,.3,.1,1.);
+ }break;
+ default:continue;
+ }
+ cairo_set_line_width(c,1.);
+ cairo_stroke(c);
+ }
+ }
+ }
+ col2++;
+ if((col2>>1)>=_dec->state.nhmbs){
+ col2=0;
+ row2+=2;
+ }
+ }
+ /*Bit usage indicator[s]:*/
+ if(_dec->telemetry_bits){
+ int widths[6];
+ int fpsn;
+ int fpsd;
+ int mult;
+ int fullw;
+ int padw;
+ int i;
+ fpsn=_dec->state.info.fps_numerator;
+ fpsd=_dec->state.info.fps_denominator;
+ mult=(_dec->telemetry_bits>=0xFF?1:_dec->telemetry_bits);
+ fullw=250.f*h*fpsd*mult/fpsn;
+ padw=w-24;
+ /*Header and coded block bits.*/
+ if(_dec->telemetry_frame_bytes<0||
+ _dec->telemetry_frame_bytes==OC_LOTS_OF_BITS){
+ _dec->telemetry_frame_bytes=0;
+ }
+ if(_dec->telemetry_coding_bytes<0||
+ _dec->telemetry_coding_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_coding_bytes=0;
+ }
+ if(_dec->telemetry_mode_bytes<0||
+ _dec->telemetry_mode_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_mode_bytes=0;
+ }
+ if(_dec->telemetry_mv_bytes<0||
+ _dec->telemetry_mv_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_mv_bytes=0;
+ }
+ if(_dec->telemetry_qi_bytes<0||
+ _dec->telemetry_qi_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_qi_bytes=0;
+ }
+ if(_dec->telemetry_dc_bytes<0||
+ _dec->telemetry_dc_bytes>_dec->telemetry_frame_bytes){
+ _dec->telemetry_dc_bytes=0;
+ }
+ widths[0]=padw*
+ (_dec->telemetry_frame_bytes-_dec->telemetry_coding_bytes)/fullw;
+ widths[1]=padw*
+ (_dec->telemetry_coding_bytes-_dec->telemetry_mode_bytes)/fullw;
+ widths[2]=padw*
+ (_dec->telemetry_mode_bytes-_dec->telemetry_mv_bytes)/fullw;
+ widths[3]=padw*(_dec->telemetry_mv_bytes-_dec->telemetry_qi_bytes)/fullw;
+ widths[4]=padw*(_dec->telemetry_qi_bytes-_dec->telemetry_dc_bytes)/fullw;
+ widths[5]=padw*(_dec->telemetry_dc_bytes)/fullw;
+ for(i=0;i<6;i++)if(widths[i]>w)widths[i]=w;
+ cairo_set_source_rgba(c,.0,.0,.0,.6);
+ cairo_rectangle(c,10,h-33,widths[0]+1,5);
+ cairo_rectangle(c,10,h-29,widths[1]+1,5);
+ cairo_rectangle(c,10,h-25,widths[2]+1,5);
+ cairo_rectangle(c,10,h-21,widths[3]+1,5);
+ cairo_rectangle(c,10,h-17,widths[4]+1,5);
+ cairo_rectangle(c,10,h-13,widths[5]+1,5);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,1,0,0);
+ cairo_rectangle(c,10.5,h-32.5,widths[0],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,0,1,0);
+ cairo_rectangle(c,10.5,h-28.5,widths[1],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,0,0,1);
+ cairo_rectangle(c,10.5,h-24.5,widths[2],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,.6,.4,.0);
+ cairo_rectangle(c,10.5,h-20.5,widths[3],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,.3,.3,.3);
+ cairo_rectangle(c,10.5,h-16.5,widths[4],4);
+ cairo_fill(c);
+ cairo_set_source_rgb(c,.5,.5,.8);
+ cairo_rectangle(c,10.5,h-12.5,widths[5],4);
+ cairo_fill(c);
+ }
+ /*Master qi indicator[s]:*/
+ if(_dec->telemetry_qi&0x1){
+ cairo_text_extents_t extents;
+ char buffer[10];
+ int p;
+ int y;
+ p=0;
+ y=h-7.5;
+ if(_dec->state.qis[0]>=10)buffer[p++]=48+_dec->state.qis[0]/10;
+ buffer[p++]=48+_dec->state.qis[0]%10;
+ if(_dec->state.nqis>=2){
+ buffer[p++]=' ';
+ if(_dec->state.qis[1]>=10)buffer[p++]=48+_dec->state.qis[1]/10;
+ buffer[p++]=48+_dec->state.qis[1]%10;
+ }
+ if(_dec->state.nqis==3){
+ buffer[p++]=' ';
+ if(_dec->state.qis[2]>=10)buffer[p++]=48+_dec->state.qis[2]/10;
+ buffer[p++]=48+_dec->state.qis[2]%10;
+ }
+ buffer[p++]='\0';
+ cairo_select_font_face(c,"sans",
+ CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size(c,18);
+ cairo_text_extents(c,buffer,&extents);
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_move_to(c,w-extents.x_advance-10,y);
+ cairo_show_text(c,buffer);
+ cairo_set_source_rgb(c,0,0,0);
+ cairo_move_to(c,w-extents.x_advance-10,y);
+ cairo_text_path(c,buffer);
+ cairo_set_line_width(c,.8);
+ cairo_set_line_join(c,CAIRO_LINE_JOIN_ROUND);
+ cairo_stroke(c);
+ }
+ cairo_destroy(c);
+ }
+ /*Out of the Cairo plane into the telemetry YUV buffer.*/
+ _ycbcr[0].data=_dec->telemetry_frame_data;
+ _ycbcr[0].stride=_ycbcr[0].width;
+ _ycbcr[1].data=_ycbcr[0].data+h*_ycbcr[0].stride;
+ _ycbcr[1].stride=_ycbcr[1].width;
+ _ycbcr[2].data=_ycbcr[1].data+(h>>vdec)*_ycbcr[1].stride;
+ _ycbcr[2].stride=_ycbcr[2].width;
+ y_row=_ycbcr[0].data;
+ u_row=_ycbcr[1].data;
+ v_row=_ycbcr[2].data;
+ rgb_row=data;
+ /*This is one of the few places it's worth handling chroma on a
+ case-by-case basis.*/
+ switch(_dec->state.info.pixel_fmt){
+ case TH_PF_420:{
+ for(y=0;y<h;y+=2){
+ unsigned char *y_row2;
+ unsigned char *rgb_row2;
+ y_row2=y_row+_ycbcr[0].stride;
+ rgb_row2=rgb_row+cstride;
+ for(x=0;x<w;x+=2){
+ int y;
+ int u;
+ int v;
+ y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+ +24966*rgb_row[4*x+0]+4207500)/255000;
+ y_row[x]=OC_CLAMP255(y);
+ y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
+ +24966*rgb_row[4*x+4]+4207500)/255000;
+ y_row[x+1]=OC_CLAMP255(y);
+ y=(65481*rgb_row2[4*x+2]+128553*rgb_row2[4*x+1]
+ +24966*rgb_row2[4*x+0]+4207500)/255000;
+ y_row2[x]=OC_CLAMP255(y);
+ y=(65481*rgb_row2[4*x+6]+128553*rgb_row2[4*x+5]
+ +24966*rgb_row2[4*x+4]+4207500)/255000;
+ y_row2[x+1]=OC_CLAMP255(y);
+ u=(-8372*(rgb_row[4*x+2]+rgb_row[4*x+6]
+ +rgb_row2[4*x+2]+rgb_row2[4*x+6])
+ -16436*(rgb_row[4*x+1]+rgb_row[4*x+5]
+ +rgb_row2[4*x+1]+rgb_row2[4*x+5])
+ +24808*(rgb_row[4*x+0]+rgb_row[4*x+4]
+ +rgb_row2[4*x+0]+rgb_row2[4*x+4])+29032005)/225930;
+ v=(39256*(rgb_row[4*x+2]+rgb_row[4*x+6]
+ +rgb_row2[4*x+2]+rgb_row2[4*x+6])
+ -32872*(rgb_row[4*x+1]+rgb_row[4*x+5]
+ +rgb_row2[4*x+1]+rgb_row2[4*x+5])
+ -6384*(rgb_row[4*x+0]+rgb_row[4*x+4]
+ +rgb_row2[4*x+0]+rgb_row2[4*x+4])+45940035)/357510;
+ u_row[x>>1]=OC_CLAMP255(u);
+ v_row[x>>1]=OC_CLAMP255(v);
+ }
+ y_row+=_ycbcr[0].stride<<1;
+ u_row+=_ycbcr[1].stride;
+ v_row+=_ycbcr[2].stride;
+ rgb_row+=cstride<<1;
+ }
+ }break;
+ case TH_PF_422:{
+ for(y=0;y<h;y++){
+ for(x=0;x<w;x+=2){
+ int y;
+ int u;
+ int v;
+ y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+ +24966*rgb_row[4*x+0]+4207500)/255000;
+ y_row[x]=OC_CLAMP255(y);
+ y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
+ +24966*rgb_row[4*x+4]+4207500)/255000;
+ y_row[x+1]=OC_CLAMP255(y);
+ u=(-16744*(rgb_row[4*x+2]+rgb_row[4*x+6])
+ -32872*(rgb_row[4*x+1]+rgb_row[4*x+5])
+ +49616*(rgb_row[4*x+0]+rgb_row[4*x+4])+29032005)/225930;
+ v=(78512*(rgb_row[4*x+2]+rgb_row[4*x+6])
+ -65744*(rgb_row[4*x+1]+rgb_row[4*x+5])
+ -12768*(rgb_row[4*x+0]+rgb_row[4*x+4])+45940035)/357510;
+ u_row[x>>1]=OC_CLAMP255(u);
+ v_row[x>>1]=OC_CLAMP255(v);
+ }
+ y_row+=_ycbcr[0].stride;
+ u_row+=_ycbcr[1].stride;
+ v_row+=_ycbcr[2].stride;
+ rgb_row+=cstride;
+ }
+ }break;
+ /*case TH_PF_444:*/
+ default:{
+ for(y=0;y<h;y++){
+ for(x=0;x<w;x++){
+ int y;
+ int u;
+ int v;
+ y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
+ +24966*rgb_row[4*x+0]+4207500)/255000;
+ u=(-33488*rgb_row[4*x+2]-65744*rgb_row[4*x+1]
+ +99232*rgb_row[4*x+0]+29032005)/225930;
+ v=(157024*rgb_row[4*x+2]-131488*rgb_row[4*x+1]
+ -25536*rgb_row[4*x+0]+45940035)/357510;
+ y_row[x]=OC_CLAMP255(y);
+ u_row[x]=OC_CLAMP255(u);
+ v_row[x]=OC_CLAMP255(v);
+ }
+ y_row+=_ycbcr[0].stride;
+ u_row+=_ycbcr[1].stride;
+ v_row+=_ycbcr[2].stride;
+ rgb_row+=cstride;
+ }
+ }break;
+ }
+ /*Finished.
+ Destroy the surface.*/
+ cairo_surface_destroy(cs);
}
+#endif
int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
ogg_int64_t *_granpos){
int ret;
if(_dec==NULL||_op==NULL)return TH_EFAULT;
/*A completely empty packet indicates a dropped frame and is treated exactly
- like an inter frame with no coded blocks.
- Only proceed if we have a non-empty packet.*/
- if(_op->bytes!=0){
- oc_dec_pipeline_state pipe;
- th_ycbcr_buffer stripe_buf;
- int stripe_fragy;
- int refi;
- int pli;
- int notstart;
- int notdone;
+ like an inter frame with no coded blocks.*/
+ if(_op->bytes==0){
+ _dec->state.frame_type=OC_INTER_FRAME;
+ _dec->state.ntotal_coded_fragis=0;
+ }
+ else{
oc_pack_readinit(&_dec->opb,_op->packet,_op->bytes);
+ ret=oc_dec_frame_header_unpack(_dec);
+ if(ret<0)return ret;
+ if(_dec->state.frame_type==OC_INTRA_FRAME)oc_dec_mark_all_intra(_dec);
+ else oc_dec_coded_flags_unpack(_dec);
+ }
+ /*If there have been no reference frames, and we need one, initialize one.*/
+ if(_dec->state.frame_type!=OC_INTRA_FRAME&&
+ (_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
+ _dec->state.ref_frame_idx[OC_FRAME_PREV]<0)){
+ oc_dec_init_dummy_frame(_dec);
+ }
+ /*If this was an inter frame with no coded blocks...*/
+ if(_dec->state.ntotal_coded_fragis<=0){
+ /*Just update the granule position and return.*/
+ _dec->state.granpos=(_dec->state.keyframe_num+_dec->state.granpos_bias<<
+ _dec->state.info.keyframe_granule_shift)
+ +(_dec->state.curframe_num-_dec->state.keyframe_num);
+ _dec->state.curframe_num++;
+ if(_granpos!=NULL)*_granpos=_dec->state.granpos;
+ return TH_DUPFRAME;
+ }
+ else{
+ th_ycbcr_buffer stripe_buf;
+ int stripe_fragy;
+ int refi;
+ int pli;
+ int notstart;
+ int notdone;
+#ifdef HAVE_CAIRO
+ int telemetry;
+ /*Save the current telemetry state.
+ This prevents it from being modified in the middle of decoding this
+ frame, which could cause us to skip calls to the striped decoding
+ callback.*/
+ telemetry=_dec->telemetry_mbmode||_dec->telemetry_mv||
+ _dec->telemetry_qi||_dec->telemetry_bits;
+#endif
+ /*Select a free buffer to use for the reconstructed version of this frame.*/
+ for(refi=0;refi==_dec->state.ref_frame_idx[OC_FRAME_GOLD]||
+ refi==_dec->state.ref_frame_idx[OC_FRAME_PREV];refi++);
+ _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
+ _dec->state.ref_frame_data[OC_FRAME_SELF]=
+ _dec->state.ref_frame_bufs[refi][0].data;
#if defined(HAVE_CAIRO)
_dec->telemetry_frame_bytes=_op->bytes;
#endif
- ret=oc_dec_frame_header_unpack(_dec);
- if(ret<0)return ret;
- /*Select a free buffer to use for the reconstructed version of this
- frame.*/
- if(_dec->state.frame_type!=OC_INTRA_FRAME&&
- (_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
- _dec->state.ref_frame_idx[OC_FRAME_PREV]<0)){
- /*No reference frames yet!*/
- oc_dec_init_dummy_frame(_dec);
- refi=_dec->state.ref_frame_idx[OC_FRAME_SELF];
- }
- else{
- for(refi=0;refi==_dec->state.ref_frame_idx[OC_FRAME_GOLD]||
- refi==_dec->state.ref_frame_idx[OC_FRAME_PREV];refi++);
- _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
- }
if(_dec->state.frame_type==OC_INTRA_FRAME){
- oc_dec_mark_all_intra(_dec);
_dec->state.keyframe_num=_dec->state.curframe_num;
#if defined(HAVE_CAIRO)
_dec->telemetry_coding_bytes=
@@ -2112,7 +2804,6 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
#endif
}
else{
- oc_dec_coded_flags_unpack(_dec);
#if defined(HAVE_CAIRO)
_dec->telemetry_coding_bytes=oc_pack_bytes_left(&_dec->opb);
#endif
@@ -2160,15 +2851,15 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
An application callback allows further application processing (blitting
to video memory, color conversion, etc.) to also use the data while it's
in cache.*/
- oc_dec_pipeline_init(_dec,&pipe);
+ oc_dec_pipeline_init(_dec,&_dec->pipe);
oc_ycbcr_buffer_flip(stripe_buf,_dec->pp_frame_buf);
notstart=0;
notdone=1;
- for(stripe_fragy=0;notdone;stripe_fragy+=pipe.mcu_nvfrags){
+ for(stripe_fragy=0;notdone;stripe_fragy+=_dec->pipe.mcu_nvfrags){
int avail_fragy0;
int avail_fragy_end;
avail_fragy0=avail_fragy_end=_dec->state.fplanes[0].nvfrags;
- notdone=stripe_fragy+pipe.mcu_nvfrags<avail_fragy_end;
+ notdone=stripe_fragy+_dec->pipe.mcu_nvfrags<avail_fragy_end;
for(pli=0;pli<3;pli++){
oc_fragment_plane *fplane;
int frag_shift;
@@ -2179,45 +2870,46 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
/*Compute the first and last fragment row of the current MCU for this
plane.*/
frag_shift=pli!=0&&!(_dec->state.info.pixel_fmt&2);
- pipe.fragy0[pli]=stripe_fragy>>frag_shift;
- pipe.fragy_end[pli]=OC_MINI(fplane->nvfrags,
- pipe.fragy0[pli]+(pipe.mcu_nvfrags>>frag_shift));
- oc_dec_dc_unpredict_mcu_plane(_dec,&pipe,pli);
- oc_dec_frags_recon_mcu_plane(_dec,&pipe,pli);
+ _dec->pipe.fragy0[pli]=stripe_fragy>>frag_shift;
+ _dec->pipe.fragy_end[pli]=OC_MINI(fplane->nvfrags,
+ _dec->pipe.fragy0[pli]+(_dec->pipe.mcu_nvfrags>>frag_shift));
+ oc_dec_dc_unpredict_mcu_plane(_dec,&_dec->pipe,pli);
+ oc_dec_frags_recon_mcu_plane(_dec,&_dec->pipe,pli);
sdelay=edelay=0;
- if(pipe.loop_filter){
+ if(_dec->pipe.loop_filter){
sdelay+=notstart;
edelay+=notdone;
- oc_state_loop_filter_frag_rows(&_dec->state,pipe.bounding_values,
- refi,pli,pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay);
+ oc_state_loop_filter_frag_rows(&_dec->state,
+ _dec->pipe.bounding_values,OC_FRAME_SELF,pli,
+ _dec->pipe.fragy0[pli]-sdelay,_dec->pipe.fragy_end[pli]-edelay);
}
/*To fill the borders, we have an additional two pixel delay, since a
fragment in the next row could filter its top edge, using two pixels
from a fragment in this row.
But there's no reason to delay a full fragment between the two.*/
oc_state_borders_fill_rows(&_dec->state,refi,pli,
- (pipe.fragy0[pli]-sdelay<<3)-(sdelay<<1),
- (pipe.fragy_end[pli]-edelay<<3)-(edelay<<1));
+ (_dec->pipe.fragy0[pli]-sdelay<<3)-(sdelay<<1),
+ (_dec->pipe.fragy_end[pli]-edelay<<3)-(edelay<<1));
/*Out-of-loop post-processing.*/
pp_offset=3*(pli!=0);
- if(pipe.pp_level>=OC_PP_LEVEL_DEBLOCKY+pp_offset){
+ if(_dec->pipe.pp_level>=OC_PP_LEVEL_DEBLOCKY+pp_offset){
/*Perform de-blocking in one plane.*/
sdelay+=notstart;
edelay+=notdone;
oc_dec_deblock_frag_rows(_dec,_dec->pp_frame_buf,
_dec->state.ref_frame_bufs[refi],pli,
- pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay);
- if(pipe.pp_level>=OC_PP_LEVEL_DERINGY+pp_offset){
+ _dec->pipe.fragy0[pli]-sdelay,_dec->pipe.fragy_end[pli]-edelay);
+ if(_dec->pipe.pp_level>=OC_PP_LEVEL_DERINGY+pp_offset){
/*Perform de-ringing in one plane.*/
sdelay+=notstart;
edelay+=notdone;
oc_dec_dering_frag_rows(_dec,_dec->pp_frame_buf,pli,
- pipe.fragy0[pli]-sdelay,pipe.fragy_end[pli]-edelay);
+ _dec->pipe.fragy0[pli]-sdelay,_dec->pipe.fragy_end[pli]-edelay);
}
}
/*If no post-processing is done, we still need to delay a row for the
loop filter, thanks to the strange filtering order VP3 chose.*/
- else if(pipe.loop_filter){
+ else if(_dec->pipe.loop_filter){
sdelay+=notstart;
edelay+=notdone;
}
@@ -2226,11 +2918,16 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
doubled, but luma might have more post-processing filters enabled
than chroma, so we don't know up front which one is the limiting
factor.*/
- avail_fragy0=OC_MINI(avail_fragy0,pipe.fragy0[pli]-sdelay<<frag_shift);
+ avail_fragy0=OC_MINI(avail_fragy0,
+ _dec->pipe.fragy0[pli]-sdelay<<frag_shift);
avail_fragy_end=OC_MINI(avail_fragy_end,
- pipe.fragy_end[pli]-edelay<<frag_shift);
+ _dec->pipe.fragy_end[pli]-edelay<<frag_shift);
}
+#ifdef HAVE_CAIRO
+ if(_dec->stripe_cb.stripe_decoded!=NULL&&!telemetry){
+#else
if(_dec->stripe_cb.stripe_decoded!=NULL){
+#endif
/*The callback might want to use the FPU, so let's make sure they can.
We violate all kinds of ABI restrictions by not doing this until
now, but none of them actually matter since we don't use floating
@@ -2252,692 +2949,44 @@ int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
_dec->state.ref_frame_idx[OC_FRAME_GOLD]=
_dec->state.ref_frame_idx[OC_FRAME_PREV]=
_dec->state.ref_frame_idx[OC_FRAME_SELF];
+ _dec->state.ref_frame_data[OC_FRAME_GOLD]=
+ _dec->state.ref_frame_data[OC_FRAME_PREV]=
+ _dec->state.ref_frame_data[OC_FRAME_SELF];
}
else{
/*Otherwise, just replace the previous reference frame.*/
_dec->state.ref_frame_idx[OC_FRAME_PREV]=
_dec->state.ref_frame_idx[OC_FRAME_SELF];
+ _dec->state.ref_frame_data[OC_FRAME_PREV]=
+ _dec->state.ref_frame_data[OC_FRAME_SELF];
}
/*Restore the FPU before dump_frame, since that _does_ use the FPU (for PNG
gamma values, if nothing else).*/
oc_restore_fpu(&_dec->state);
+#ifdef HAVE_CAIRO
+ /*If telemetry ioctls are active, we need to draw to the output buffer.*/
+ if(telemetry){
+ oc_render_telemetry(_dec,stripe_buf,telemetry);
+ oc_ycbcr_buffer_flip(_dec->pp_frame_buf,stripe_buf);
+ /*If we had a striped decoding callback, we skipped calling it above
+ (because the telemetry wasn't rendered yet).
+ Call it now with the whole frame.*/
+ if(_dec->stripe_cb.stripe_decoded!=NULL){
+ (*_dec->stripe_cb.stripe_decoded)(_dec->stripe_cb.ctx,
+ stripe_buf,0,_dec->state.fplanes[0].nvfrags);
+ }
+ }
+#endif
#if defined(OC_DUMP_IMAGES)
- /*Don't dump images for dropped frames.*/
+ /*We only dump images if there were some coded blocks.*/
oc_state_dump_frame(&_dec->state,OC_FRAME_SELF,"dec");
#endif
return 0;
}
- else{
- if(_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
- _dec->state.ref_frame_idx[OC_FRAME_PREV]<0){
- int refi;
- /*No reference frames yet!*/
- oc_dec_init_dummy_frame(_dec);
- refi=_dec->state.ref_frame_idx[OC_FRAME_PREV];
- _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
- memcpy(_dec->pp_frame_buf,_dec->state.ref_frame_bufs[refi],
- sizeof(_dec->pp_frame_buf[0])*3);
- }
- /*Just update the granule position and return.*/
- _dec->state.granpos=(_dec->state.keyframe_num+_dec->state.granpos_bias<<
- _dec->state.info.keyframe_granule_shift)
- +(_dec->state.curframe_num-_dec->state.keyframe_num);
- _dec->state.curframe_num++;
- if(_granpos!=NULL)*_granpos=_dec->state.granpos;
- return TH_DUPFRAME;
- }
}
int th_decode_ycbcr_out(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr){
if(_dec==NULL||_ycbcr==NULL)return TH_EFAULT;
oc_ycbcr_buffer_flip(_ycbcr,_dec->pp_frame_buf);
-#if defined(HAVE_CAIRO)
- /*If telemetry ioctls are active, we need to draw to the output buffer.
- Stuff the plane into cairo.*/
- if(_dec->telemetry){
- cairo_surface_t *cs;
- unsigned char *data;
- unsigned char *y_row;
- unsigned char *u_row;
- unsigned char *v_row;
- unsigned char *rgb_row;
- int cstride;
- int w;
- int h;
- int x;
- int y;
- int hdec;
- int vdec;
- w=_ycbcr[0].width;
- h=_ycbcr[0].height;
- hdec=!(_dec->state.info.pixel_fmt&1);
- vdec=!(_dec->state.info.pixel_fmt&2);
- /*Lazy data buffer init.
- We could try to re-use the post-processing buffer, which would save
- memory, but complicate the allocation logic there.
- I don't think anyone cares about memory usage when using telemetry; it is
- not meant for embedded devices.*/
- if(_dec->telemetry_frame_data==NULL){
- _dec->telemetry_frame_data=_ogg_malloc(
- (w*h+2*(w>>hdec)*(h>>vdec))*sizeof(*_dec->telemetry_frame_data));
- if(_dec->telemetry_frame_data==NULL)return 0;
- }
- cs=cairo_image_surface_create(CAIRO_FORMAT_RGB24,w,h);
- /*Sadly, no YUV support in Cairo (yet); convert into the RGB buffer.*/
- data=cairo_image_surface_get_data(cs);
- if(data==NULL){
- cairo_surface_destroy(cs);
- return 0;
- }
- cstride=cairo_image_surface_get_stride(cs);
- y_row=_ycbcr[0].data;
- u_row=_ycbcr[1].data;
- v_row=_ycbcr[2].data;
- rgb_row=data;
- for(y=0;y<h;y++){
- for(x=0;x<w;x++){
- int r;
- int g;
- int b;
- r=(1904000*y_row[x]+2609823*v_row[x>>hdec]-363703744)/1635200;
- g=(3827562*y_row[x]-1287801*u_row[x>>hdec]
- -2672387*v_row[x>>hdec]+447306710)/3287200;
- b=(952000*y_row[x]+1649289*u_row[x>>hdec]-225932192)/817600;
- rgb_row[4*x+0]=OC_CLAMP255(b);
- rgb_row[4*x+1]=OC_CLAMP255(g);
- rgb_row[4*x+2]=OC_CLAMP255(r);
- }
- y_row+=_ycbcr[0].stride;
- u_row+=_ycbcr[1].stride&-((y&1)|!vdec);
- v_row+=_ycbcr[2].stride&-((y&1)|!vdec);
- rgb_row+=cstride;
- }
- /*Draw coded identifier for each macroblock (stored in Hilbert order).*/
- {
- cairo_t *c;
- const oc_fragment *frags;
- oc_mv *frag_mvs;
- const signed char *mb_modes;
- oc_mb_map *mb_maps;
- size_t nmbs;
- size_t mbi;
- int row2;
- int col2;
- int qim[3]={0,0,0};
- if(_dec->state.nqis==2){
- int bqi;
- bqi=_dec->state.qis[0];
- if(_dec->state.qis[1]>bqi)qim[1]=1;
- if(_dec->state.qis[1]<bqi)qim[1]=-1;
- }
- if(_dec->state.nqis==3){
- int bqi;
- int cqi;
- int dqi;
- bqi=_dec->state.qis[0];
- cqi=_dec->state.qis[1];
- dqi=_dec->state.qis[2];
- if(cqi>bqi&&dqi>bqi){
- if(dqi>cqi){
- qim[1]=1;
- qim[2]=2;
- }
- else{
- qim[1]=2;
- qim[2]=1;
- }
- }
- else if(cqi<bqi&&dqi<bqi){
- if(dqi<cqi){
- qim[1]=-1;
- qim[2]=-2;
- }
- else{
- qim[1]=-2;
- qim[2]=-1;
- }
- }
- else{
- if(cqi<bqi)qim[1]=-1;
- else qim[1]=1;
- if(dqi<bqi)qim[2]=-1;
- else qim[2]=1;
- }
- }
- c=cairo_create(cs);
- frags=_dec->state.frags;
- frag_mvs=_dec->state.frag_mvs;
- mb_modes=_dec->state.mb_modes;
- mb_maps=_dec->state.mb_maps;
- nmbs=_dec->state.nmbs;
- row2=0;
- col2=0;
- for(mbi=0;mbi<nmbs;mbi++){
- float x;
- float y;
- int bi;
- y=h-(row2+((col2+1>>1)&1))*16-16;
- x=(col2>>1)*16;
- cairo_set_line_width(c,1.);
- /*Keyframe (all intra) red box.*/
- if(_dec->state.frame_type==OC_INTRA_FRAME){
- if(_dec->telemetry_mbmode&0x02){
- cairo_set_source_rgba(c,1.,0,0,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,0,0,.25);
- cairo_fill(c);
- }
- }
- else{
- const signed char *frag_mv;
- ptrdiff_t fragi;
- for(bi=0;bi<4;bi++){
- fragi=mb_maps[mbi][0][bi];
- if(fragi>=0&&frags[fragi].coded){
- frag_mv=frag_mvs[fragi];
- break;
- }
- }
- if(bi<4){
- switch(mb_modes[mbi]){
- case OC_MODE_INTRA:{
- if(_dec->telemetry_mbmode&0x02){
- cairo_set_source_rgba(c,1.,0,0,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,0,0,.25);
- cairo_fill(c);
- }
- }break;
- case OC_MODE_INTER_NOMV:{
- if(_dec->telemetry_mbmode&0x01){
- cairo_set_source_rgba(c,0,0,1.,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,0,0,1.,.25);
- cairo_fill(c);
- }
- }break;
- case OC_MODE_INTER_MV:{
- if(_dec->telemetry_mbmode&0x04){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x04){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_INTER_MV_LAST:{
- if(_dec->telemetry_mbmode&0x08){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_move_to(c,x+13.5,y+2.5);
- cairo_line_to(c,x+2.5,y+8);
- cairo_line_to(c,x+13.5,y+13.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x08){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_INTER_MV_LAST2:{
- if(_dec->telemetry_mbmode&0x10){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_move_to(c,x+8,y+2.5);
- cairo_line_to(c,x+2.5,y+8);
- cairo_line_to(c,x+8,y+13.5);
- cairo_move_to(c,x+13.5,y+2.5);
- cairo_line_to(c,x+8,y+8);
- cairo_line_to(c,x+13.5,y+13.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x10){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_GOLDEN_NOMV:{
- if(_dec->telemetry_mbmode&0x20){
- cairo_set_source_rgba(c,1.,1.,0,.5);
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,1.,0,.25);
- cairo_fill(c);
- }
- }break;
- case OC_MODE_GOLDEN_MV:{
- if(_dec->telemetry_mbmode&0x40){
- cairo_rectangle(c,x+2.5,y+2.5,11,11);
- cairo_set_source_rgba(c,1.,1.,0,.5);
- cairo_stroke(c);
- }
- if(_dec->telemetry_mv&0x40){
- cairo_move_to(c,x+8+frag_mv[0],y+8-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+8+frag_mv[0]*.66,y+8-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+8+frag_mv[0]*.33,y+8-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+8,y+8);
- cairo_stroke(c);
- }
- }break;
- case OC_MODE_INTER_MV_FOUR:{
- if(_dec->telemetry_mbmode&0x80){
- cairo_rectangle(c,x+2.5,y+2.5,4,4);
- cairo_rectangle(c,x+9.5,y+2.5,4,4);
- cairo_rectangle(c,x+2.5,y+9.5,4,4);
- cairo_rectangle(c,x+9.5,y+9.5,4,4);
- cairo_set_source_rgba(c,0,1.,0,.5);
- cairo_stroke(c);
- }
- /*4mv is odd, coded in raster order.*/
- fragi=mb_maps[mbi][0][0];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+4+frag_mv[0],y+12-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+4+frag_mv[0]*.66,y+12-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+4+frag_mv[0]*.33,y+12-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+4,y+12);
- cairo_stroke(c);
- }
- fragi=mb_maps[mbi][0][1];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+12+frag_mv[0],y+12-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+12+frag_mv[0]*.66,y+12-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+12+frag_mv[0]*.33,y+12-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+12,y+12);
- cairo_stroke(c);
- }
- fragi=mb_maps[mbi][0][2];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+4+frag_mv[0],y+4-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+4+frag_mv[0]*.66,y+4-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+4+frag_mv[0]*.33,y+4-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+4,y+4);
- cairo_stroke(c);
- }
- fragi=mb_maps[mbi][0][3];
- if(frags[fragi].coded&&_dec->telemetry_mv&0x80){
- frag_mv=frag_mvs[fragi];
- cairo_move_to(c,x+12+frag_mv[0],y+4-frag_mv[1]);
- cairo_set_source_rgba(c,1.,1.,1.,.9);
- cairo_set_line_width(c,3.);
- cairo_line_to(c,x+12+frag_mv[0]*.66,y+4-frag_mv[1]*.66);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,2.);
- cairo_line_to(c,x+12+frag_mv[0]*.33,y+4-frag_mv[1]*.33);
- cairo_stroke_preserve(c);
- cairo_set_line_width(c,1.);
- cairo_line_to(c,x+12,y+4);
- cairo_stroke(c);
- }
- }break;
- }
- }
- }
- /*qii illustration.*/
- if(_dec->telemetry_qi&0x2){
- cairo_set_line_cap(c,CAIRO_LINE_CAP_SQUARE);
- for(bi=0;bi<4;bi++){
- ptrdiff_t fragi;
- int qiv;
- int xp;
- int yp;
- xp=x+(bi&1)*8;
- yp=y+8-(bi&2)*4;
- fragi=mb_maps[mbi][0][bi];
- if(fragi>=0&&frags[fragi].coded){
- qiv=qim[frags[fragi].qii];
- cairo_set_line_width(c,3.);
- cairo_set_source_rgba(c,0.,0.,0.,.5);
- switch(qiv){
- /*Double plus:*/
- case 2:{
- if((bi&1)^((bi&2)>>1)){
- cairo_move_to(c,xp+2.5,yp+1.5);
- cairo_line_to(c,xp+2.5,yp+3.5);
- cairo_move_to(c,xp+1.5,yp+2.5);
- cairo_line_to(c,xp+3.5,yp+2.5);
- cairo_move_to(c,xp+5.5,yp+4.5);
- cairo_line_to(c,xp+5.5,yp+6.5);
- cairo_move_to(c,xp+4.5,yp+5.5);
- cairo_line_to(c,xp+6.5,yp+5.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,0.,1.,1.,1.);
- }
- else{
- cairo_move_to(c,xp+5.5,yp+1.5);
- cairo_line_to(c,xp+5.5,yp+3.5);
- cairo_move_to(c,xp+4.5,yp+2.5);
- cairo_line_to(c,xp+6.5,yp+2.5);
- cairo_move_to(c,xp+2.5,yp+4.5);
- cairo_line_to(c,xp+2.5,yp+6.5);
- cairo_move_to(c,xp+1.5,yp+5.5);
- cairo_line_to(c,xp+3.5,yp+5.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,0.,1.,1.,1.);
- }
- }break;
- /*Double minus:*/
- case -2:{
- cairo_move_to(c,xp+2.5,yp+2.5);
- cairo_line_to(c,xp+5.5,yp+2.5);
- cairo_move_to(c,xp+2.5,yp+5.5);
- cairo_line_to(c,xp+5.5,yp+5.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,1.,1.,1.);
- }break;
- /*Plus:*/
- case 1:{
- if(bi&2==0)yp-=2;
- if(bi&1==0)xp-=2;
- cairo_move_to(c,xp+4.5,yp+2.5);
- cairo_line_to(c,xp+4.5,yp+6.5);
- cairo_move_to(c,xp+2.5,yp+4.5);
- cairo_line_to(c,xp+6.5,yp+4.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,.1,1.,.3,1.);
- break;
- }
- /*Fall through.*/
- /*Minus:*/
- case -1:{
- cairo_move_to(c,xp+2.5,yp+4.5);
- cairo_line_to(c,xp+6.5,yp+4.5);
- cairo_stroke_preserve(c);
- cairo_set_source_rgba(c,1.,.3,.1,1.);
- }break;
- default:continue;
- }
- cairo_set_line_width(c,1.);
- cairo_stroke(c);
- }
- }
- }
- col2++;
- if((col2>>1)>=_dec->state.nhmbs){
- col2=0;
- row2+=2;
- }
- }
- /*Bit usage indicator[s]:*/
- if(_dec->telemetry_bits){
- int widths[6];
- int fpsn;
- int fpsd;
- int mult;
- int fullw;
- int padw;
- int i;
- fpsn=_dec->state.info.fps_numerator;
- fpsd=_dec->state.info.fps_denominator;
- mult=(_dec->telemetry_bits>=0xFF?1:_dec->telemetry_bits);
- fullw=250.f*h*fpsd*mult/fpsn;
- padw=w-24;
- /*Header and coded block bits.*/
- if(_dec->telemetry_frame_bytes<0||
- _dec->telemetry_frame_bytes==OC_LOTS_OF_BITS){
- _dec->telemetry_frame_bytes=0;
- }
- if(_dec->telemetry_coding_bytes<0||
- _dec->telemetry_coding_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_coding_bytes=0;
- }
- if(_dec->telemetry_mode_bytes<0||
- _dec->telemetry_mode_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_mode_bytes=0;
- }
- if(_dec->telemetry_mv_bytes<0||
- _dec->telemetry_mv_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_mv_bytes=0;
- }
- if(_dec->telemetry_qi_bytes<0||
- _dec->telemetry_qi_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_qi_bytes=0;
- }
- if(_dec->telemetry_dc_bytes<0||
- _dec->telemetry_dc_bytes>_dec->telemetry_frame_bytes){
- _dec->telemetry_dc_bytes=0;
- }
- widths[0]=padw*(_dec->telemetry_frame_bytes-_dec->telemetry_coding_bytes)/fullw;
- widths[1]=padw*(_dec->telemetry_coding_bytes-_dec->telemetry_mode_bytes)/fullw;
- widths[2]=padw*(_dec->telemetry_mode_bytes-_dec->telemetry_mv_bytes)/fullw;
- widths[3]=padw*(_dec->telemetry_mv_bytes-_dec->telemetry_qi_bytes)/fullw;
- widths[4]=padw*(_dec->telemetry_qi_bytes-_dec->telemetry_dc_bytes)/fullw;
- widths[5]=padw*(_dec->telemetry_dc_bytes)/fullw;
- for(i=0;i<6;i++)if(widths[i]>w)widths[i]=w;
- cairo_set_source_rgba(c,.0,.0,.0,.6);
- cairo_rectangle(c,10,h-33,widths[0]+1,5);
- cairo_rectangle(c,10,h-29,widths[1]+1,5);
- cairo_rectangle(c,10,h-25,widths[2]+1,5);
- cairo_rectangle(c,10,h-21,widths[3]+1,5);
- cairo_rectangle(c,10,h-17,widths[4]+1,5);
- cairo_rectangle(c,10,h-13,widths[5]+1,5);
- cairo_fill(c);
- cairo_set_source_rgb(c,1,0,0);
- cairo_rectangle(c,10.5,h-32.5,widths[0],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,0,1,0);
- cairo_rectangle(c,10.5,h-28.5,widths[1],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,0,0,1);
- cairo_rectangle(c,10.5,h-24.5,widths[2],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,.6,.4,.0);
- cairo_rectangle(c,10.5,h-20.5,widths[3],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,.3,.3,.3);
- cairo_rectangle(c,10.5,h-16.5,widths[4],4);
- cairo_fill(c);
- cairo_set_source_rgb(c,.5,.5,.8);
- cairo_rectangle(c,10.5,h-12.5,widths[5],4);
- cairo_fill(c);
- }
- /*Master qi indicator[s]:*/
- if(_dec->telemetry_qi&0x1){
- cairo_text_extents_t extents;
- char buffer[10];
- int p;
- int y;
- p=0;
- y=h-7.5;
- if(_dec->state.qis[0]>=10)buffer[p++]=48+_dec->state.qis[0]/10;
- buffer[p++]=48+_dec->state.qis[0]%10;
- if(_dec->state.nqis>=2){
- buffer[p++]=' ';
- if(_dec->state.qis[1]>=10)buffer[p++]=48+_dec->state.qis[1]/10;
- buffer[p++]=48+_dec->state.qis[1]%10;
- }
- if(_dec->state.nqis==3){
- buffer[p++]=' ';
- if(_dec->state.qis[2]>=10)buffer[p++]=48+_dec->state.qis[2]/10;
- buffer[p++]=48+_dec->state.qis[2]%10;
- }
- buffer[p++]='\0';
- cairo_select_font_face(c,"sans",
- CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_BOLD);
- cairo_set_font_size(c,18);
- cairo_text_extents(c,buffer,&extents);
- cairo_set_source_rgb(c,1,1,1);
- cairo_move_to(c,w-extents.x_advance-10,y);
- cairo_show_text(c,buffer);
- cairo_set_source_rgb(c,0,0,0);
- cairo_move_to(c,w-extents.x_advance-10,y);
- cairo_text_path(c,buffer);
- cairo_set_line_width(c,.8);
- cairo_set_line_join(c,CAIRO_LINE_JOIN_ROUND);
- cairo_stroke(c);
- }
- cairo_destroy(c);
- }
- /*Out of the Cairo plane into the telemetry YUV buffer.*/
- _ycbcr[0].data=_dec->telemetry_frame_data;
- _ycbcr[0].stride=_ycbcr[0].width;
- _ycbcr[1].data=_ycbcr[0].data+h*_ycbcr[0].stride;
- _ycbcr[1].stride=_ycbcr[1].width;
- _ycbcr[2].data=_ycbcr[1].data+(h>>vdec)*_ycbcr[1].stride;
- _ycbcr[2].stride=_ycbcr[2].width;
- y_row=_ycbcr[0].data;
- u_row=_ycbcr[1].data;
- v_row=_ycbcr[2].data;
- rgb_row=data;
- /*This is one of the few places it's worth handling chroma on a
- case-by-case basis.*/
- switch(_dec->state.info.pixel_fmt){
- case TH_PF_420:{
- for(y=0;y<h;y+=2){
- unsigned char *y_row2;
- unsigned char *rgb_row2;
- y_row2=y_row+_ycbcr[0].stride;
- rgb_row2=rgb_row+cstride;
- for(x=0;x<w;x+=2){
- int y;
- int u;
- int v;
- y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
- +24966*rgb_row[4*x+0]+4207500)/255000;
- y_row[x]=OC_CLAMP255(y);
- y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
- +24966*rgb_row[4*x+4]+4207500)/255000;
- y_row[x+1]=OC_CLAMP255(y);
- y=(65481*rgb_row2[4*x+2]+128553*rgb_row2[4*x+1]
- +24966*rgb_row2[4*x+0]+4207500)/255000;
- y_row2[x]=OC_CLAMP255(y);
- y=(65481*rgb_row2[4*x+6]+128553*rgb_row2[4*x+5]
- +24966*rgb_row2[4*x+4]+4207500)/255000;
- y_row2[x+1]=OC_CLAMP255(y);
- u=(-8372*(rgb_row[4*x+2]+rgb_row[4*x+6]
- +rgb_row2[4*x+2]+rgb_row2[4*x+6])
- -16436*(rgb_row[4*x+1]+rgb_row[4*x+5]
- +rgb_row2[4*x+1]+rgb_row2[4*x+5])
- +24808*(rgb_row[4*x+0]+rgb_row[4*x+4]
- +rgb_row2[4*x+0]+rgb_row2[4*x+4])+29032005)/225930;
- v=(39256*(rgb_row[4*x+2]+rgb_row[4*x+6]
- +rgb_row2[4*x+2]+rgb_row2[4*x+6])
- -32872*(rgb_row[4*x+1]+rgb_row[4*x+5]
- +rgb_row2[4*x+1]+rgb_row2[4*x+5])
- -6384*(rgb_row[4*x+0]+rgb_row[4*x+4]
- +rgb_row2[4*x+0]+rgb_row2[4*x+4])+45940035)/357510;
- u_row[x>>1]=OC_CLAMP255(u);
- v_row[x>>1]=OC_CLAMP255(v);
- }
- y_row+=_ycbcr[0].stride<<1;
- u_row+=_ycbcr[1].stride;
- v_row+=_ycbcr[2].stride;
- rgb_row+=cstride<<1;
- }
- }break;
- case TH_PF_422:{
- for(y=0;y<h;y++){
- for(x=0;x<w;x+=2){
- int y;
- int u;
- int v;
- y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
- +24966*rgb_row[4*x+0]+4207500)/255000;
- y_row[x]=OC_CLAMP255(y);
- y=(65481*rgb_row[4*x+6]+128553*rgb_row[4*x+5]
- +24966*rgb_row[4*x+4]+4207500)/255000;
- y_row[x+1]=OC_CLAMP255(y);
- u=(-16744*(rgb_row[4*x+2]+rgb_row[4*x+6])
- -32872*(rgb_row[4*x+1]+rgb_row[4*x+5])
- +49616*(rgb_row[4*x+0]+rgb_row[4*x+4])+29032005)/225930;
- v=(78512*(rgb_row[4*x+2]+rgb_row[4*x+6])
- -65744*(rgb_row[4*x+1]+rgb_row[4*x+5])
- -12768*(rgb_row[4*x+0]+rgb_row[4*x+4])+45940035)/357510;
- u_row[x>>1]=OC_CLAMP255(u);
- v_row[x>>1]=OC_CLAMP255(v);
- }
- y_row+=_ycbcr[0].stride;
- u_row+=_ycbcr[1].stride;
- v_row+=_ycbcr[2].stride;
- rgb_row+=cstride;
- }
- }break;
- /*case TH_PF_444:*/
- default:{
- for(y=0;y<h;y++){
- for(x=0;x<w;x++){
- int y;
- int u;
- int v;
- y=(65481*rgb_row[4*x+2]+128553*rgb_row[4*x+1]
- +24966*rgb_row[4*x+0]+4207500)/255000;
- u=(-33488*rgb_row[4*x+2]-65744*rgb_row[4*x+1]
- +99232*rgb_row[4*x+0]+29032005)/225930;
- v=(157024*rgb_row[4*x+2]-131488*rgb_row[4*x+1]
- -25536*rgb_row[4*x+0]+45940035)/357510;
- y_row[x]=OC_CLAMP255(y);
- u_row[x]=OC_CLAMP255(u);
- v_row[x]=OC_CLAMP255(v);
- }
- y_row+=_ycbcr[0].stride;
- u_row+=_ycbcr[1].stride;
- v_row+=_ycbcr[2].stride;
- rgb_row+=cstride;
- }
- }break;
- }
- /*Finished.
- Destroy the surface.*/
- cairo_surface_destroy(cs);
- }
-#endif
return 0;
}
diff --git a/thirdparty/libtheora/dequant.c b/thirdparty/libtheora/dequant.c
index e554872d4e..860536f72d 100644
--- a/thirdparty/libtheora/dequant.c
+++ b/thirdparty/libtheora/dequant.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: dequant.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/dequant.h b/thirdparty/libtheora/dequant.h
index ef25838e35..9d6cd6be56 100644
--- a/thirdparty/libtheora/dequant.h
+++ b/thirdparty/libtheora/dequant.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: dequant.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/encfrag.c b/thirdparty/libtheora/encfrag.c
index bb814c8e4a..0e18111ac7 100644
--- a/thirdparty/libtheora/encfrag.c
+++ b/thirdparty/libtheora/encfrag.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: encfrag.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -19,11 +19,6 @@
#include "encint.h"
-void oc_enc_frag_sub(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,const unsigned char *_ref,int _ystride){
- (*_enc->opt_vtable.frag_sub)(_diff,_src,_ref,_ystride);
-}
-
void oc_enc_frag_sub_c(ogg_int16_t _diff[64],const unsigned char *_src,
const unsigned char *_ref,int _ystride){
int i;
@@ -35,11 +30,6 @@ void oc_enc_frag_sub_c(ogg_int16_t _diff[64],const unsigned char *_src,
}
}
-void oc_enc_frag_sub_128(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,int _ystride){
- (*_enc->opt_vtable.frag_sub_128)(_diff,_src,_ystride);
-}
-
void oc_enc_frag_sub_128_c(ogg_int16_t *_diff,
const unsigned char *_src,int _ystride){
int i;
@@ -50,11 +40,6 @@ void oc_enc_frag_sub_128_c(ogg_int16_t *_diff,
}
}
-unsigned oc_enc_frag_sad(const oc_enc_ctx *_enc,const unsigned char *_x,
- const unsigned char *_y,int _ystride){
- return (*_enc->opt_vtable.frag_sad)(_x,_y,_ystride);
-}
-
unsigned oc_enc_frag_sad_c(const unsigned char *_src,
const unsigned char *_ref,int _ystride){
unsigned sad;
@@ -69,12 +54,6 @@ unsigned oc_enc_frag_sad_c(const unsigned char *_src,
return sad;
}
-unsigned oc_enc_frag_sad_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh){
- return (*_enc->opt_vtable.frag_sad_thresh)(_src,_ref,_ystride,_thresh);
-}
-
unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
const unsigned char *_ref,int _ystride,unsigned _thresh){
unsigned sad;
@@ -90,13 +69,6 @@ unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
return sad;
}
-unsigned oc_enc_frag_sad2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh){
- return (*_enc->opt_vtable.frag_sad2_thresh)(_src,_ref1,_ref2,_ystride,
- _thresh);
-}
-
unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh){
@@ -114,6 +86,27 @@ unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
return sad;
}
+unsigned oc_enc_frag_intra_sad_c(const unsigned char *_src, int _ystride){
+ const unsigned char *src = _src;
+ unsigned dc;
+ unsigned sad;
+ int i;
+ dc=0;
+ for(i=8;i-->0;){
+ int j;
+ for(j=0;j<8;j++)dc+=src[j];
+ src+=_ystride;
+ }
+ dc=dc+32>>6;
+ sad=0;
+ for(i=8;i-->0;){
+ int j;
+ for(j=0;j<8;j++)sad+=abs(_src[j]-dc);
+ _src+=_ystride;
+ }
+ return sad;
+}
+
static void oc_diff_hadamard(ogg_int16_t _buf[64],const unsigned char *_src,
const unsigned char *_ref,int _ystride){
int i;
@@ -269,19 +262,20 @@ static void oc_intra_hadamard(ogg_int16_t _buf[64],const unsigned char *_src,
}
}
-unsigned oc_hadamard_sad_thresh(const ogg_int16_t _buf[64],unsigned _thresh){
- unsigned sad;
- int t0;
- int t1;
- int t2;
- int t3;
- int t4;
- int t5;
- int t6;
- int t7;
- int r;
- int i;
- sad=0;
+unsigned oc_hadamard_sad(int *_dc,const ogg_int16_t _buf[64]){
+ unsigned sad;
+ int dc;
+ int t0;
+ int t1;
+ int t2;
+ int t3;
+ int t4;
+ int t5;
+ int t6;
+ int t7;
+ int r;
+ int i;
+ sad=dc=0;
for(i=0;i<8;i++){
/*Hadamard stage 1:*/
t0=_buf[i*8+0]+_buf[i*8+4];
@@ -306,7 +300,7 @@ unsigned oc_hadamard_sad_thresh(const ogg_int16_t _buf[64],unsigned _thresh){
t5+=t7;
t7=r-t7;
/*Hadamard stage 3:*/
- r=abs(t0+t1);
+ r=abs(t0+t1)&-(i>0);
r+=abs(t0-t1);
r+=abs(t2+t3);
r+=abs(t2-t3);
@@ -315,54 +309,61 @@ unsigned oc_hadamard_sad_thresh(const ogg_int16_t _buf[64],unsigned _thresh){
r+=abs(t6+t7);
r+=abs(t6-t7);
sad+=r;
- if(sad>_thresh)break;
}
+ dc=_buf[0]+_buf[1]+_buf[2]+_buf[3]+_buf[4]+_buf[5]+_buf[6]+_buf[7];
+ *_dc=dc;
return sad;
}
-unsigned oc_enc_frag_satd_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh){
- return (*_enc->opt_vtable.frag_satd_thresh)(_src,_ref,_ystride,_thresh);
-}
-
-unsigned oc_enc_frag_satd_thresh_c(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
+unsigned oc_enc_frag_satd_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
ogg_int16_t buf[64];
oc_diff_hadamard(buf,_src,_ref,_ystride);
- return oc_hadamard_sad_thresh(buf,_thresh);
-}
-
-unsigned oc_enc_frag_satd2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh){
- return (*_enc->opt_vtable.frag_satd2_thresh)(_src,_ref1,_ref2,_ystride,
- _thresh);
+ return oc_hadamard_sad(_dc,buf);
}
-unsigned oc_enc_frag_satd2_thresh_c(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
+unsigned oc_enc_frag_satd2_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
ogg_int16_t buf[64];
oc_diff_hadamard2(buf,_src,_ref1,_ref2,_ystride);
- return oc_hadamard_sad_thresh(buf,_thresh);
+ return oc_hadamard_sad(_dc,buf);
}
-unsigned oc_enc_frag_intra_satd(const oc_enc_ctx *_enc,
+unsigned oc_enc_frag_intra_satd_c(int *_dc,
const unsigned char *_src,int _ystride){
- return (*_enc->opt_vtable.frag_intra_satd)(_src,_ystride);
-}
-
-unsigned oc_enc_frag_intra_satd_c(const unsigned char *_src,int _ystride){
ogg_int16_t buf[64];
oc_intra_hadamard(buf,_src,_ystride);
- return oc_hadamard_sad_thresh(buf,UINT_MAX)
- -abs(buf[0]+buf[1]+buf[2]+buf[3]+buf[4]+buf[5]+buf[6]+buf[7]);
+ return oc_hadamard_sad(_dc,buf);
}
-void oc_enc_frag_copy2(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride){
- (*_enc->opt_vtable.frag_copy2)(_dst,_src1,_src2,_ystride);
+unsigned oc_enc_frag_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ unsigned ret;
+ int y;
+ int x;
+ ret=0;
+ for(y=0;y<8;y++){
+ for(x=0;x<8;x++)ret+=(_src[x]-_ref[x])*(_src[x]-_ref[x]);
+ _src+=_ystride;
+ _ref+=_ystride;
+ }
+ return ret;
+}
+
+unsigned oc_enc_frag_border_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask){
+ unsigned ret;
+ int y;
+ int x;
+ ret=0;
+ for(y=0;y<8;y++){
+ for(x=0;x<8;x++,_mask>>=1){
+ if(_mask&1)ret+=(_src[x]-_ref[x])*(_src[x]-_ref[x]);
+ }
+ _src+=_ystride;
+ _ref+=_ystride;
+ }
+ return ret;
}
void oc_enc_frag_copy2_c(unsigned char *_dst,
@@ -376,13 +377,3 @@ void oc_enc_frag_copy2_c(unsigned char *_dst,
_src2+=_ystride;
}
}
-
-void oc_enc_frag_recon_intra(const oc_enc_ctx *_enc,
- unsigned char *_dst,int _ystride,const ogg_int16_t _residue[64]){
- (*_enc->opt_vtable.frag_recon_intra)(_dst,_ystride,_residue);
-}
-
-void oc_enc_frag_recon_inter(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){
- (*_enc->opt_vtable.frag_recon_inter)(_dst,_src,_ystride,_residue);
-}
diff --git a/thirdparty/libtheora/encinfo.c b/thirdparty/libtheora/encinfo.c
index 83be1dae72..41db6bad45 100644
--- a/thirdparty/libtheora/encinfo.c
+++ b/thirdparty/libtheora/encinfo.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <string.h>
-#include "internal.h"
+#include "state.h"
#include "enquant.h"
#include "huffenc.h"
diff --git a/thirdparty/libtheora/encint.h b/thirdparty/libtheora/encint.h
index 97897d5a04..d25de4b8f6 100644
--- a/thirdparty/libtheora/encint.h
+++ b/thirdparty/libtheora/encint.h
@@ -11,17 +11,13 @@
********************************************************************
function:
- last mod: $Id: encint.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_encint_H)
# define _encint_H (1)
-# if defined(HAVE_CONFIG_H)
-# include "config.h"
-# endif
# include "theora/theoraenc.h"
-# include "internal.h"
-# include "ocintrin.h"
+# include "state.h"
# include "mathops.h"
# include "enquant.h"
# include "huffenc.h"
@@ -32,8 +28,13 @@
typedef oc_mv oc_mv2[2];
typedef struct oc_enc_opt_vtable oc_enc_opt_vtable;
+typedef struct oc_enc_opt_data oc_enc_opt_data;
typedef struct oc_mb_enc_info oc_mb_enc_info;
typedef struct oc_mode_scheme_chooser oc_mode_scheme_chooser;
+typedef struct oc_fr_state oc_fr_state;
+typedef struct oc_qii_state oc_qii_state;
+typedef struct oc_enc_pipeline_state oc_enc_pipeline_state;
+typedef struct oc_mode_rd oc_mode_rd;
typedef struct oc_iir_filter oc_iir_filter;
typedef struct oc_frame_metrics oc_frame_metrics;
typedef struct oc_rc_state oc_rc_state;
@@ -42,6 +43,170 @@ typedef struct oc_token_checkpoint oc_token_checkpoint;
+/*Encoder-specific accelerated functions.*/
+# if defined(OC_X86_ASM)
+# if defined(_MSC_VER)
+# include "x86_vc/x86enc.h"
+# else
+# include "x86/x86enc.h"
+# endif
+# endif
+# if defined(OC_ARM_ASM)
+# include "arm/armenc.h"
+# endif
+
+# if !defined(oc_enc_accel_init)
+# define oc_enc_accel_init oc_enc_accel_init_c
+# endif
+# if defined(OC_ENC_USE_VTABLE)
+# if !defined(oc_enc_frag_sub)
+# define oc_enc_frag_sub(_enc,_diff,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_sub)(_diff,_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_sub_128)
+# define oc_enc_frag_sub_128(_enc,_diff,_src,_ystride) \
+ ((*(_enc)->opt_vtable.frag_sub_128)(_diff,_src,_ystride))
+# endif
+# if !defined(oc_enc_frag_sad)
+# define oc_enc_frag_sad(_enc,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_sad)(_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_sad_thresh)
+# define oc_enc_frag_sad_thresh(_enc,_src,_ref,_ystride,_thresh) \
+ ((*(_enc)->opt_vtable.frag_sad_thresh)(_src,_ref,_ystride,_thresh))
+# endif
+# if !defined(oc_enc_frag_sad2_thresh)
+# define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
+ ((*(_enc)->opt_vtable.frag_sad2_thresh)(_src,_ref1,_ref2,_ystride,_thresh))
+# endif
+# if !defined(oc_enc_frag_intra_sad)
+# define oc_enc_frag_intra_sad(_enc,_src,_ystride) \
+ ((*(_enc)->opt_vtable.frag_intra_sad)(_src,_ystride))
+# endif
+# if !defined(oc_enc_frag_satd)
+# define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_satd)(_dc,_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_satd2)
+# define oc_enc_frag_satd2(_enc,_dc,_src,_ref1,_ref2,_ystride) \
+ ((*(_enc)->opt_vtable.frag_satd2)(_dc,_src,_ref1,_ref2,_ystride))
+# endif
+# if !defined(oc_enc_frag_intra_satd)
+# define oc_enc_frag_intra_satd(_enc,_dc,_src,_ystride) \
+ ((*(_enc)->opt_vtable.frag_intra_satd)(_dc,_src,_ystride))
+# endif
+# if !defined(oc_enc_frag_ssd)
+# define oc_enc_frag_ssd(_enc,_src,_ref,_ystride) \
+ ((*(_enc)->opt_vtable.frag_ssd)(_src,_ref,_ystride))
+# endif
+# if !defined(oc_enc_frag_border_ssd)
+# define oc_enc_frag_border_ssd(_enc,_src,_ref,_ystride,_mask) \
+ ((*(_enc)->opt_vtable.frag_border_ssd)(_src,_ref,_ystride,_mask))
+# endif
+# if !defined(oc_enc_frag_copy2)
+# define oc_enc_frag_copy2(_enc,_dst,_src1,_src2,_ystride) \
+ ((*(_enc)->opt_vtable.frag_copy2)(_dst,_src1,_src2,_ystride))
+# endif
+# if !defined(oc_enc_enquant_table_init)
+# define oc_enc_enquant_table_init(_enc,_enquant,_dequant) \
+ ((*(_enc)->opt_vtable.enquant_table_init)(_enquant,_dequant))
+# endif
+# if !defined(oc_enc_enquant_table_fixup)
+# define oc_enc_enquant_table_fixup(_enc,_enquant,_nqis) \
+ ((*(_enc)->opt_vtable.enquant_table_fixup)(_enquant,_nqis))
+# endif
+# if !defined(oc_enc_quantize)
+# define oc_enc_quantize(_enc,_qdct,_dct,_dequant,_enquant) \
+ ((*(_enc)->opt_vtable.quantize)(_qdct,_dct,_dequant,_enquant))
+# endif
+# if !defined(oc_enc_frag_recon_intra)
+# define oc_enc_frag_recon_intra(_enc,_dst,_ystride,_residue) \
+ ((*(_enc)->opt_vtable.frag_recon_intra)(_dst,_ystride,_residue))
+# endif
+# if !defined(oc_enc_frag_recon_inter)
+# define oc_enc_frag_recon_inter(_enc,_dst,_src,_ystride,_residue) \
+ ((*(_enc)->opt_vtable.frag_recon_inter)(_dst,_src,_ystride,_residue))
+# endif
+# if !defined(oc_enc_fdct8x8)
+# define oc_enc_fdct8x8(_enc,_y,_x) \
+ ((*(_enc)->opt_vtable.fdct8x8)(_y,_x))
+# endif
+# else
+# if !defined(oc_enc_frag_sub)
+# define oc_enc_frag_sub(_enc,_diff,_src,_ref,_ystride) \
+ oc_enc_frag_sub_c(_diff,_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_sub_128)
+# define oc_enc_frag_sub_128(_enc,_diff,_src,_ystride) \
+ oc_enc_frag_sub_128_c(_diff,_src,_ystride)
+# endif
+# if !defined(oc_enc_frag_sad)
+# define oc_enc_frag_sad(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_sad_c(_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_sad_thresh)
+# define oc_enc_frag_sad_thresh(_enc,_src,_ref,_ystride,_thresh) \
+ oc_enc_frag_sad_thresh_c(_src,_ref,_ystride,_thresh)
+# endif
+# if !defined(oc_enc_frag_sad2_thresh)
+# define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
+ oc_enc_frag_sad2_thresh_c(_src,_ref1,_ref2,_ystride,_thresh)
+# endif
+# if !defined(oc_enc_frag_intra_sad)
+# define oc_enc_frag_intra_sad(_enc,_src,_ystride) \
+ oc_enc_frag_intra_sad_c(_src,_ystride)
+# endif
+# if !defined(oc_enc_frag_satd)
+# define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
+ oc_enc_frag_satd_c(_dc,_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_satd2)
+# define oc_enc_frag_satd2(_enc,_dc,_src,_ref1,_ref2,_ystride) \
+ oc_enc_frag_satd2_c(_dc,_src,_ref1,_ref2,_ystride)
+# endif
+# if !defined(oc_enc_frag_intra_satd)
+# define oc_enc_frag_intra_satd(_enc,_dc,_src,_ystride) \
+ oc_enc_frag_intra_satd_c(_dc,_src,_ystride)
+# endif
+# if !defined(oc_enc_frag_ssd)
+# define oc_enc_frag_ssd(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_ssd_c(_src,_ref,_ystride)
+# endif
+# if !defined(oc_enc_frag_border_ssd)
+# define oc_enc_frag_border_ssd(_enc,_src,_ref,_ystride,_mask) \
+ oc_enc_frag_border_ssd_c(_src,_ref,_ystride,_mask)
+# endif
+# if !defined(oc_enc_frag_copy2)
+# define oc_enc_frag_copy2(_enc,_dst,_src1,_src2,_ystride) \
+ oc_enc_frag_copy2_c(_dst,_src1,_src2,_ystride)
+# endif
+# if !defined(oc_enc_enquant_table_init)
+# define oc_enc_enquant_table_init(_enc,_enquant,_dequant) \
+ oc_enc_enquant_table_init_c(_enquant,_dequant)
+# endif
+# if !defined(oc_enc_enquant_table_fixup)
+# define oc_enc_enquant_table_fixup(_enc,_enquant,_nqis) \
+ oc_enc_enquant_table_fixup_c(_enquant,_nqis)
+# endif
+# if !defined(oc_enc_quantize)
+# define oc_enc_quantize(_enc,_qdct,_dct,_dequant,_enquant) \
+ oc_enc_quantize_c(_qdct,_dct,_dequant,_enquant)
+# endif
+# if !defined(oc_enc_frag_recon_intra)
+# define oc_enc_frag_recon_intra(_enc,_dst,_ystride,_residue) \
+ oc_frag_recon_intra_c(_dst,_ystride,_residue)
+# endif
+# if !defined(oc_enc_frag_recon_inter)
+# define oc_enc_frag_recon_inter(_enc,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_c(_dst,_src,_ystride,_residue)
+# endif
+# if !defined(oc_enc_fdct8x8)
+# define oc_enc_fdct8x8(_enc,_y,_x) oc_enc_fdct8x8_c(_y,_x)
+# endif
+# endif
+
+
+
/*Constants for the packet-out state machine specific to the encoder.*/
/*Next packet to emit: Data packet, but none are ready yet.*/
@@ -50,13 +215,61 @@ typedef struct oc_token_checkpoint oc_token_checkpoint;
#define OC_PACKET_READY (1)
/*All features enabled.*/
-#define OC_SP_LEVEL_SLOW (0)
+#define OC_SP_LEVEL_SLOW (0)
/*Enable early skip.*/
-#define OC_SP_LEVEL_EARLY_SKIP (1)
+#define OC_SP_LEVEL_EARLY_SKIP (1)
+/*Use analysis shortcuts, single quantizer, and faster tokenization.*/
+#define OC_SP_LEVEL_FAST_ANALYSIS (2)
+/*Use SAD instead of SATD*/
+#define OC_SP_LEVEL_NOSATD (3)
/*Disable motion compensation.*/
-#define OC_SP_LEVEL_NOMC (2)
+#define OC_SP_LEVEL_NOMC (4)
/*Maximum valid speed level.*/
-#define OC_SP_LEVEL_MAX (2)
+#define OC_SP_LEVEL_MAX (4)
+
+
+/*The number of extra bits of precision at which to store rate metrics.*/
+# define OC_BIT_SCALE (6)
+/*The number of extra bits of precision at which to store RMSE metrics.
+ This must be at least half OC_BIT_SCALE (rounded up).*/
+# define OC_RMSE_SCALE (5)
+/*The number of quantizer bins to partition statistics into.*/
+# define OC_LOGQ_BINS (8)
+/*The number of SAD/SATD bins to partition statistics into.*/
+# define OC_COMP_BINS (24)
+/*The number of bits of precision to drop from SAD and SATD scores
+ to assign them to a bin.*/
+# define OC_SAD_SHIFT (6)
+# define OC_SATD_SHIFT (9)
+
+/*Masking is applied by scaling the D used in R-D optimization (via rd_scale)
+ or the lambda parameter (via rd_iscale).
+ These are only equivalent within a single block; when more than one block is
+ being considered, the former is the interpretation used.*/
+
+/*This must be at least 4 for OC_RD_SKIP_SCALE() to work below.*/
+# define OC_RD_SCALE_BITS (12-OC_BIT_SCALE)
+# define OC_RD_ISCALE_BITS (11)
+
+/*This macro is applied to _ssd values with just 4 bits of headroom
+ ((15-OC_RMSE_SCALE)*2+OC_BIT_SCALE+2); since we want to allow rd_scales as
+ large as 16, and need additional fractional bits, our only recourse that
+ doesn't lose precision on blocks with very small SSDs is to use a wider
+ multiply.*/
+# if LONG_MAX>2147483647
+# define OC_RD_SCALE(_ssd,_rd_scale) \
+ ((unsigned)((unsigned long)(_ssd)*(_rd_scale) \
+ +((1<<OC_RD_SCALE_BITS)>>1)>>OC_RD_SCALE_BITS))
+# else
+# define OC_RD_SCALE(_ssd,_rd_scale) \
+ (((_ssd)>>OC_RD_SCALE_BITS)*(_rd_scale) \
+ +(((_ssd)&(1<<OC_RD_SCALE_BITS)-1)*(_rd_scale) \
+ +((1<<OC_RD_SCALE_BITS)>>1)>>OC_RD_SCALE_BITS))
+# endif
+# define OC_RD_SKIP_SCALE(_ssd,_rd_scale) \
+ ((_ssd)*(_rd_scale)+((1<<OC_RD_SCALE_BITS-4)>>1)>>OC_RD_SCALE_BITS-4)
+# define OC_RD_ISCALE(_lambda,_rd_iscale) \
+ ((_lambda)*(_rd_iscale)+((1<<OC_RD_ISCALE_BITS)>>1)>>OC_RD_ISCALE_BITS)
/*The bits used for each of the MB mode codebooks.*/
@@ -78,6 +291,10 @@ extern const unsigned char OC_BLOCK_RUN_CODE_NBITS[30];
/*Encoder specific functions with accelerated variants.*/
struct oc_enc_opt_vtable{
+ void (*frag_sub)(ogg_int16_t _diff[64],const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+ void (*frag_sub_128)(ogg_int16_t _diff[64],
+ const unsigned char *_src,int _ystride);
unsigned (*frag_sad)(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
unsigned (*frag_sad_thresh)(const unsigned char *_src,
@@ -85,18 +302,23 @@ struct oc_enc_opt_vtable{
unsigned (*frag_sad2_thresh)(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
- unsigned (*frag_satd_thresh)(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
- unsigned (*frag_satd2_thresh)(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
- unsigned (*frag_intra_satd)(const unsigned char *_src,int _ystride);
- void (*frag_sub)(ogg_int16_t _diff[64],const unsigned char *_src,
+ unsigned (*frag_intra_sad)(const unsigned char *_src,int _ystride);
+ unsigned (*frag_satd)(int *_dc,const unsigned char *_src,
const unsigned char *_ref,int _ystride);
- void (*frag_sub_128)(ogg_int16_t _diff[64],
- const unsigned char *_src,int _ystride);
+ unsigned (*frag_satd2)(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+ unsigned (*frag_intra_satd)(int *_dc,const unsigned char *_src,int _ystride);
+ unsigned (*frag_ssd)(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+ unsigned (*frag_border_ssd)(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask);
void (*frag_copy2)(unsigned char *_dst,
const unsigned char *_src1,const unsigned char *_src2,int _ystride);
+ void (*enquant_table_init)(void *_enquant,
+ const ogg_uint16_t _dequant[64]);
+ void (*enquant_table_fixup)(void *_enquant[3][3][2],int _nqis);
+ int (*quantize)(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant);
void (*frag_recon_intra)(unsigned char *_dst,int _ystride,
const ogg_int16_t _residue[64]);
void (*frag_recon_inter)(unsigned char *_dst,
@@ -105,7 +327,19 @@ struct oc_enc_opt_vtable{
};
-void oc_enc_vtable_init(oc_enc_ctx *_enc);
+/*Encoder specific data that varies according to which variants of the above
+ functions are used.*/
+struct oc_enc_opt_data{
+ /*The size of a single quantizer table.
+ This must be a multiple of enquant_table_alignment.*/
+ size_t enquant_table_size;
+ /*The alignment required for the quantizer tables.
+ This must be a positive power of two.*/
+ int enquant_table_alignment;
+};
+
+
+void oc_enc_accel_init(oc_enc_ctx *_enc);
@@ -158,7 +392,7 @@ struct oc_mode_scheme_chooser{
corresponds to the ranks above.*/
unsigned char scheme0_list[OC_NMODES];
/*The number of times each mode has been chosen so far.*/
- int mode_counts[OC_NMODES];
+ unsigned mode_counts[OC_NMODES];
/*The list of mode coding schemes, sorted in ascending order of bit cost.*/
unsigned char scheme_list[8];
/*The number of bits used by each mode coding scheme.*/
@@ -170,6 +404,106 @@ void oc_mode_scheme_chooser_init(oc_mode_scheme_chooser *_chooser);
+/*State to track coded block flags and their bit cost.
+ We use opportunity cost to measure the bits required to code or skip the next
+ block, using the cheaper of the cost to code it fully or partially, so long
+ as both are possible.*/
+struct oc_fr_state{
+ /*The number of bits required for the coded block flags so far this frame.*/
+ ptrdiff_t bits;
+ /*The length of the current run for the partial super block flag, not
+ including the current super block.*/
+ unsigned sb_partial_count:16;
+ /*The length of the current run for the full super block flag, not
+ including the current super block.*/
+ unsigned sb_full_count:16;
+ /*The length of the coded block flag run when the current super block
+ started.*/
+ unsigned b_coded_count_prev:6;
+ /*The coded block flag when the current super block started.*/
+ signed int b_coded_prev:2;
+ /*The length of the current coded block flag run.*/
+ unsigned b_coded_count:6;
+ /*The current coded block flag.*/
+ signed int b_coded:2;
+ /*The number of blocks processed in the current super block.*/
+ unsigned b_count:5;
+ /*Whether or not it is cheaper to code the current super block partially,
+ even if it could still be coded fully.*/
+ unsigned sb_prefer_partial:1;
+ /*Whether the last super block was coded partially.*/
+ signed int sb_partial:2;
+ /*The number of bits required for the flags for the current super block.*/
+ unsigned sb_bits:6;
+ /*Whether the last non-partial super block was coded fully.*/
+ signed int sb_full:2;
+};
+
+
+
+struct oc_qii_state{
+ ptrdiff_t bits;
+ unsigned qi01_count:14;
+ signed int qi01:2;
+ unsigned qi12_count:14;
+ signed int qi12:2;
+};
+
+
+
+/*Temporary encoder state for the analysis pipeline.*/
+struct oc_enc_pipeline_state{
+ /*DCT coefficient storage.
+ This is kept off the stack because a) gcc can't align things on the stack
+ reliably on ARM, and b) it avoids (unintentional) data hazards between
+ ARM and NEON code.*/
+ OC_ALIGN16(ogg_int16_t dct_data[64*3]);
+ OC_ALIGN16(signed char bounding_values[256]);
+ oc_fr_state fr[3];
+ oc_qii_state qs[3];
+ /*Skip SSD storage for the current MCU in each plane.*/
+ unsigned *skip_ssd[3];
+ /*Coded/uncoded fragment lists for each plane for the current MCU.*/
+ ptrdiff_t *coded_fragis[3];
+ ptrdiff_t *uncoded_fragis[3];
+ ptrdiff_t ncoded_fragis[3];
+ ptrdiff_t nuncoded_fragis[3];
+ /*The starting fragment for the current MCU in each plane.*/
+ ptrdiff_t froffset[3];
+ /*The starting row for the current MCU in each plane.*/
+ int fragy0[3];
+ /*The ending row for the current MCU in each plane.*/
+ int fragy_end[3];
+ /*The starting superblock for the current MCU in each plane.*/
+ unsigned sbi0[3];
+ /*The ending superblock for the current MCU in each plane.*/
+ unsigned sbi_end[3];
+ /*The number of tokens for zzi=1 for each color plane.*/
+ int ndct_tokens1[3];
+ /*The outstanding eob_run count for zzi=1 for each color plane.*/
+ int eob_run1[3];
+ /*Whether or not the loop filter is enabled.*/
+ int loop_filter;
+};
+
+
+
+/*Statistics used to estimate R-D cost of a block in a given coding mode.
+ See modedec.h for more details.*/
+struct oc_mode_rd{
+ /*The expected bits used by the DCT tokens, shifted by OC_BIT_SCALE.*/
+ ogg_int16_t rate;
+ /*The expected square root of the sum of squared errors, shifted by
+ OC_RMSE_SCALE.*/
+ ogg_int16_t rmse;
+};
+
+# if defined(OC_COLLECT_METRICS)
+# include "collect.h"
+# endif
+
+
+
/*A 2nd order low-pass Bessel follower.
We use this for rate control because it has fast reaction time, but is
critically damped.*/
@@ -190,6 +524,8 @@ struct oc_frame_metrics{
unsigned dup_count:31;
/*The frame type from pass 1.*/
unsigned frame_type:1;
+ /*The frame activity average from pass 1.*/
+ unsigned activity_avg;
};
@@ -335,10 +671,15 @@ struct th_enc_ctx{
size_t mv_bits[2];
/*The mode scheme chooser for estimating mode coding costs.*/
oc_mode_scheme_chooser chooser;
+ /*Temporary encoder state for the analysis pipeline.*/
+ oc_enc_pipeline_state pipe;
/*The number of vertical super blocks in an MCU.*/
int mcu_nvsbs;
/*The SSD error for skipping each fragment in the current MCU.*/
unsigned *mcu_skip_ssd;
+ /*The masking scale factors for chroma blocks in the current MCU.*/
+ ogg_uint16_t *mcu_rd_scale;
+ ogg_uint16_t *mcu_rd_iscale;
/*The DCT token lists for each coefficient and each plane.*/
unsigned char **dct_tokens[3];
/*The extra bits associated with each DCT token.*/
@@ -350,8 +691,10 @@ struct th_enc_ctx{
/*The offset of the first DCT token for each coefficient for each plane.*/
unsigned char dct_token_offs[3][64];
/*The last DC coefficient for each plane and reference frame.*/
- int dc_pred_last[3][3];
+ int dc_pred_last[3][4];
#if defined(OC_COLLECT_METRICS)
+ /*Fragment SAD statistics for MB mode estimation metrics.*/
+ unsigned *frag_sad;
/*Fragment SATD statistics for MB mode estimation metrics.*/
unsigned *frag_satd;
/*Fragment SSD statistics for MB mode estimation metrics.*/
@@ -359,32 +702,56 @@ struct th_enc_ctx{
#endif
/*The R-D optimization parameter.*/
int lambda;
+ /*The average block "activity" of the previous frame.*/
+ unsigned activity_avg;
+ /*The average MB luma of the previous frame.*/
+ unsigned luma_avg;
/*The huffman tables in use.*/
th_huff_code huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
/*The quantization parameters in use.*/
th_quant_info qinfo;
- oc_iquant *enquant_tables[64][3][2];
- oc_iquant_table enquant_table_data[64][3][2];
- /*An "average" quantizer for each quantizer type (INTRA or INTER) and qi
- value.
- This is used to paramterize the rate control decisions.
+ /*The original DC coefficients saved off from the dequatization tables.*/
+ ogg_uint16_t dequant_dc[64][3][2];
+ /*Condensed dequantization tables.*/
+ const ogg_uint16_t *dequant[3][3][2];
+ /*Condensed quantization tables.*/
+ void *enquant[3][3][2];
+ /*The full set of quantization tables.*/
+ void *enquant_tables[64][3][2];
+ /*Storage for the quantization tables.*/
+ unsigned char *enquant_table_data;
+ /*An "average" quantizer for each frame type (INTRA or INTER) and qi value.
+ This is used to parameterize the rate control decisions.
They are kept in the log domain to simplify later processing.
- Keep in mind these are DCT domain quantizers, and so are scaled by an
- additional factor of 4 from the pixel domain.*/
+ These are DCT domain quantizers, and so are scaled by an additional factor
+ of 4 from the pixel domain.*/
ogg_int64_t log_qavg[2][64];
+ /*The "average" quantizer futher partitioned by color plane.
+ This is used to parameterize mode decision.
+ These are DCT domain quantizers, and so are scaled by an additional factor
+ of 4 from the pixel domain.*/
+ ogg_int16_t log_plq[64][3][2];
+ /*The R-D scale factors to apply to chroma blocks for a given frame type
+ (INTRA or INTER) and qi value.
+ The first is the "D" modifier (rd_scale), while the second is the "lambda"
+ modifier (rd_iscale).*/
+ ogg_uint16_t chroma_rd_scale[2][64][2];
+ /*The interpolated mode decision R-D lookup tables for the current
+ quantizers, color plane, and quantization type.*/
+ oc_mode_rd mode_rd[3][3][2][OC_COMP_BINS];
/*The buffer state used to drive rate control.*/
oc_rc_state rc;
+# if defined(OC_ENC_USE_VTABLE)
/*Table for encoder acceleration functions.*/
oc_enc_opt_vtable opt_vtable;
+# endif
+ /*Table for encoder data used by accelerated functions.*/
+ oc_enc_opt_data opt_data;
};
void oc_enc_analyze_intra(oc_enc_ctx *_enc,int _recode);
int oc_enc_analyze_inter(oc_enc_ctx *_enc,int _allow_keyframe,int _recode);
-#if defined(OC_COLLECT_METRICS)
-void oc_enc_mode_metrics_collect(oc_enc_ctx *_enc);
-void oc_enc_mode_metrics_dump(oc_enc_ctx *_enc);
-#endif
@@ -415,8 +782,13 @@ struct oc_token_checkpoint{
void oc_enc_tokenize_start(oc_enc_ctx *_enc);
int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
- ogg_int16_t *_qdct,const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
- int _zzi,oc_token_checkpoint **_stack,int _acmin);
+ ogg_int16_t *_qdct_out,const ogg_int16_t *_qdct_in,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin);
+int oc_enc_tokenize_ac_fast(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
+ ogg_int16_t *_qdct_out,const ogg_int16_t *_qdct_in,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin);
void oc_enc_tokenlog_rollback(oc_enc_ctx *_enc,
const oc_token_checkpoint *_stack,int _n);
void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
@@ -436,45 +808,13 @@ int oc_state_flushheader(oc_theora_state *_state,int *_packet_state,
-/*Encoder-specific accelerated functions.*/
-void oc_enc_frag_sub(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,const unsigned char *_ref,int _ystride);
-void oc_enc_frag_sub_128(const oc_enc_ctx *_enc,ogg_int16_t _diff[64],
- const unsigned char *_src,int _ystride);
-unsigned oc_enc_frag_sad(const oc_enc_ctx *_enc,const unsigned char *_src,
- const unsigned char *_ref,int _ystride);
-unsigned oc_enc_frag_sad_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_sad2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh(const oc_enc_ctx *_enc,
- const unsigned char *_src,const unsigned char *_ref1,
- const unsigned char *_ref2,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_intra_satd(const oc_enc_ctx *_enc,
- const unsigned char *_src,int _ystride);
-void oc_enc_frag_copy2(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride);
-void oc_enc_frag_recon_intra(const oc_enc_ctx *_enc,
- unsigned char *_dst,int _ystride,const ogg_int16_t _residue[64]);
-void oc_enc_frag_recon_inter(const oc_enc_ctx *_enc,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
-void oc_enc_fdct8x8(const oc_enc_ctx *_enc,ogg_int16_t _y[64],
- const ogg_int16_t _x[64]);
-
-/*Default pure-C implementations.*/
-void oc_enc_vtable_init_c(oc_enc_ctx *_enc);
+/*Default pure-C implementations of encoder-specific accelerated functions.*/
+void oc_enc_accel_init_c(oc_enc_ctx *_enc);
void oc_enc_frag_sub_c(ogg_int16_t _diff[64],
const unsigned char *_src,const unsigned char *_ref,int _ystride);
void oc_enc_frag_sub_128_c(ogg_int16_t _diff[64],
const unsigned char *_src,int _ystride);
-void oc_enc_frag_copy2_c(unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride);
unsigned oc_enc_frag_sad_c(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
@@ -482,12 +822,24 @@ unsigned oc_enc_frag_sad_thresh_c(const unsigned char *_src,
unsigned oc_enc_frag_sad2_thresh_c(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh_c(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh_c(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_intra_satd_c(const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_intra_sad_c(const unsigned char *_src, int _ystride);
+unsigned oc_enc_frag_satd_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd2_c(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_intra_satd_c(int *_dc,
+ const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_border_ssd_c(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask);
+void oc_enc_frag_copy2_c(unsigned char *_dst,
+ const unsigned char *_src1,const unsigned char *_src2,int _ystride);
+void oc_enc_enquant_table_init_c(void *_enquant,
+ const ogg_uint16_t _dequant[64]);
+void oc_enc_enquant_table_fixup_c(void *_enquant[3][3][2],int _nqis);
+int oc_enc_quantize_c(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant);
void oc_enc_fdct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
#endif
diff --git a/thirdparty/libtheora/encode.c b/thirdparty/libtheora/encode.c
index 0c5ea6a172..3309f97c03 100644
--- a/thirdparty/libtheora/encode.c
+++ b/thirdparty/libtheora/encode.c
@@ -11,15 +11,13 @@
********************************************************************
function:
- last mod: $Id: encode.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
#include <string.h>
#include "encint.h"
-#if defined(OC_X86_ASM)
-# include "x86/x86enc.h"
-#endif
+#include "dequant.h"
@@ -288,12 +286,12 @@ const th_quant_info TH_DEF_QUANT_INFO={
28, 25, 24, 22, 20, 17, 14, 10
},
{
- 30,25,20,20,15,15,14,14,
- 13,13,12,12,11,11,10,10,
- 9, 9, 8, 8, 7, 7, 7, 7,
- 6, 6, 6, 6, 5, 5, 5, 5,
- 4, 4, 4, 4, 3, 3, 3, 3,
+ 15,12, 9, 8, 6, 6, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 4, 4, 4, 4, 4, 4, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
},
@@ -623,11 +621,15 @@ static void oc_enc_mb_modes_pack(oc_enc_ctx *_enc){
}
}
-static void oc_enc_mv_pack(oc_enc_ctx *_enc,int _mv_scheme,int _dx,int _dy){
+static void oc_enc_mv_pack(oc_enc_ctx *_enc,int _mv_scheme,oc_mv _mv){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_mv);
+ dy=OC_MV_Y(_mv);
oggpackB_write(&_enc->opb,
- OC_MV_CODES[_mv_scheme][_dx+31],OC_MV_BITS[_mv_scheme][_dx+31]);
+ OC_MV_CODES[_mv_scheme][dx+31],OC_MV_BITS[_mv_scheme][dx+31]);
oggpackB_write(&_enc->opb,
- OC_MV_CODES[_mv_scheme][_dy+31],OC_MV_BITS[_mv_scheme][_dy+31]);
+ OC_MV_CODES[_mv_scheme][dy+31],OC_MV_BITS[_mv_scheme][dy+31]);
}
static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
@@ -650,7 +652,7 @@ static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
mb_modes=_enc->state.mb_modes;
mb_maps=(const oc_mb_map *)_enc->state.mb_maps;
frags=_enc->state.frags;
- frag_mvs=(const oc_mv *)_enc->state.frag_mvs;
+ frag_mvs=_enc->state.frag_mvs;
for(mbii=0;mbii<ncoded_mbis;mbii++){
ptrdiff_t fragi;
unsigned mbi;
@@ -662,8 +664,7 @@ static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
for(bi=0;;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- oc_enc_mv_pack(_enc,mv_scheme,
- frag_mvs[fragi][0],frag_mvs[fragi][1]);
+ oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]);
/*Only code a single MV for this macro block.*/
break;
}
@@ -673,8 +674,7 @@ static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
for(bi=0;bi<4;bi++){
fragi=mb_maps[mbi][0][bi];
if(frags[fragi].coded){
- oc_enc_mv_pack(_enc,mv_scheme,
- frag_mvs[fragi][0],frag_mvs[fragi][1]);
+ oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]);
/*Keep coding all the MVs for this macro block.*/
}
}
@@ -863,11 +863,55 @@ static void oc_enc_residual_tokens_pack(oc_enc_ctx *_enc){
}
}
+/*Packs an explicit drop frame, instead of using the more efficient 0-byte
+ packet.
+ This is only enabled in VP3-compatibility mode, even though it is not
+ strictly required for VP3 compatibility (VP3 could be encoded in AVI, which
+ also supports dropping frames by inserting 0 byte packets).
+ However, almost every _Theora_ player used to get this wrong (and many still
+ do), and it wasn't until we started shipping a post-VP3 encoder that
+ actually used non-VP3 features that this began to be discovered and fixed,
+ despite being in the standard since 2004.
+ The pack buffer must be reset before calling this function.*/
+static void oc_enc_drop_frame_pack(oc_enc_ctx *_enc){
+ unsigned nsbs;
+ /*Mark this as a data packet.*/
+ oggpackB_write(&_enc->opb,0,1);
+ /*Output the frame type (key frame or delta frame).*/
+ oggpackB_write(&_enc->opb,OC_INTER_FRAME,1);
+ /*Write out the current qi list.
+ We always use just 1 qi, to avoid wasting bits on the others.*/
+ oggpackB_write(&_enc->opb,_enc->state.qis[0],6);
+ oggpackB_write(&_enc->opb,0,1);
+ /*Coded block flags: everything is uncoded.*/
+ nsbs=_enc->state.nsbs;
+ /*No partially coded SBs.*/
+ oggpackB_write(&_enc->opb,0,1);
+ oc_sb_run_pack(&_enc->opb,nsbs,0,1);
+ /*No fully coded SBs.*/
+ oggpackB_write(&_enc->opb,0,1);
+ oc_sb_run_pack(&_enc->opb,nsbs,0,1);
+ /*MB modes: just need write which scheme to use.
+ Since we have no coded MBs, we can pick any of them except 0, which would
+ require writing out an additional mode list.*/
+ oggpackB_write(&_enc->opb,7,3);
+ /*MVs: just need write which scheme to use.
+ We can pick either one, since we have no MVs.*/
+ oggpackB_write(&_enc->opb,1,1);
+ /*Write the chosen DC token tables.*/
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][0],4);
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][1],4);
+ /*Write the chosen AC token tables.*/
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][0],4);
+ oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][1],4);
+}
+
static void oc_enc_frame_pack(oc_enc_ctx *_enc){
+ /*musl libc malloc()/realloc() calls might use floating point, so make sure
+ we've cleared the MMX state for them.*/
+ oc_restore_fpu(&_enc->state);
oggpackB_reset(&_enc->opb);
- /*Only proceed if we have some coded blocks.
- If there are no coded blocks, we can drop this frame simply by emitting a
- 0 byte packet.*/
+ /*Only proceed if we have some coded blocks.*/
if(_enc->state.ntotal_coded_fragis>0){
oc_enc_frame_header_pack(_enc);
if(_enc->state.frame_type==OC_INTER_FRAME){
@@ -880,6 +924,10 @@ static void oc_enc_frame_pack(oc_enc_ctx *_enc){
oc_enc_tokenize_finish(_enc);
oc_enc_residual_tokens_pack(_enc);
}
+ /*If there are no coded blocks, we can drop this frame simply by emitting a
+ 0 byte packet.
+ We emit an inter frame with no coded blocks in VP3-compatibility mode.*/
+ else if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc);
/*Success: Mark the packet as ready to be flushed.*/
_enc->packet_state=OC_PACKET_READY;
#if defined(OC_COLLECT_METRICS)
@@ -888,21 +936,31 @@ static void oc_enc_frame_pack(oc_enc_ctx *_enc){
}
-void oc_enc_vtable_init_c(oc_enc_ctx *_enc){
+void oc_enc_accel_init_c(oc_enc_ctx *_enc){
/*The implementations prefixed with oc_enc_ are encoder-specific.
The rest we re-use from the decoder.*/
+# if defined(OC_ENC_USE_VTABLE)
+ _enc->opt_vtable.frag_sub=oc_enc_frag_sub_c;
+ _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_c;
_enc->opt_vtable.frag_sad=oc_enc_frag_sad_c;
_enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_c;
_enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_c;
- _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_c;
- _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_c;
+ _enc->opt_vtable.frag_intra_sad=oc_enc_frag_intra_sad_c;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_c;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_c;
_enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_c;
- _enc->opt_vtable.frag_sub=oc_enc_frag_sub_c;
- _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_c;
+ _enc->opt_vtable.frag_ssd=oc_enc_frag_ssd_c;
+ _enc->opt_vtable.frag_border_ssd=oc_enc_frag_border_ssd_c;
_enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_c;
+ _enc->opt_vtable.enquant_table_init=oc_enc_enquant_table_init_c;
+ _enc->opt_vtable.enquant_table_fixup=oc_enc_enquant_table_fixup_c;
+ _enc->opt_vtable.quantize=oc_enc_quantize_c;
_enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c;
_enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c;
_enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_c;
+# endif
+ _enc->opt_data.enquant_table_size=64*sizeof(oc_iquant);
+ _enc->opt_data.enquant_table_alignment=16;
}
/*Initialize the macro block neighbor lists for MC analysis.
@@ -1003,6 +1061,55 @@ static int oc_enc_set_huffman_codes(oc_enc_ctx *_enc,
return 0;
}
+static void oc_enc_enquant_tables_init(oc_enc_ctx *_enc,
+ const th_quant_info *_qinfo){
+ unsigned char *etd;
+ size_t ets;
+ int align;
+ int qii;
+ int qi;
+ int pli;
+ int qti;
+ for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ _enc->state.dequant_tables[qi][pli][qti]=
+ _enc->state.dequant_table_data[qi][pli][qti];
+ }
+ /*Initialize the dequantization tables.*/
+ oc_dequant_tables_init(_enc->state.dequant_tables,NULL,_qinfo);
+ /*And save off the DC values.*/
+ for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ _enc->dequant_dc[qi][pli][qti]=_enc->state.dequant_tables[qi][pli][qti][0];
+ }
+ /*Set up storage for the quantization tables.*/
+ etd=_enc->enquant_table_data;
+ ets=_enc->opt_data.enquant_table_size;
+ align=-(etd-(unsigned char *)0)&_enc->opt_data.enquant_table_alignment-1;
+ etd+=align;
+ /*Set up the main tables.*/
+ for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
+ _enc->enquant_tables[qi][pli][qti]=etd;
+ oc_enc_enquant_table_init(_enc,etd,
+ _enc->state.dequant_tables[qi][pli][qti]);
+ etd+=ets;
+ }
+ /*Set up storage for the local copies we modify for each frame.*/
+ for(pli=0;pli<3;pli++)for(qii=0;qii<3;qii++)for(qti=0;qti<2;qti++){
+ _enc->enquant[pli][qii][qti]=etd;
+ etd+=ets;
+ }
+}
+
+/*Updates the encoder state after the quantization parameters have been
+ changed.*/
+static void oc_enc_quant_params_updated(oc_enc_ctx *_enc,
+ const th_quant_info *_qinfo){
+ oc_enc_enquant_tables_init(_enc,_qinfo);
+ memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits,
+ sizeof(_enc->state.loop_filter_limits));
+ oc_enquant_qavg_init(_enc->log_qavg,_enc->log_plq,_enc->chroma_rd_scale,
+ _enc->state.dequant_tables,_enc->state.info.pixel_fmt);
+}
+
/*Sets the quantization parameters to use.
This may only be called before the setup header is written.
If it is called multiple times, only the last call has any effect.
@@ -1012,25 +1119,20 @@ static int oc_enc_set_huffman_codes(oc_enc_ctx *_enc,
will be used.*/
static int oc_enc_set_quant_params(oc_enc_ctx *_enc,
const th_quant_info *_qinfo){
- int qi;
- int pli;
- int qti;
+ th_quant_info old_qinfo;
+ int ret;
if(_enc==NULL)return TH_EFAULT;
if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
if(_qinfo==NULL)_qinfo=&TH_DEF_QUANT_INFO;
- /*TODO: Analyze for packing purposes instead of just doing a shallow copy.*/
- memcpy(&_enc->qinfo,_qinfo,sizeof(_enc->qinfo));
- for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
- _enc->state.dequant_tables[qi][pli][qti]=
- _enc->state.dequant_table_data[qi][pli][qti];
- _enc->enquant_tables[qi][pli][qti]=_enc->enquant_table_data[qi][pli][qti];
+ memcpy(&old_qinfo,&_enc->qinfo,sizeof(old_qinfo));
+ ret=oc_quant_params_clone(&_enc->qinfo,_qinfo);
+ if(ret<0){
+ oc_quant_params_clear(&_enc->qinfo);
+ memcpy(&_enc->qinfo,&old_qinfo,sizeof(old_qinfo));
+ return ret;
}
- oc_enquant_tables_init(_enc->state.dequant_tables,
- _enc->enquant_tables,_qinfo);
- memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits,
- sizeof(_enc->state.loop_filter_limits));
- oc_enquant_qavg_init(_enc->log_qavg,_enc->state.dequant_tables,
- _enc->state.info.pixel_fmt);
+ else oc_quant_params_clear(&old_qinfo);
+ oc_enc_quant_params_updated(_enc,_qinfo);
return 0;
}
@@ -1039,6 +1141,7 @@ static void oc_enc_clear(oc_enc_ctx *_enc);
static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
th_info info;
size_t mcu_nmbs;
+ ptrdiff_t mcu_ncfrags;
ptrdiff_t mcu_nfrags;
int hdec;
int vdec;
@@ -1053,8 +1156,9 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
if(info.quality<0)info.quality=32;
if(info.target_bitrate<0)info.target_bitrate=0;
/*Initialize the shared encoder/decoder state.*/
- ret=oc_state_init(&_enc->state,&info,4);
+ ret=oc_state_init(&_enc->state,&info,6);
if(ret<0)return ret;
+ oc_enc_accel_init(_enc);
_enc->mb_info=_ogg_calloc(_enc->state.nmbs,sizeof(*_enc->mb_info));
_enc->frag_dc=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_dc));
_enc->coded_mbis=
@@ -1065,9 +1169,14 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
super block rows of Y' for each super block row of Cb and Cr.*/
_enc->mcu_nvsbs=1<<vdec;
mcu_nmbs=_enc->mcu_nvsbs*_enc->state.fplanes[0].nhsbs*(size_t)4;
- mcu_nfrags=4*mcu_nmbs+(8*mcu_nmbs>>hdec+vdec);
+ mcu_ncfrags=mcu_nmbs<<3-(hdec+vdec);
+ mcu_nfrags=4*mcu_nmbs+mcu_ncfrags;
_enc->mcu_skip_ssd=(unsigned *)_ogg_malloc(
mcu_nfrags*sizeof(*_enc->mcu_skip_ssd));
+ _enc->mcu_rd_scale=(ogg_uint16_t *)_ogg_malloc(
+ (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_scale));
+ _enc->mcu_rd_iscale=(ogg_uint16_t *)_ogg_malloc(
+ (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_iscale));
for(pli=0;pli<3;pli++){
_enc->dct_tokens[pli]=(unsigned char **)oc_malloc_2d(64,
_enc->state.fplanes[pli].nfrags,sizeof(**_enc->dct_tokens));
@@ -1075,34 +1184,22 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
_enc->state.fplanes[pli].nfrags,sizeof(**_enc->extra_bits));
}
#if defined(OC_COLLECT_METRICS)
+ _enc->frag_sad=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_sad));
_enc->frag_satd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_satd));
_enc->frag_ssd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_ssd));
#endif
-#if defined(OC_X86_ASM)
- oc_enc_vtable_init_x86(_enc);
-#else
- oc_enc_vtable_init_c(_enc);
-#endif
+ _enc->enquant_table_data=(unsigned char *)_ogg_malloc(
+ (64+3)*3*2*_enc->opt_data.enquant_table_size
+ +_enc->opt_data.enquant_table_alignment-1);
_enc->keyframe_frequency_force=1<<_enc->state.info.keyframe_granule_shift;
_enc->state.qis[0]=_enc->state.info.quality;
_enc->state.nqis=1;
+ _enc->activity_avg=90<<12;
+ _enc->luma_avg=128<<8;
oc_rc_state_init(&_enc->rc,_enc);
oggpackB_writeinit(&_enc->opb);
- if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL||
- _enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL||
- _enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL||
- _enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL||
- _enc->extra_bits[2]==NULL
-#if defined(OC_COLLECT_METRICS)
- ||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
-#endif
- ){
- oc_enc_clear(_enc);
- return TH_EFAULT;
- }
- oc_mode_scheme_chooser_init(&_enc->chooser);
- oc_enc_mb_info_init(_enc);
- memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs));
+ memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes));
+ memset(_enc->qinfo.qi_ranges,0,sizeof(_enc->qinfo.qi_ranges));
/*Reset the packet-out state machine.*/
_enc->packet_state=OC_PACKET_INFO_HDR;
_enc->dup_count=0;
@@ -1114,26 +1211,45 @@ static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
_enc->vp3_compatible=0;
/*No INTER frames coded yet.*/
_enc->coded_inter_frame=0;
- memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes));
- oc_enc_set_quant_params(_enc,NULL);
+ if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL
+ ||_enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL
+ ||_enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL
+ ||_enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL
+ ||_enc->extra_bits[2]==NULL
+#if defined(OC_COLLECT_METRICS)
+ ||_enc->frag_sad==NULL||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
+#endif
+ ||oc_enc_set_quant_params(_enc,NULL)<0){
+ oc_enc_clear(_enc);
+ return TH_EFAULT;
+ }
+ oc_mode_scheme_chooser_init(&_enc->chooser);
+ oc_enc_mb_info_init(_enc);
+ memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs));
return 0;
}
static void oc_enc_clear(oc_enc_ctx *_enc){
int pli;
oc_rc_state_clear(&_enc->rc);
-#if defined(OC_COLLECT_METRICS)
- oc_enc_mode_metrics_dump(_enc);
-#endif
oggpackB_writeclear(&_enc->opb);
+ oc_quant_params_clear(&_enc->qinfo);
+ _ogg_free(_enc->enquant_table_data);
#if defined(OC_COLLECT_METRICS)
+ /*Save the collected metrics from this run.
+ Use tools/process_modedec_stats to actually generate modedec.h from the
+ resulting file.*/
+ oc_mode_metrics_dump();
_ogg_free(_enc->frag_ssd);
_ogg_free(_enc->frag_satd);
+ _ogg_free(_enc->frag_sad);
#endif
for(pli=3;pli-->0;){
oc_free_2d(_enc->extra_bits[pli]);
oc_free_2d(_enc->dct_tokens[pli]);
}
+ _ogg_free(_enc->mcu_rd_iscale);
+ _ogg_free(_enc->mcu_rd_scale);
_ogg_free(_enc->mcu_skip_ssd);
_ogg_free(_enc->coded_mbis);
_ogg_free(_enc->frag_dc);
@@ -1145,10 +1261,14 @@ static void oc_enc_drop_frame(th_enc_ctx *_enc){
/*Use the previous frame's reconstruction.*/
_enc->state.ref_frame_idx[OC_FRAME_SELF]=
_enc->state.ref_frame_idx[OC_FRAME_PREV];
+ _enc->state.ref_frame_data[OC_FRAME_SELF]=
+ _enc->state.ref_frame_data[OC_FRAME_PREV];
/*Flag motion vector analysis about the frame drop.*/
_enc->prevframe_dropped=1;
/*Zero the packet.*/
oggpackB_reset(&_enc->opb);
+ /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/
+ if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc);
}
static void oc_enc_compress_keyframe(oc_enc_ctx *_enc,int _recode){
@@ -1222,9 +1342,9 @@ static void oc_enc_set_granpos(oc_enc_ctx *_enc){
th_enc_ctx *th_encode_alloc(const th_info *_info){
oc_enc_ctx *enc;
if(_info==NULL)return NULL;
- enc=_ogg_malloc(sizeof(*enc));
+ enc=oc_aligned_malloc(sizeof(*enc),16);
if(enc==NULL||oc_enc_init(enc,_info)<0){
- _ogg_free(enc);
+ oc_aligned_free(enc);
return NULL;
}
return enc;
@@ -1233,7 +1353,7 @@ th_enc_ctx *th_encode_alloc(const th_info *_info){
void th_encode_free(th_enc_ctx *_enc){
if(_enc!=NULL){
oc_enc_clear(_enc);
- _ogg_free(_enc);
+ oc_aligned_free(_enc);
}
}
@@ -1272,12 +1392,17 @@ int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){
}break;
case TH_ENCCTL_SET_VP3_COMPATIBLE:{
int vp3_compatible;
+ int ret;
if(_enc==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(vp3_compatible))return TH_EINVAL;
+ /*Try this before we change anything else, because it can fail.*/
+ ret=oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO);
+ /*If we can't allocate enough memory, don't change any of the state.*/
+ if(ret==TH_EFAULT)return ret;
vp3_compatible=*(int *)_buf;
_enc->vp3_compatible=vp3_compatible;
if(oc_enc_set_huffman_codes(_enc,TH_VP31_HUFF_CODES)<0)vp3_compatible=0;
- if(oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO)<0)vp3_compatible=0;
+ if(ret<0)vp3_compatible=0;
if(_enc->state.info.pixel_fmt!=TH_PF_420||
_enc->state.info.pic_width<_enc->state.info.frame_width||
_enc->state.info.pic_height<_enc->state.info.frame_height||
@@ -1386,6 +1511,44 @@ int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){
}
return oc_enc_rc_2pass_in(_enc,_buf,_buf_sz);
}break;
+ case TH_ENCCTL_SET_COMPAT_CONFIG:{
+ unsigned char buf[7];
+ oc_pack_buf opb;
+ th_quant_info qinfo;
+ th_huff_code huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
+ int ret;
+ int i;
+ if(_enc==NULL||_buf==NULL)return TH_EFAULT;
+ if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
+ oc_pack_readinit(&opb,_buf,_buf_sz);
+ /*Validate the setup packet header.*/
+ for(i=0;i<7;i++)buf[i]=(unsigned char)oc_pack_read(&opb,8);
+ if(!(buf[0]&0x80)||memcmp(buf+1,"theora",6)!=0)return TH_ENOTFORMAT;
+ if(buf[0]!=0x82)return TH_EBADHEADER;
+ /*Reads its contents.*/
+ ret=oc_quant_params_unpack(&opb,&qinfo);
+ if(ret<0){
+ oc_quant_params_clear(&qinfo);
+ return ret;
+ }
+ ret=oc_huff_codes_unpack(&opb,huff_codes);
+ if(ret<0){
+ oc_quant_params_clear(&qinfo);
+ return ret;
+ }
+ /*Install the new state.*/
+ oc_quant_params_clear(&_enc->qinfo);
+ memcpy(&_enc->qinfo,&qinfo,sizeof(qinfo));
+ oc_enc_quant_params_updated(_enc,&qinfo);
+ memcpy(_enc->huff_codes,huff_codes,sizeof(_enc->huff_codes));
+ return 0;
+ }
+#if defined(OC_COLLECT_METRICS)
+ case TH_ENCCTL_SET_METRICS_FILE:{
+ OC_MODE_METRICS_FILENAME=(const char *)_buf;
+ return 0;
+ }
+#endif
default:return TH_EIMPL;
}
}
@@ -1477,6 +1640,12 @@ static void oc_img_plane_copy_pad(th_img_plane *_dst,th_img_plane *_src,
int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
th_ycbcr_buffer img;
+ int frame_width;
+ int frame_height;
+ int pic_width;
+ int pic_height;
+ int pic_x;
+ int pic_y;
int cframe_width;
int cframe_height;
int cpic_width;
@@ -1492,53 +1661,94 @@ int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
if(_enc==NULL||_img==NULL)return TH_EFAULT;
if(_enc->packet_state==OC_PACKET_DONE)return TH_EINVAL;
if(_enc->rc.twopass&&_enc->rc.twopass_buffer_bytes==0)return TH_EINVAL;
- if((ogg_uint32_t)_img[0].width!=_enc->state.info.frame_width||
- (ogg_uint32_t)_img[0].height!=_enc->state.info.frame_height){
- return TH_EINVAL;
- }
hdec=!(_enc->state.info.pixel_fmt&1);
vdec=!(_enc->state.info.pixel_fmt&2);
- cframe_width=_enc->state.info.frame_width>>hdec;
- cframe_height=_enc->state.info.frame_height>>vdec;
- if(_img[1].width!=cframe_width||_img[2].width!=cframe_width||
- _img[1].height!=cframe_height||_img[2].height!=cframe_height){
- return TH_EINVAL;
- }
- /*Step 2: Copy the input to our internal buffer.
- This lets us add padding, if necessary, so we don't have to worry about
- dereferencing possibly invalid addresses, and allows us to use the same
- strides and fragment offsets for both the input frame and the reference
- frames.*/
+ frame_width=_enc->state.info.frame_width;
+ frame_height=_enc->state.info.frame_height;
+ pic_x=_enc->state.info.pic_x;
+ pic_y=_enc->state.info.pic_y;
+ pic_width=_enc->state.info.pic_width;
+ pic_height=_enc->state.info.pic_height;
+ cframe_width=frame_width>>hdec;
+ cframe_height=frame_height>>vdec;
+ cpic_x=pic_x>>hdec;
+ cpic_y=pic_y>>vdec;
+ cpic_width=(pic_x+pic_width+hdec>>hdec)-cpic_x;
+ cpic_height=(pic_y+pic_height+vdec>>vdec)-cpic_y;
/*Flip the input buffer upside down.*/
oc_ycbcr_buffer_flip(img,_img);
- oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+0,img+0,
- _enc->state.info.pic_x,_enc->state.info.pic_y,
- _enc->state.info.pic_width,_enc->state.info.pic_height);
- cpic_x=_enc->state.info.pic_x>>hdec;
- cpic_y=_enc->state.info.pic_y>>vdec;
- cpic_width=(_enc->state.info.pic_x+_enc->state.info.pic_width+hdec>>hdec)
- -cpic_x;
- cpic_height=(_enc->state.info.pic_y+_enc->state.info.pic_height+vdec>>vdec)
- -cpic_y;
- for(pli=1;pli<3;pli++){
- oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[OC_FRAME_IO]+pli,img+pli,
- cpic_x,cpic_y,cpic_width,cpic_height);
+ if(img[0].width!=frame_width||img[0].height!=frame_height||
+ img[1].width!=cframe_width||img[2].width!=cframe_width||
+ img[1].height!=cframe_height||img[2].height!=cframe_height){
+ /*The buffer does not match the frame size.
+ Check to see if it matches the picture size.*/
+ if(img[0].width!=pic_width||img[0].height!=pic_height||
+ img[1].width!=cpic_width||img[2].width!=cpic_width||
+ img[1].height!=cpic_height||img[2].height!=cpic_height){
+ /*It doesn't; we don't know how to handle it.*/
+ return TH_EINVAL;
+ }
+ /*Adjust the pointers to address a full frame.
+ We still only use the picture region, however.*/
+ img[0].data-=pic_y*(ptrdiff_t)img[0].stride+pic_x;
+ img[1].data-=cpic_y*(ptrdiff_t)img[1].stride+cpic_x;
+ img[2].data-=cpic_y*(ptrdiff_t)img[2].stride+cpic_x;
}
- /*Step 3: Update the buffer state.*/
+ /*Step 2: Update the buffer state.*/
if(_enc->state.ref_frame_idx[OC_FRAME_SELF]>=0){
_enc->state.ref_frame_idx[OC_FRAME_PREV]=
_enc->state.ref_frame_idx[OC_FRAME_SELF];
+ _enc->state.ref_frame_data[OC_FRAME_PREV]=
+ _enc->state.ref_frame_data[OC_FRAME_SELF];
if(_enc->state.frame_type==OC_INTRA_FRAME){
/*The new frame becomes both the previous and gold reference frames.*/
_enc->state.keyframe_num=_enc->state.curframe_num;
_enc->state.ref_frame_idx[OC_FRAME_GOLD]=
_enc->state.ref_frame_idx[OC_FRAME_SELF];
+ _enc->state.ref_frame_data[OC_FRAME_GOLD]=
+ _enc->state.ref_frame_data[OC_FRAME_SELF];
+ }
+ }
+ if(_enc->state.ref_frame_idx[OC_FRAME_IO]>=0&&_enc->prevframe_dropped==0){
+ _enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG]=
+ _enc->state.ref_frame_idx[OC_FRAME_IO];
+ _enc->state.ref_frame_data[OC_FRAME_PREV_ORIG]=
+ _enc->state.ref_frame_data[OC_FRAME_IO];
+ if(_enc->state.frame_type==OC_INTRA_FRAME){
+ /*The new input frame becomes both the previous and gold
+ original-reference frames.*/
+ _enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]=
+ _enc->state.ref_frame_idx[OC_FRAME_IO];
+ _enc->state.ref_frame_data[OC_FRAME_GOLD_ORIG]=
+ _enc->state.ref_frame_data[OC_FRAME_IO];
}
}
+ /*Select a free buffer to use for the incoming frame*/
+ for(refi=3;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]||
+ refi==_enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG];refi++);
+ _enc->state.ref_frame_idx[OC_FRAME_IO]=refi;
+ _enc->state.ref_frame_data[OC_FRAME_IO]=
+ _enc->state.ref_frame_bufs[refi][0].data;
+ /*Step 3: Copy the input to our internal buffer.
+ This lets us add padding, so we don't have to worry about dereferencing
+ possibly invalid addresses, and allows us to use the same strides and
+ fragment offsets for both the input frame and the reference frames.*/
+ oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+0,img+0,
+ pic_x,pic_y,pic_width,pic_height);
+ oc_state_borders_fill_rows(&_enc->state,refi,0,0,frame_height);
+ oc_state_borders_fill_caps(&_enc->state,refi,0);
+ for(pli=1;pli<3;pli++){
+ oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+pli,img+pli,
+ cpic_x,cpic_y,cpic_width,cpic_height);
+ oc_state_borders_fill_rows(&_enc->state,refi,pli,0,cframe_height);
+ oc_state_borders_fill_caps(&_enc->state,refi,pli);
+ }
/*Select a free buffer to use for the reconstructed version of this frame.*/
for(refi=0;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD]||
refi==_enc->state.ref_frame_idx[OC_FRAME_PREV];refi++);
_enc->state.ref_frame_idx[OC_FRAME_SELF]=refi;
+ _enc->state.ref_frame_data[OC_FRAME_SELF]=
+ _enc->state.ref_frame_bufs[refi][0].data;
_enc->state.curframe_num+=_enc->prev_dup_count+1;
/*Step 4: Compress the frame.*/
/*Start with a keyframe, and don't allow the generation of invalid files that
@@ -1575,11 +1785,11 @@ int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
}
int th_encode_packetout(th_enc_ctx *_enc,int _last_p,ogg_packet *_op){
+ unsigned char *packet;
if(_enc==NULL||_op==NULL)return TH_EFAULT;
if(_enc->packet_state==OC_PACKET_READY){
_enc->packet_state=OC_PACKET_EMPTY;
if(_enc->rc.twopass!=1){
- unsigned char *packet;
packet=oggpackB_get_buffer(&_enc->opb);
/*If there's no packet, malloc failed while writing; it's lost forever.*/
if(packet==NULL)return TH_EFAULT;
@@ -1595,8 +1805,22 @@ int th_encode_packetout(th_enc_ctx *_enc,int _last_p,ogg_packet *_op){
else if(_enc->packet_state==OC_PACKET_EMPTY){
if(_enc->nqueued_dups>0){
_enc->nqueued_dups--;
- _op->packet=NULL;
- _op->bytes=0;
+ /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/
+ if(_enc->vp3_compatible){
+ oggpackB_reset(&_enc->opb);
+ oc_enc_drop_frame_pack(_enc);
+ packet=oggpackB_get_buffer(&_enc->opb);
+ /*If there's no packet, malloc failed while writing; it's lost
+ forever.*/
+ if(packet==NULL)return TH_EFAULT;
+ _op->packet=packet;
+ _op->bytes=oggpackB_bytes(&_enc->opb);
+ }
+ /*Otherwise emit a 0-byte packet.*/
+ else{
+ _op->packet=NULL;
+ _op->bytes=0;
+ }
}
else{
if(_last_p)_enc->packet_state=OC_PACKET_DONE;
diff --git a/thirdparty/libtheora/encoder_disabled.c b/thirdparty/libtheora/encoder_disabled.c
index 0cbf6645ac..ba6d995505 100644
--- a/thirdparty/libtheora/encoder_disabled.c
+++ b/thirdparty/libtheora/encoder_disabled.c
@@ -11,12 +11,15 @@
********************************************************************
function:
- last mod: $Id: encoder_disabled.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include "apiwrapper.h"
#include "encint.h"
+const th_quant_info TH_VP31_QUANT_INFO = {};
+const th_huff_code TH_VP31_HUFF_CODES[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
+
th_enc_ctx *th_encode_alloc(const th_info *_info){
return NULL;
}
diff --git a/thirdparty/libtheora/enquant.c b/thirdparty/libtheora/enquant.c
index 3372fed221..8fd220edd7 100644
--- a/thirdparty/libtheora/enquant.c
+++ b/thirdparty/libtheora/enquant.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: enquant.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -20,6 +20,69 @@
+int oc_quant_params_clone(th_quant_info *_dst,const th_quant_info *_src){
+ int i;
+ memcpy(_dst,_src,sizeof(*_dst));
+ memset(_dst->qi_ranges,0,sizeof(_dst->qi_ranges));
+ for(i=0;i<6;i++){
+ int nranges;
+ int qti;
+ int pli;
+ int qtj;
+ int plj;
+ int pdup;
+ int qdup;
+ qti=i/3;
+ pli=i%3;
+ qtj=(i-1)/3;
+ plj=(i-1)%3;
+ nranges=_src->qi_ranges[qti][pli].nranges;
+ /*Check for those duplicates that can be cleanly handled by
+ oc_quant_params_clear().*/
+ pdup=i>0&&nranges<=_src->qi_ranges[qtj][plj].nranges;
+ qdup=qti>0&&nranges<=_src->qi_ranges[0][pli].nranges;
+ _dst->qi_ranges[qti][pli].nranges=nranges;
+ if(pdup&&_src->qi_ranges[qti][pli].sizes==_src->qi_ranges[qtj][plj].sizes){
+ _dst->qi_ranges[qti][pli].sizes=_dst->qi_ranges[qtj][plj].sizes;
+ }
+ else if(qdup&&_src->qi_ranges[1][pli].sizes==_src->qi_ranges[0][pli].sizes){
+ _dst->qi_ranges[1][pli].sizes=_dst->qi_ranges[0][pli].sizes;
+ }
+ else{
+ int *sizes;
+ sizes=(int *)_ogg_malloc(nranges*sizeof(*sizes));
+ /*Note: The caller is responsible for cleaning up any partially
+ constructed qinfo.*/
+ if(sizes==NULL)return TH_EFAULT;
+ memcpy(sizes,_src->qi_ranges[qti][pli].sizes,nranges*sizeof(*sizes));
+ _dst->qi_ranges[qti][pli].sizes=sizes;
+ }
+ if(pdup&&_src->qi_ranges[qti][pli].base_matrices==
+ _src->qi_ranges[qtj][plj].base_matrices){
+ _dst->qi_ranges[qti][pli].base_matrices=
+ _dst->qi_ranges[qtj][plj].base_matrices;
+ }
+ else if(qdup&&_src->qi_ranges[1][pli].base_matrices==
+ _src->qi_ranges[0][pli].base_matrices){
+ _dst->qi_ranges[1][pli].base_matrices=
+ _dst->qi_ranges[0][pli].base_matrices;
+ }
+ else{
+ th_quant_base *base_matrices;
+ base_matrices=(th_quant_base *)_ogg_malloc(
+ (nranges+1)*sizeof(*base_matrices));
+ /*Note: The caller is responsible for cleaning up any partially
+ constructed qinfo.*/
+ if(base_matrices==NULL)return TH_EFAULT;
+ memcpy(base_matrices,_src->qi_ranges[qti][pli].base_matrices,
+ (nranges+1)*sizeof(*base_matrices));
+ _dst->qi_ranges[qti][pli].base_matrices=
+ (const th_quant_base *)base_matrices;
+ }
+ }
+ return 0;
+}
+
void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo){
const th_quant_ranges *qranges;
const th_quant_base *base_mats[2*3*64];
@@ -119,7 +182,7 @@ void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo){
}
}
-static void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){
+void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){
ogg_uint32_t t;
int l;
_d<<=1;
@@ -129,48 +192,61 @@ static void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d){
_this->l=l;
}
-/*See comments at oc_dequant_tables_init() for how the quantization tables'
- storage should be initialized.*/
-void oc_enquant_tables_init(ogg_uint16_t *_dequant[64][3][2],
- oc_iquant *_enquant[64][3][2],const th_quant_info *_qinfo){
- int qi;
+void oc_enc_enquant_table_init_c(void *_enquant,
+ const ogg_uint16_t _dequant[64]){
+ oc_iquant *enquant;
+ int zzi;
+ /*In the original VP3.2 code, the rounding offset and the size of the
+ dead zone around 0 were controlled by a "sharpness" parameter.
+ We now R-D optimize the tokens for each block after quantization,
+ so the rounding offset should always be 1/2, and an explicit dead
+ zone is unnecessary.
+ Hence, all of that VP3.2 code is gone from here, and the remaining
+ floating point code has been implemented as equivalent integer
+ code with exact precision.*/
+ enquant=(oc_iquant *)_enquant;
+ for(zzi=0;zzi<64;zzi++)oc_iquant_init(enquant+zzi,_dequant[zzi]);
+}
+
+void oc_enc_enquant_table_fixup_c(void *_enquant[3][3][2],int _nqis){
int pli;
+ int qii;
int qti;
- /*Initialize the dequantization tables first.*/
- oc_dequant_tables_init(_dequant,NULL,_qinfo);
- /*Derive the quantization tables directly from the dequantization tables.*/
- for(qi=0;qi<64;qi++)for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
- int zzi;
- int plj;
- int qtj;
- int dupe;
- dupe=0;
- for(qtj=0;qtj<=qti;qtj++){
- for(plj=0;plj<(qtj<qti?3:pli);plj++){
- if(_dequant[qi][pli][qti]==_dequant[qi][plj][qtj]){
- dupe=1;
- break;
- }
- }
- if(dupe)break;
- }
- if(dupe){
- _enquant[qi][pli][qti]=_enquant[qi][plj][qtj];
- continue;
- }
- /*In the original VP3.2 code, the rounding offset and the size of the
- dead zone around 0 were controlled by a "sharpness" parameter.
- We now R-D optimize the tokens for each block after quantization,
- so the rounding offset should always be 1/2, and an explicit dead
- zone is unnecessary.
- Hence, all of that VP3.2 code is gone from here, and the remaining
- floating point code has been implemented as equivalent integer
- code with exact precision.*/
- for(zzi=0;zzi<64;zzi++){
- oc_iquant_init(_enquant[qi][pli][qti]+zzi,
- _dequant[qi][pli][qti][zzi]);
+ for(pli=0;pli<3;pli++)for(qii=1;qii<_nqis;qii++)for(qti=0;qti<2;qti++){
+ *((oc_iquant *)_enquant[pli][qii][qti])=
+ *((oc_iquant *)_enquant[pli][0][qti]);
+ }
+}
+
+int oc_enc_quantize_c(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant){
+ const oc_iquant *enquant;
+ int nonzero;
+ int zzi;
+ int val;
+ int d;
+ int s;
+ enquant=(const oc_iquant *)_enquant;
+ nonzero=0;
+ for(zzi=0;zzi<64;zzi++){
+ val=_dct[zzi];
+ d=_dequant[zzi];
+ val=val<<1;
+ if(abs(val)>=d){
+ s=OC_SIGNMASK(val);
+ /*The bias added here rounds ties away from zero, since token
+ optimization can only decrease the magnitude of the quantized
+ value.*/
+ val+=d+s^s;
+ /*Note the arithmetic right shift is not guaranteed by ANSI C.
+ Hopefully no one still uses ones-complement architectures.*/
+ val=((enquant[zzi].m*(ogg_int32_t)val>>16)+val>>enquant[zzi].l)-s;
+ _qdct[zzi]=(ogg_int16_t)val;
+ nonzero=zzi;
}
+ else _qdct[zzi]=0;
}
+ return nonzero;
}
@@ -226,7 +302,7 @@ static const ogg_uint16_t OC_RPSD[2][64]={
relative to the total, scaled by 2**16, for each pixel format.
These values were measured after motion-compensated prediction, before
quantization, over a large set of test video encoded at all possible rates.
- TODO: These values are only from INTER frames; it should be re-measured for
+ TODO: These values are only from INTER frames; they should be re-measured for
INTRA frames.*/
static const ogg_uint16_t OC_PCD[4][3]={
{59926, 3038, 2572},
@@ -236,38 +312,58 @@ static const ogg_uint16_t OC_PCD[4][3]={
};
-/*Compute an "average" quantizer for each qi level.
- We do one for INTER and one for INTRA, since their behavior is very
- different, but average across chroma channels.
+/*Compute "average" quantizers for each qi level to use for rate control.
+ We do one for each color channel, as well as an average across color
+ channels, separately for INTER and INTRA, since their behavior is very
+ different.
The basic approach is to compute a harmonic average of the squared quantizer,
weighted by the expected squared magnitude of the DCT coefficients.
Under the (not quite true) assumption that DCT coefficients are
Laplacian-distributed, this preserves the product Q*lambda, where
lambda=sqrt(2/sigma**2) is the Laplacian distribution parameter (not to be
confused with the lambda used in R-D optimization throughout most of the
- rest of the code).
- The value Q*lambda completely determines the entropy of the coefficients.*/
+ rest of the code), when the distributions from multiple coefficients are
+ pooled.
+ The value Q*lambda completely determines the entropy of coefficients drawn
+ from a Laplacian distribution, and thus the expected bitrate.*/
void oc_enquant_qavg_init(ogg_int64_t _log_qavg[2][64],
+ ogg_int16_t _log_plq[64][3][2],ogg_uint16_t _chroma_rd_scale[2][64][2],
ogg_uint16_t *_dequant[64][3][2],int _pixel_fmt){
int qi;
int pli;
int qti;
int ci;
for(qti=0;qti<2;qti++)for(qi=0;qi<64;qi++){
- ogg_int64_t q2;
+ ogg_int64_t q2;
+ ogg_uint32_t qp[3];
+ ogg_uint32_t cqp;
+ ogg_uint32_t d;
q2=0;
for(pli=0;pli<3;pli++){
- ogg_uint32_t qp;
- qp=0;
+ qp[pli]=0;
for(ci=0;ci<64;ci++){
unsigned rq;
unsigned qd;
qd=_dequant[qi][pli][qti][OC_IZIG_ZAG[ci]];
rq=(OC_RPSD[qti][ci]+(qd>>1))/qd;
- qp+=rq*(ogg_uint32_t)rq;
+ qp[pli]+=rq*(ogg_uint32_t)rq;
}
- q2+=OC_PCD[_pixel_fmt][pli]*(ogg_int64_t)qp;
+ q2+=OC_PCD[_pixel_fmt][pli]*(ogg_int64_t)qp[pli];
+ /*plq=1.0/sqrt(qp)*/
+ _log_plq[qi][pli][qti]=
+ (ogg_int16_t)(OC_Q10(32)-oc_blog32_q10(qp[pli])>>1);
}
+ d=OC_PCD[_pixel_fmt][1]+OC_PCD[_pixel_fmt][2];
+ cqp=(ogg_uint32_t)((OC_PCD[_pixel_fmt][1]*(ogg_int64_t)qp[1]+
+ OC_PCD[_pixel_fmt][2]*(ogg_int64_t)qp[2]+(d>>1))/d);
+ /*chroma_rd_scale=clamp(0.25,cqp/qp[0],4)*/
+ d=OC_MAXI(qp[0]+(1<<OC_RD_SCALE_BITS-1)>>OC_RD_SCALE_BITS,1);
+ d=OC_CLAMPI(1<<OC_RD_SCALE_BITS-2,(cqp+(d>>1))/d,4<<OC_RD_SCALE_BITS);
+ _chroma_rd_scale[qti][qi][0]=(ogg_int16_t)d;
+ /*chroma_rd_iscale=clamp(0.25,qp[0]/cqp,4)*/
+ d=OC_MAXI(OC_RD_ISCALE(cqp,1),1);
+ d=OC_CLAMPI(1<<OC_RD_ISCALE_BITS-2,(qp[0]+(d>>1))/d,4<<OC_RD_ISCALE_BITS);
+ _chroma_rd_scale[qti][qi][1]=(ogg_int16_t)d;
/*qavg=1.0/sqrt(q2).*/
_log_qavg[qti][qi]=OC_Q57(48)-oc_blog64(q2)>>1;
}
diff --git a/thirdparty/libtheora/enquant.h b/thirdparty/libtheora/enquant.h
index d62df10d1a..e5f78144cc 100644
--- a/thirdparty/libtheora/enquant.h
+++ b/thirdparty/libtheora/enquant.h
@@ -14,14 +14,13 @@ struct oc_iquant{
ogg_int16_t l;
};
-typedef oc_iquant oc_iquant_table[64];
-
+int oc_quant_params_clone(th_quant_info *_dst,const th_quant_info *_src);
void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo);
-void oc_enquant_tables_init(ogg_uint16_t *_dequant[64][3][2],
- oc_iquant *_enquant[64][3][2],const th_quant_info *_qinfo);
+void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d);
void oc_enquant_qavg_init(ogg_int64_t _log_qavg[2][64],
+ ogg_int16_t _log_plq[64][3][2],ogg_uint16_t _pl_rd_scale[2][64][2],
ogg_uint16_t *_dequant[64][3][2],int _pixel_fmt);
#endif
diff --git a/thirdparty/libtheora/fdct.c b/thirdparty/libtheora/fdct.c
index dc3a66f245..9c2f8b0446 100644
--- a/thirdparty/libtheora/fdct.c
+++ b/thirdparty/libtheora/fdct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: fdct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include "encint.h"
@@ -120,11 +120,6 @@ static void oc_fdct8(ogg_int16_t _y[8],const ogg_int16_t *_x){
_y[7]=v;
}
-void oc_enc_fdct8x8(const oc_enc_ctx *_enc,ogg_int16_t _y[64],
- const ogg_int16_t _x[64]){
- (*_enc->opt_vtable.fdct8x8)(_y,_x);
-}
-
/*Performs a forward 8x8 Type-II DCT transform.
The output is scaled by a factor of 4 relative to the orthonormal version
of the transform.
@@ -152,7 +147,7 @@ void oc_enc_fdct8x8_c(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
/*Round the result back to the external working precision (which is still
scaled by four relative to the orthogonal result).
TODO: We should just update the external working precision.*/
- for(i=0;i<64;i++)_y[i]=w[i]+2>>2;
+ for(i=0;i<64;i++)_y[i]=w[OC_FZIG_ZAG[i]]+2>>2;
}
diff --git a/thirdparty/libtheora/fragment.c b/thirdparty/libtheora/fragment.c
index 15372e9d9f..14c38be507 100644
--- a/thirdparty/libtheora/fragment.c
+++ b/thirdparty/libtheora/fragment.c
@@ -11,17 +11,12 @@
********************************************************************
function:
- last mod: $Id: fragment.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <string.h>
#include "internal.h"
-void oc_frag_copy(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride){
- (*_state->opt_vtable.frag_copy)(_dst,_src,_ystride);
-}
-
void oc_frag_copy_c(unsigned char *_dst,const unsigned char *_src,int _ystride){
int i;
for(i=8;i-->0;){
@@ -31,9 +26,24 @@ void oc_frag_copy_c(unsigned char *_dst,const unsigned char *_src,int _ystride){
}
}
-void oc_frag_recon_intra(const oc_theora_state *_state,unsigned char *_dst,
- int _ystride,const ogg_int16_t _residue[64]){
- _state->opt_vtable.frag_recon_intra(_dst,_ystride,_residue);
+/*Copies the fragments specified by the lists of fragment indices from one
+ frame to another.
+ _dst_frame: The reference frame to copy to.
+ _src_frame: The reference frame to copy from.
+ _ystride: The row stride of the reference frames.
+ _fragis: A pointer to a list of fragment indices.
+ _nfragis: The number of fragment indices to copy.
+ _frag_buf_offs: The offsets of fragments in the reference frames.*/
+void oc_frag_copy_list_c(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs){
+ ptrdiff_t fragii;
+ for(fragii=0;fragii<_nfragis;fragii++){
+ ptrdiff_t frag_buf_off;
+ frag_buf_off=_frag_buf_offs[_fragis[fragii]];
+ oc_frag_copy_c(_dst_frame+frag_buf_off,
+ _src_frame+frag_buf_off,_ystride);
+ }
}
void oc_frag_recon_intra_c(unsigned char *_dst,int _ystride,
@@ -46,11 +56,6 @@ void oc_frag_recon_intra_c(unsigned char *_dst,int _ystride,
}
}
-void oc_frag_recon_inter(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){
- _state->opt_vtable.frag_recon_inter(_dst,_src,_ystride,_residue);
-}
-
void oc_frag_recon_inter_c(unsigned char *_dst,
const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]){
int i;
@@ -62,12 +67,6 @@ void oc_frag_recon_inter_c(unsigned char *_dst,
}
}
-void oc_frag_recon_inter2(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src1,const unsigned char *_src2,int _ystride,
- const ogg_int16_t _residue[64]){
- _state->opt_vtable.frag_recon_inter2(_dst,_src1,_src2,_ystride,_residue);
-}
-
void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]){
int i;
@@ -80,8 +79,4 @@ void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
}
}
-void oc_restore_fpu(const oc_theora_state *_state){
- _state->opt_vtable.restore_fpu();
-}
-
void oc_restore_fpu_c(void){}
diff --git a/thirdparty/libtheora/huffdec.c b/thirdparty/libtheora/huffdec.c
index 8cf27f0341..5a83c5f150 100644
--- a/thirdparty/libtheora/huffdec.c
+++ b/thirdparty/libtheora/huffdec.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: huffdec.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -22,14 +22,60 @@
#include "decint.h"
-/*The ANSI offsetof macro is broken on some platforms (e.g., older DECs).*/
-#define _ogg_offsetof(_type,_field)\
- ((size_t)((char *)&((_type *)0)->_field-(char *)0))
-/*The number of internal tokens associated with each of the spec tokens.*/
-static const unsigned char OC_DCT_TOKEN_MAP_ENTRIES[TH_NDCT_TOKENS]={
- 1,1,1,4,8,1,1,8,1,1,1,1,1,2,2,2,2,4,8,2,2,2,4,2,2,2,2,2,8,2,4,8
-};
+/*Instead of storing every branching in the tree, subtrees can be collapsed
+ into one node, with a table of size 1<<nbits pointing directly to its
+ descedents nbits levels down.
+ This allows more than one bit to be read at a time, and avoids following all
+ the intermediate branches with next to no increased code complexity once
+ the collapsed tree has been built.
+ We do _not_ require that a subtree be complete to be collapsed, but instead
+ store duplicate pointers in the table, and record the actual depth of the
+ node below its parent.
+ This tells us the number of bits to advance the stream after reaching it.
+
+ This turns out to be equivalent to the method described in \cite{Hash95},
+ without the requirement that codewords be sorted by length.
+ If the codewords were sorted by length (so-called ``canonical-codes''), they
+ could be decoded much faster via either Lindell and Moffat's approach or
+ Hashemian's Condensed Huffman Code approach, the latter of which has an
+ extremely small memory footprint.
+ We can't use Choueka et al.'s finite state machine approach, which is
+ extremely fast, because we can't allow multiple symbols to be output at a
+ time; the codebook can and does change between symbols.
+ It also has very large memory requirements, which impairs cache coherency.
+
+ We store the tree packed in an array of 16-bit integers (words).
+ Each node consists of a single word, followed consecutively by two or more
+ indices of its children.
+ Let n be the value of this first word.
+ This is the number of bits that need to be read to traverse the node, and
+ must be positive.
+ 1<<n entries follow in the array, each an index to a child node.
+ If the child is positive, then it is the index of another internal node in
+ the table.
+ If the child is negative or zero, then it is a leaf node.
+ These are stored directly in the child pointer to save space, since they only
+ require a single word.
+ If a leaf node would have been encountered before reading n bits, then it is
+ duplicated the necessary number of times in this table.
+ Leaf nodes pack both a token value and their actual depth in the tree.
+ The token in the leaf node is (-leaf&255).
+ The number of bits that need to be consumed to reach the leaf, starting from
+ the current node, is (-leaf>>8).
+
+ @ARTICLE{Hash95,
+ author="Reza Hashemian",
+ title="Memory Efficient and High-Speed Search {Huffman} Coding",
+ journal="{IEEE} Transactions on Communications",
+ volume=43,
+ number=10,
+ pages="2576--2581",
+ month=Oct,
+ year=1995
+ }*/
+
+
/*The map from external spec-defined tokens to internal tokens.
This is constructed so that any extra bits read with the original token value
@@ -99,391 +145,371 @@ static const unsigned char OC_DCT_TOKEN_MAP[TH_NDCT_TOKENS]={
40
};
-/*These three functions are really part of the bitpack.c module, but
- they are only used here.
- Declaring local static versions so they can be inlined saves considerable
- function call overhead.*/
-
-static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){
- const unsigned char *ptr;
- const unsigned char *stop;
- oc_pb_window window;
- int available;
- window=_b->window;
- available=_b->bits;
- ptr=_b->ptr;
- stop=_b->stop;
- /*This version of _refill() doesn't bother setting eof because we won't
- check for it after we've started decoding DCT tokens.*/
- if(ptr>=stop)available=OC_LOTS_OF_BITS;
- while(available<=OC_PB_WINDOW_SIZE-8){
- available+=8;
- window|=(oc_pb_window)*ptr++<<OC_PB_WINDOW_SIZE-available;
- if(ptr>=stop)available=OC_LOTS_OF_BITS;
- }
- _b->ptr=ptr;
- if(_bits>available)window|=*ptr>>(available&7);
- _b->bits=available;
- return window;
-}
-
-
-/*Read in bits without advancing the bit pointer.
- Here we assume 0<=_bits&&_bits<=32.*/
-static long oc_pack_look(oc_pack_buf *_b,int _bits){
- oc_pb_window window;
- int available;
- long result;
- window=_b->window;
- available=_b->bits;
- if(_bits==0)return 0;
- if(_bits>available)_b->window=window=oc_pack_refill(_b,_bits);
- result=window>>OC_PB_WINDOW_SIZE-_bits;
- return result;
-}
-
-/*Advance the bit pointer.*/
-static void oc_pack_adv(oc_pack_buf *_b,int _bits){
- /*We ignore the special cases for _bits==0 and _bits==32 here, since they are
- never used actually used.
- OC_HUFF_SLUSH (defined below) would have to be at least 27 to actually read
- 32 bits in a single go, and would require a 32 GB lookup table (assuming
- 8 byte pointers, since 4 byte pointers couldn't fit such a table).*/
- _b->window<<=_bits;
- _b->bits-=_bits;
-}
+/*The log base 2 of number of internal tokens associated with each of the spec
+ tokens (i.e., how many of the extra bits are folded into the token value).
+ Increasing the maximum value beyond 3 will enlarge the amount of stack
+ required for tree construction.*/
+static const unsigned char OC_DCT_TOKEN_MAP_LOG_NENTRIES[TH_NDCT_TOKENS]={
+ 0,0,0,2,3,0,0,3,0,0,0,0,0,1,1,1,1,2,3,1,1,1,2,1,1,1,1,1,3,1,2,3
+};
-/*The log_2 of the size of a lookup table is allowed to grow to relative to
- the number of unique nodes it contains.
- E.g., if OC_HUFF_SLUSH is 2, then at most 75% of the space in the tree is
- wasted (each node will have an amortized cost of at most 20 bytes when using
- 4-byte pointers).
+/*The size a lookup table is allowed to grow to relative to the number of
+ unique nodes it contains.
+ E.g., if OC_HUFF_SLUSH is 4, then at most 75% of the space in the tree is
+ wasted (1/4 of the space must be used).
Larger numbers can decode tokens with fewer read operations, while smaller
- numbers may save more space (requiring as little as 8 bytes amortized per
- node, though there will be more nodes).
+ numbers may save more space.
With a sample file:
32233473 read calls are required when no tree collapsing is done (100.0%).
- 19269269 read calls are required when OC_HUFF_SLUSH is 0 (59.8%).
- 11144969 read calls are required when OC_HUFF_SLUSH is 1 (34.6%).
- 10538563 read calls are required when OC_HUFF_SLUSH is 2 (32.7%).
- 10192578 read calls are required when OC_HUFF_SLUSH is 3 (31.6%).
- Since a value of 1 gets us the vast majority of the speed-up with only a
- small amount of wasted memory, this is what we use.*/
-#define OC_HUFF_SLUSH (1)
-
-
-/*Determines the size in bytes of a Huffman tree node that represents a
- subtree of depth _nbits.
- _nbits: The depth of the subtree.
- If this is 0, the node is a leaf node.
- Otherwise 1<<_nbits pointers are allocated for children.
- Return: The number of bytes required to store the node.*/
-static size_t oc_huff_node_size(int _nbits){
- size_t size;
- size=_ogg_offsetof(oc_huff_node,nodes);
- if(_nbits>0)size+=sizeof(oc_huff_node *)*(1<<_nbits);
- return size;
-}
-
-static oc_huff_node *oc_huff_node_init(char **_storage,size_t _size,int _nbits){
- oc_huff_node *ret;
- ret=(oc_huff_node *)*_storage;
- ret->nbits=(unsigned char)_nbits;
- (*_storage)+=_size;
- return ret;
-}
-
-
-/*Determines the size in bytes of a Huffman tree.
- _nbits: The depth of the subtree.
- If this is 0, the node is a leaf node.
- Otherwise storage for 1<<_nbits pointers are added for children.
- Return: The number of bytes required to store the tree.*/
-static size_t oc_huff_tree_size(const oc_huff_node *_node){
- size_t size;
- size=oc_huff_node_size(_node->nbits);
- if(_node->nbits){
- int nchildren;
- int i;
- nchildren=1<<_node->nbits;
- for(i=0;i<nchildren;i+=1<<_node->nbits-_node->nodes[i]->depth){
- size+=oc_huff_tree_size(_node->nodes[i]);
- }
- }
- return size;
-}
-
-
-/*Unpacks a sub-tree from the given buffer.
- _opb: The buffer to unpack from.
- _binodes: The nodes to store the sub-tree in.
- _nbinodes: The number of nodes available for the sub-tree.
- Return: 0 on success, or a negative value on error.*/
-static int oc_huff_tree_unpack(oc_pack_buf *_opb,
- oc_huff_node *_binodes,int _nbinodes){
- oc_huff_node *binode;
- long bits;
- int nused;
- if(_nbinodes<1)return TH_EBADHEADER;
- binode=_binodes;
- nused=0;
- bits=oc_pack_read1(_opb);
- if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
- /*Read an internal node:*/
- if(!bits){
- int ret;
- nused++;
- binode->nbits=1;
- binode->depth=1;
- binode->nodes[0]=_binodes+nused;
- ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
- if(ret>=0){
- nused+=ret;
- binode->nodes[1]=_binodes+nused;
- ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
- }
- if(ret<0)return ret;
- nused+=ret;
- }
- /*Read a leaf node:*/
- else{
- int ntokens;
- int token;
- int i;
- bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ 19269269 read calls are required when OC_HUFF_SLUSH is 1 (59.8%).
+ 11144969 read calls are required when OC_HUFF_SLUSH is 2 (34.6%).
+ 10538563 read calls are required when OC_HUFF_SLUSH is 4 (32.7%).
+ 10192578 read calls are required when OC_HUFF_SLUSH is 8 (31.6%).
+ Since a value of 2 gets us the vast majority of the speed-up with only a
+ small amount of wasted memory, this is what we use.
+ This value must be less than 128, or you could create a tree with more than
+ 32767 entries, which would overflow the 16-bit words used to index it.*/
+#define OC_HUFF_SLUSH (2)
+/*The root of the tree is on the fast path, and a larger value here is more
+ beneficial than elsewhere in the tree.
+ 7 appears to give the best performance, trading off between increased use of
+ the single-read fast path and cache footprint for the tables, though
+ obviously this will depend on your cache size.
+ Using 7 here, the VP3 tables are about twice as large compared to using 2.*/
+#define OC_ROOT_HUFF_SLUSH (7)
+
+
+
+/*Unpacks a Huffman codebook.
+ _opb: The buffer to unpack from.
+ _tokens: Stores a list of internal tokens, in the order they were found in
+ the codebook, and the lengths of their corresponding codewords.
+ This is enough to completely define the codebook, while minimizing
+ stack usage and avoiding temporary allocations (for platforms
+ where free() is a no-op).
+ Return: The number of internal tokens in the codebook, or a negative value
+ on error.*/
+int oc_huff_tree_unpack(oc_pack_buf *_opb,unsigned char _tokens[256][2]){
+ ogg_uint32_t code;
+ int len;
+ int ntokens;
+ int nleaves;
+ code=0;
+ len=ntokens=nleaves=0;
+ for(;;){
+ long bits;
+ bits=oc_pack_read1(_opb);
+ /*Only process nodes so long as there's more bits in the buffer.*/
if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
- /*Find out how many internal tokens we translate this external token into.*/
- ntokens=OC_DCT_TOKEN_MAP_ENTRIES[bits];
- if(_nbinodes<2*ntokens-1)return TH_EBADHEADER;
- /*Fill in a complete binary tree pointing to the internal tokens.*/
- for(i=1;i<ntokens;i<<=1){
- int j;
- binode=_binodes+nused;
- nused+=i;
- for(j=0;j<i;j++){
- binode[j].nbits=1;
- binode[j].depth=1;
- binode[j].nodes[0]=_binodes+nused+2*j;
- binode[j].nodes[1]=_binodes+nused+2*j+1;
- }
+ /*Read an internal node:*/
+ if(!bits){
+ len++;
+ /*Don't allow codewords longer than 32 bits.*/
+ if(len>32)return TH_EBADHEADER;
}
- /*And now the leaf nodes with those tokens.*/
- token=OC_DCT_TOKEN_MAP[bits];
- for(i=0;i<ntokens;i++){
- binode=_binodes+nused++;
- binode->nbits=0;
- binode->depth=1;
- binode->token=token+i;
+ /*Read a leaf node:*/
+ else{
+ ogg_uint32_t code_bit;
+ int neb;
+ int nentries;
+ int token;
+ /*Don't allow more than 32 spec-tokens per codebook.*/
+ if(++nleaves>32)return TH_EBADHEADER;
+ bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ neb=OC_DCT_TOKEN_MAP_LOG_NENTRIES[bits];
+ token=OC_DCT_TOKEN_MAP[bits];
+ nentries=1<<neb;
+ while(nentries-->0){
+ _tokens[ntokens][0]=(unsigned char)token++;
+ _tokens[ntokens][1]=(unsigned char)(len+neb);
+ ntokens++;
+ }
+ code_bit=0x80000000U>>len-1;
+ while(len>0&&(code&code_bit)){
+ code^=code_bit;
+ code_bit<<=1;
+ len--;
+ }
+ if(len<=0)break;
+ code|=code_bit;
}
}
- return nused;
-}
-
-/*Finds the depth of shortest branch of the given sub-tree.
- The tree must be binary.
- _binode: The root of the given sub-tree.
- _binode->nbits must be 0 or 1.
- Return: The smallest depth of a leaf node in this sub-tree.
- 0 indicates this sub-tree is a leaf node.*/
-static int oc_huff_tree_mindepth(oc_huff_node *_binode){
- int depth0;
- int depth1;
- if(_binode->nbits==0)return 0;
- depth0=oc_huff_tree_mindepth(_binode->nodes[0]);
- depth1=oc_huff_tree_mindepth(_binode->nodes[1]);
- return OC_MINI(depth0,depth1)+1;
-}
-
-/*Finds the number of internal nodes at a given depth, plus the number of
- leaves at that depth or shallower.
- The tree must be binary.
- _binode: The root of the given sub-tree.
- _binode->nbits must be 0 or 1.
- Return: The number of entries that would be contained in a jump table of the
- given depth.*/
-static int oc_huff_tree_occupancy(oc_huff_node *_binode,int _depth){
- if(_binode->nbits==0||_depth<=0)return 1;
- else{
- return oc_huff_tree_occupancy(_binode->nodes[0],_depth-1)+
- oc_huff_tree_occupancy(_binode->nodes[1],_depth-1);
- }
+ return ntokens;
}
-/*Makes a copy of the given Huffman tree.
- _node: The Huffman tree to copy.
- Return: The copy of the Huffman tree.*/
-static oc_huff_node *oc_huff_tree_copy(const oc_huff_node *_node,
- char **_storage){
- oc_huff_node *ret;
- ret=oc_huff_node_init(_storage,oc_huff_node_size(_node->nbits),_node->nbits);
- ret->depth=_node->depth;
- if(_node->nbits){
- int nchildren;
- int i;
- int inext;
- nchildren=1<<_node->nbits;
- for(i=0;i<nchildren;){
- ret->nodes[i]=oc_huff_tree_copy(_node->nodes[i],_storage);
- inext=i+(1<<_node->nbits-ret->nodes[i]->depth);
- while(++i<inext)ret->nodes[i]=ret->nodes[i-1];
+/*Count how many tokens would be required to fill a subtree at depth _depth.
+ _tokens: A list of internal tokens, in the order they are found in the
+ codebook, and the lengths of their corresponding codewords.
+ _depth: The depth of the desired node in the corresponding tree structure.
+ Return: The number of tokens that belong to that subtree.*/
+static int oc_huff_subtree_tokens(unsigned char _tokens[][2],int _depth){
+ ogg_uint32_t code;
+ int ti;
+ code=0;
+ ti=0;
+ do{
+ if(_tokens[ti][1]-_depth<32)code+=0x80000000U>>_tokens[ti++][1]-_depth;
+ else{
+ /*Because of the expanded internal tokens, we can have codewords as long
+ as 35 bits.
+ A single recursion here is enough to advance past them.*/
+ code++;
+ ti+=oc_huff_subtree_tokens(_tokens+ti,_depth+31);
}
}
- else ret->token=_node->token;
- return ret;
+ while(code<0x80000000U);
+ return ti;
}
-static size_t oc_huff_tree_collapse_size(oc_huff_node *_binode,int _depth){
- size_t size;
- int mindepth;
- int depth;
- int loccupancy;
- int occupancy;
- if(_binode->nbits!=0&&_depth>0){
- return oc_huff_tree_collapse_size(_binode->nodes[0],_depth-1)+
- oc_huff_tree_collapse_size(_binode->nodes[1],_depth-1);
- }
- depth=mindepth=oc_huff_tree_mindepth(_binode);
- occupancy=1<<mindepth;
+/*Compute the number of bits to use for a collapsed tree node at the given
+ depth.
+ _tokens: A list of internal tokens, in the order they are found in the
+ codebook, and the lengths of their corresponding codewords.
+ _ntokens: The number of tokens corresponding to this tree node.
+ _depth: The depth of this tree node.
+ Return: The number of bits to use for a collapsed tree node rooted here.
+ This is always at least one, even if this was a leaf node.*/
+static int oc_huff_tree_collapse_depth(unsigned char _tokens[][2],
+ int _ntokens,int _depth){
+ int got_leaves;
+ int loccupancy;
+ int occupancy;
+ int slush;
+ int nbits;
+ int best_nbits;
+ slush=_depth>0?OC_HUFF_SLUSH:OC_ROOT_HUFF_SLUSH;
+ /*It's legal to have a tree with just a single node, which requires no bits
+ to decode and always returns the same token.
+ However, no encoder actually does this (yet).
+ To avoid a special case in oc_huff_token_decode(), we force the number of
+ lookahead bits to be at least one.
+ This will produce a tree that looks ahead one bit and then advances the
+ stream zero bits.*/
+ nbits=1;
+ occupancy=2;
+ got_leaves=1;
do{
+ int ti;
+ if(got_leaves)best_nbits=nbits;
+ nbits++;
+ got_leaves=0;
loccupancy=occupancy;
- occupancy=oc_huff_tree_occupancy(_binode,++depth);
- }
- while(occupancy>loccupancy&&occupancy>=1<<OC_MAXI(depth-OC_HUFF_SLUSH,0));
- depth--;
- size=oc_huff_node_size(depth);
- if(depth>0){
- size+=oc_huff_tree_collapse_size(_binode->nodes[0],depth-1);
- size+=oc_huff_tree_collapse_size(_binode->nodes[1],depth-1);
+ for(occupancy=ti=0;ti<_ntokens;occupancy++){
+ if(_tokens[ti][1]<_depth+nbits)ti++;
+ else if(_tokens[ti][1]==_depth+nbits){
+ got_leaves=1;
+ ti++;
+ }
+ else ti+=oc_huff_subtree_tokens(_tokens+ti,_depth+nbits);
+ }
}
- return size;
+ while(occupancy>loccupancy&&occupancy*slush>=1<<nbits);
+ return best_nbits;
}
-static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode,
- char **_storage);
-
-/*Fills the given nodes table with all the children in the sub-tree at the
- given depth.
- The nodes in the sub-tree with a depth less than that stored in the table
- are freed.
- The sub-tree must be binary and complete up until the given depth.
- _nodes: The nodes table to fill.
- _binode: The root of the sub-tree to fill it with.
- _binode->nbits must be 0 or 1.
- _level: The current level in the table.
- 0 indicates that the current node should be stored, regardless of
- whether it is a leaf node or an internal node.
- _depth: The depth of the nodes to fill the table with, relative to their
- parent.*/
-static void oc_huff_node_fill(oc_huff_node **_nodes,
- oc_huff_node *_binode,int _level,int _depth,char **_storage){
- if(_level<=0||_binode->nbits==0){
- int i;
- _binode->depth=(unsigned char)(_depth-_level);
- _nodes[0]=oc_huff_tree_collapse(_binode,_storage);
- for(i=1;i<1<<_level;i++)_nodes[i]=_nodes[0];
- }
- else{
- _level--;
- oc_huff_node_fill(_nodes,_binode->nodes[0],_level,_depth,_storage);
- _nodes+=1<<_level;
- oc_huff_node_fill(_nodes,_binode->nodes[1],_level,_depth,_storage);
- }
+/*Determines the size in words of a Huffman tree node that represents a
+ subtree of depth _nbits.
+ _nbits: The depth of the subtree.
+ This must be greater than zero.
+ Return: The number of words required to store the node.*/
+static size_t oc_huff_node_size(int _nbits){
+ return 1+(1<<_nbits);
}
-/*Finds the largest complete sub-tree rooted at the current node and collapses
- it into a single node.
- This procedure is then applied recursively to all the children of that node.
- _binode: The root of the sub-tree to collapse.
- _binode->nbits must be 0 or 1.
- Return: The new root of the collapsed sub-tree.*/
-static oc_huff_node *oc_huff_tree_collapse(oc_huff_node *_binode,
- char **_storage){
- oc_huff_node *root;
- size_t size;
- int mindepth;
- int depth;
- int loccupancy;
- int occupancy;
- depth=mindepth=oc_huff_tree_mindepth(_binode);
- occupancy=1<<mindepth;
+/*Produces a collapsed-tree representation of the given token list.
+ _tree: The storage for the collapsed Huffman tree.
+ This may be NULL to compute the required storage size instead of
+ constructing the tree.
+ _tokens: A list of internal tokens, in the order they are found in the
+ codebook, and the lengths of their corresponding codewords.
+ _ntokens: The number of tokens corresponding to this tree node.
+ Return: The number of words required to store the tree.*/
+static size_t oc_huff_tree_collapse(ogg_int16_t *_tree,
+ unsigned char _tokens[][2],int _ntokens){
+ ogg_int16_t node[34];
+ unsigned char depth[34];
+ unsigned char last[34];
+ size_t ntree;
+ int ti;
+ int l;
+ depth[0]=0;
+ last[0]=(unsigned char)(_ntokens-1);
+ ntree=0;
+ ti=0;
+ l=0;
do{
- loccupancy=occupancy;
- occupancy=oc_huff_tree_occupancy(_binode,++depth);
+ int nbits;
+ nbits=oc_huff_tree_collapse_depth(_tokens+ti,last[l]+1-ti,depth[l]);
+ node[l]=(ogg_int16_t)ntree;
+ ntree+=oc_huff_node_size(nbits);
+ if(_tree!=NULL)_tree[node[l]++]=(ogg_int16_t)nbits;
+ do{
+ while(ti<=last[l]&&_tokens[ti][1]<=depth[l]+nbits){
+ if(_tree!=NULL){
+ ogg_int16_t leaf;
+ int nentries;
+ nentries=1<<depth[l]+nbits-_tokens[ti][1];
+ leaf=(ogg_int16_t)-(_tokens[ti][1]-depth[l]<<8|_tokens[ti][0]);
+ while(nentries-->0)_tree[node[l]++]=leaf;
+ }
+ ti++;
+ }
+ if(ti<=last[l]){
+ /*We need to recurse*/
+ depth[l+1]=(unsigned char)(depth[l]+nbits);
+ if(_tree!=NULL)_tree[node[l]++]=(ogg_int16_t)ntree;
+ l++;
+ last[l]=
+ (unsigned char)(ti+oc_huff_subtree_tokens(_tokens+ti,depth[l])-1);
+ break;
+ }
+ /*Pop back up a level of recursion.*/
+ else if(l-->0)nbits=depth[l+1]-depth[l];
+ }
+ while(l>=0);
}
- while(occupancy>loccupancy&&occupancy>=1<<OC_MAXI(depth-OC_HUFF_SLUSH,0));
- depth--;
- if(depth<=1)return oc_huff_tree_copy(_binode,_storage);
- size=oc_huff_node_size(depth);
- root=oc_huff_node_init(_storage,size,depth);
- root->depth=_binode->depth;
- oc_huff_node_fill(root->nodes,_binode,depth,depth,_storage);
- return root;
+ while(l>=0);
+ return ntree;
}
/*Unpacks a set of Huffman trees, and reduces them to a collapsed
representation.
_opb: The buffer to unpack the trees from.
_nodes: The table to fill with the Huffman trees.
- Return: 0 on success, or a negative value on error.*/
+ Return: 0 on success, or a negative value on error.
+ The caller is responsible for cleaning up any partially initialized
+ _nodes on failure.*/
int oc_huff_trees_unpack(oc_pack_buf *_opb,
- oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){
+ ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]){
int i;
for(i=0;i<TH_NHUFFMAN_TABLES;i++){
- oc_huff_node nodes[511];
- char *storage;
- size_t size;
- int ret;
+ unsigned char tokens[256][2];
+ int ntokens;
+ ogg_int16_t *tree;
+ size_t size;
/*Unpack the full tree into a temporary buffer.*/
- ret=oc_huff_tree_unpack(_opb,nodes,sizeof(nodes)/sizeof(*nodes));
- if(ret<0)return ret;
- /*Figure out how big the collapsed tree will be.*/
- size=oc_huff_tree_collapse_size(nodes,0);
- storage=(char *)_ogg_calloc(1,size);
- if(storage==NULL)return TH_EFAULT;
- /*And collapse it.*/
- _nodes[i]=oc_huff_tree_collapse(nodes,&storage);
+ ntokens=oc_huff_tree_unpack(_opb,tokens);
+ if(ntokens<0)return ntokens;
+ /*Figure out how big the collapsed tree will be and allocate space for it.*/
+ size=oc_huff_tree_collapse(NULL,tokens,ntokens);
+ /*This should never happen; if it does it means you set OC_HUFF_SLUSH or
+ OC_ROOT_HUFF_SLUSH too large.*/
+ if(size>32767)return TH_EIMPL;
+ tree=(ogg_int16_t *)_ogg_malloc(size*sizeof(*tree));
+ if(tree==NULL)return TH_EFAULT;
+ /*Construct the collapsed the tree.*/
+ oc_huff_tree_collapse(tree,tokens,ntokens);
+ _nodes[i]=tree;
}
return 0;
}
+/*Determines the size in words of a Huffman subtree.
+ _tree: The complete Huffman tree.
+ _node: The index of the root of the desired subtree.
+ Return: The number of words required to store the tree.*/
+static size_t oc_huff_tree_size(const ogg_int16_t *_tree,int _node){
+ size_t size;
+ int nchildren;
+ int n;
+ int i;
+ n=_tree[_node];
+ size=oc_huff_node_size(n);
+ nchildren=1<<n;
+ i=0;
+ do{
+ int child;
+ child=_tree[_node+i+1];
+ if(child<=0)i+=1<<n-(-child>>8);
+ else{
+ size+=oc_huff_tree_size(_tree,child);
+ i++;
+ }
+ }
+ while(i<nchildren);
+ return size;
+}
+
/*Makes a copy of the given set of Huffman trees.
_dst: The array to store the copy in.
_src: The array of trees to copy.*/
-int oc_huff_trees_copy(oc_huff_node *_dst[TH_NHUFFMAN_TABLES],
- const oc_huff_node *const _src[TH_NHUFFMAN_TABLES]){
+int oc_huff_trees_copy(ogg_int16_t *_dst[TH_NHUFFMAN_TABLES],
+ const ogg_int16_t *const _src[TH_NHUFFMAN_TABLES]){
+ int total;
int i;
+ total=0;
for(i=0;i<TH_NHUFFMAN_TABLES;i++){
- size_t size;
- char *storage;
- size=oc_huff_tree_size(_src[i]);
- storage=(char *)_ogg_calloc(1,size);
- if(storage==NULL){
+ size_t size;
+ size=oc_huff_tree_size(_src[i],0);
+ total+=size;
+ _dst[i]=(ogg_int16_t *)_ogg_malloc(size*sizeof(*_dst[i]));
+ if(_dst[i]==NULL){
while(i-->0)_ogg_free(_dst[i]);
return TH_EFAULT;
}
- _dst[i]=oc_huff_tree_copy(_src[i],&storage);
+ memcpy(_dst[i],_src[i],size*sizeof(*_dst[i]));
}
return 0;
}
/*Frees the memory used by a set of Huffman trees.
_nodes: The array of trees to free.*/
-void oc_huff_trees_clear(oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]){
+void oc_huff_trees_clear(ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]){
int i;
for(i=0;i<TH_NHUFFMAN_TABLES;i++)_ogg_free(_nodes[i]);
}
+
/*Unpacks a single token using the given Huffman tree.
_opb: The buffer to unpack the token from.
_node: The tree to unpack the token with.
Return: The token value.*/
-int oc_huff_token_decode(oc_pack_buf *_opb,const oc_huff_node *_node){
- long bits;
- while(_node->nbits!=0){
- bits=oc_pack_look(_opb,_node->nbits);
- _node=_node->nodes[bits];
- oc_pack_adv(_opb,_node->depth);
+int oc_huff_token_decode_c(oc_pack_buf *_opb,const ogg_int16_t *_tree){
+ const unsigned char *ptr;
+ const unsigned char *stop;
+ oc_pb_window window;
+ int available;
+ long bits;
+ int node;
+ int n;
+ ptr=_opb->ptr;
+ window=_opb->window;
+ stop=_opb->stop;
+ available=_opb->bits;
+ node=0;
+ for(;;){
+ n=_tree[node];
+ if(n>available){
+ unsigned shift;
+ shift=OC_PB_WINDOW_SIZE-available;
+ do{
+ /*We don't bother setting eof because we won't check for it after we've
+ started decoding DCT tokens.*/
+ if(ptr>=stop){
+ shift=(unsigned)-OC_LOTS_OF_BITS;
+ break;
+ }
+ shift-=8;
+ window|=(oc_pb_window)*ptr++<<shift;
+ }
+ while(shift>=8);
+ /*Note: We never request more than 24 bits, so there's no need to fill in
+ the last partial byte here.*/
+ available=OC_PB_WINDOW_SIZE-shift;
+ }
+ bits=window>>OC_PB_WINDOW_SIZE-n;
+ node=_tree[node+1+bits];
+ if(node<=0)break;
+ window<<=n;
+ available-=n;
}
- return _node->token;
+ node=-node;
+ n=node>>8;
+ window<<=n;
+ available-=n;
+ _opb->ptr=ptr;
+ _opb->window=window;
+ _opb->bits=available;
+ return node&255;
}
diff --git a/thirdparty/libtheora/huffdec.h b/thirdparty/libtheora/huffdec.h
index d7ffa0e99b..03d25dcd1e 100644
--- a/thirdparty/libtheora/huffdec.h
+++ b/thirdparty/libtheora/huffdec.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: huffdec.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -22,71 +22,11 @@
-typedef struct oc_huff_node oc_huff_node;
-
-/*A node in the Huffman tree.
- Instead of storing every branching in the tree, subtrees can be collapsed
- into one node, with a table of size 1<<nbits pointing directly to its
- descedents nbits levels down.
- This allows more than one bit to be read at a time, and avoids following all
- the intermediate branches with next to no increased code complexity once
- the collapsed tree has been built.
- We do _not_ require that a subtree be complete to be collapsed, but instead
- store duplicate pointers in the table, and record the actual depth of the
- node below its parent.
- This tells us the number of bits to advance the stream after reaching it.
-
- This turns out to be equivalent to the method described in \cite{Hash95},
- without the requirement that codewords be sorted by length.
- If the codewords were sorted by length (so-called ``canonical-codes''), they
- could be decoded much faster via either Lindell and Moffat's approach or
- Hashemian's Condensed Huffman Code approach, the latter of which has an
- extremely small memory footprint.
- We can't use Choueka et al.'s finite state machine approach, which is
- extremely fast, because we can't allow multiple symbols to be output at a
- time; the codebook can and does change between symbols.
- It also has very large memory requirements, which impairs cache coherency.
-
- @ARTICLE{Hash95,
- author="Reza Hashemian",
- title="Memory Efficient and High-Speed Search {Huffman} Coding",
- journal="{IEEE} Transactions on Communications",
- volume=43,
- number=10,
- pages="2576--2581",
- month=Oct,
- year=1995
- }*/
-struct oc_huff_node{
- /*The number of bits of the code needed to descend through this node.
- 0 indicates a leaf node.
- Otherwise there are 1<<nbits nodes in the nodes table, which can be
- indexed by reading nbits bits from the stream.*/
- unsigned char nbits;
- /*The value of a token stored in a leaf node.
- The value in non-leaf nodes is undefined.*/
- unsigned char token;
- /*The depth of the current node, relative to its parent in the collapsed
- tree.
- This can be less than its parent's nbits value, in which case there are
- 1<<nbits-depth copies of this node in the table, and the bitstream should
- only be advanced depth bits after reaching this node.*/
- unsigned char depth;
- /*The table of child nodes.
- The ACTUAL size of this array is 1<<nbits, despite what the declaration
- below claims.
- The exception is that for leaf nodes the size is 0.*/
- oc_huff_node *nodes[2];
-};
-
-
-
int oc_huff_trees_unpack(oc_pack_buf *_opb,
- oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]);
-int oc_huff_trees_copy(oc_huff_node *_dst[TH_NHUFFMAN_TABLES],
- const oc_huff_node *const _src[TH_NHUFFMAN_TABLES]);
-void oc_huff_trees_clear(oc_huff_node *_nodes[TH_NHUFFMAN_TABLES]);
-int oc_huff_token_decode(oc_pack_buf *_opb,const oc_huff_node *_node);
-
+ ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]);
+int oc_huff_trees_copy(ogg_int16_t *_dst[TH_NHUFFMAN_TABLES],
+ const ogg_int16_t *const _src[TH_NHUFFMAN_TABLES]);
+void oc_huff_trees_clear(ogg_int16_t *_nodes[TH_NHUFFMAN_TABLES]);
+int oc_huff_token_decode_c(oc_pack_buf *_opb,const ogg_int16_t *_node);
#endif
diff --git a/thirdparty/libtheora/huffenc.c b/thirdparty/libtheora/huffenc.c
index bf624e0523..77ab584a19 100644
--- a/thirdparty/libtheora/huffenc.c
+++ b/thirdparty/libtheora/huffenc.c
@@ -859,9 +859,10 @@ int oc_huff_codes_pack(oggpack_buffer *_opb,
/*First, find the maximum code length so we can align all the bit
patterns.*/
maxlen=_codes[i][0].nbits;
- for(j=1;j<TH_NDCT_TOKENS;j++){
- maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
- }
+ for(j=1;j<TH_NDCT_TOKENS;j++)maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
+ /*It's improbable that a code with more than 32 bits could pass the
+ validation below, but abort early in any case.*/
+ if(maxlen>32)return TH_EINVAL;
mask=(1<<(maxlen>>1)<<(maxlen+1>>1))-1;
/*Copy over the codes into our temporary workspace.
The bit patterns are aligned, and the original entry each code is from
@@ -877,34 +878,89 @@ int oc_huff_codes_pack(oggpack_buffer *_opb,
/*For each leaf of the tree:*/
bpos=maxlen;
for(j=0;j<TH_NDCT_TOKENS;j++){
- int bit;
- /*If this code has any bits at all.*/
- if(entries[j].shift<maxlen){
- /*Descend into the tree, writing a bit for each branch.*/
- for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
- /*Mark this as a leaf node, and write its value.*/
- oggpackB_write(_opb,1,1);
- oggpackB_write(_opb,entries[j].token,5);
- /*For each 1 branch we've descended, back up the tree until we reach a
- 0 branch.*/
- bit=1<<bpos;
- for(;entries[j].pattern&bit;bpos++)bit<<=1;
- /*Validate the code.*/
- if(j+1<TH_NDCT_TOKENS){
- mask=~(bit-1)<<1;
- /*The next entry should have a 1 bit where we had a 0, and should
- match our code above that bit.
- This verifies both fullness and prefix-freeness simultaneously.*/
- if(!(entries[j+1].pattern&bit)||
- (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
- return TH_EINVAL;
- }
+ ogg_uint32_t bit;
+ /*Fail if this code has no bits at all.
+ Technically a codebook with a single 0-bit entry is legal, but the
+ encoder currently does not support codebooks which do not contain all
+ the tokens.*/
+ if(entries[j].shift>=maxlen)return TH_EINVAL;
+ /*Descend into the tree, writing a bit for each branch.*/
+ for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
+ /*Mark this as a leaf node, and write its value.*/
+ oggpackB_write(_opb,1,1);
+ oggpackB_write(_opb,entries[j].token,5);
+ /*For each 1 branch we've descended, back up the tree until we reach a
+ 0 branch.*/
+ bit=(ogg_uint32_t)1<<bpos;
+ for(;entries[j].pattern&bit;bpos++)bit<<=1;
+ /*Validate the code.*/
+ if(j+1<TH_NDCT_TOKENS){
+ mask=~(bit-1)<<1;
+ /*The next entry should have a 1 bit where we had a 0, and should
+ match our code above that bit.
+ This verifies both fullness and prefix-freeness simultaneously.*/
+ if(!(entries[j+1].pattern&bit)||
+ (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
+ return TH_EINVAL;
+ }
+ }
+ /*If there are no more codes, we should have ascended back to the top
+ of the tree.*/
+ else if(bpos<maxlen)return TH_EINVAL;
+ }
+ }
+ return 0;
+}
+
+/*This is used to copy the configuration of an existing setup header for use by
+ the encoder.
+ The decoder uses a completely different data structure for the Huffman
+ codebooks.*/
+int oc_huff_codes_unpack(oc_pack_buf *_opb,
+ th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){
+ int i;
+ for(i=0;i<TH_NHUFFMAN_TABLES;i++){
+ ogg_uint32_t code;
+ int len;
+ int nleaves;
+ code=0;
+ len=nleaves=0;
+ memset(_codes[i],0,TH_NDCT_TOKENS*sizeof(*_codes[i]));
+ for(;;){
+ long bits;
+ bits=oc_pack_read1(_opb);
+ /*Only process nodes so long as there's more bits in the buffer.*/
+ if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
+ /*Read an internal node:*/
+ if(!bits){
+ len++;
+ /*Don't allow codewords longer than 32 bits.*/
+ if(len>32)return TH_EBADHEADER;
+ }
+ /*Read a leaf node:*/
+ else{
+ ogg_uint32_t code_bit;
+ /*Don't allow more than 32 tokens per codebook.*/
+ if(++nleaves>32)return TH_EBADHEADER;
+ bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ /*The current encoder does not support codebooks that do not contain
+ all of the tokens.*/
+ if(_codes[i][bits].nbits>0)return TH_EINVAL;
+ _codes[i][bits].pattern=code>>32-len;
+ _codes[i][bits].nbits=len;
+ code_bit=0x80000000U>>len-1;
+ while(len>0&&(code&code_bit)){
+ code^=code_bit;
+ code_bit<<=1;
+ len--;
}
- /*If there are no more codes, we should have ascended back to the top
- of the tree.*/
- else if(bpos<maxlen)return TH_EINVAL;
+ if(len<=0)break;
+ code|=code_bit;
}
}
+ /*The current encoder does not support codebooks that do not contain all of
+ the tokens.*/
+ if(nleaves<32)return TH_EINVAL;
}
return 0;
}
diff --git a/thirdparty/libtheora/huffenc.h b/thirdparty/libtheora/huffenc.h
index c5a3956f1f..0554cc4060 100644
--- a/thirdparty/libtheora/huffenc.h
+++ b/thirdparty/libtheora/huffenc.h
@@ -1,6 +1,7 @@
#if !defined(_huffenc_H)
# define _huffenc_H (1)
# include "huffman.h"
+# include "bitpack.h"
@@ -15,5 +16,7 @@ extern const th_huff_code
int oc_huff_codes_pack(oggpack_buffer *_opb,
const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]);
+int oc_huff_codes_unpack(oc_pack_buf *_opb,
+ th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]);
#endif
diff --git a/thirdparty/libtheora/huffman.h b/thirdparty/libtheora/huffman.h
index 36cf7572e5..eb805866b9 100644
--- a/thirdparty/libtheora/huffman.h
+++ b/thirdparty/libtheora/huffman.h
@@ -11,12 +11,12 @@
********************************************************************
function:
- last mod: $Id: huffman.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_huffman_H)
-# define _hufffman_H (1)
+# define _huffman_H (1)
# include "theora/codec.h"
# include "ocintrin.h"
diff --git a/thirdparty/libtheora/idct.c b/thirdparty/libtheora/idct.c
index 0e68ac7658..838e3ad8ca 100644
--- a/thirdparty/libtheora/idct.c
+++ b/thirdparty/libtheora/idct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: idct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -231,18 +231,18 @@ static void idct8_1(ogg_int16_t *_y,const ogg_int16_t _x[1]){
_y: The buffer to store the result in.
This may be the same as _x.
_x: The input coefficients.*/
-static void oc_idct8x8_3(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- const ogg_int16_t *in;
- ogg_int16_t *end;
- ogg_int16_t *out;
- ogg_int16_t w[64];
+static void oc_idct8x8_3(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ ogg_int16_t w[64];
+ int i;
/*Transform rows of x into columns of w.*/
idct8_2(w,_x);
idct8_1(w+1,_x+8);
/*Transform rows of w into columns of y.*/
- for(in=w,out=_y,end=out+8;out<end;in+=8,out++)idct8_2(out,in);
+ for(i=0;i<8;i++)idct8_2(_y+i,w+i*8);
/*Adjust for the scale factor.*/
- for(out=_y,end=out+64;out<end;out++)*out=(ogg_int16_t)(*out+8>>4);
+ for(i=0;i<64;i++)_y[i]=(ogg_int16_t)(_y[i]+8>>4);
+ /*Clear input data for next block.*/
+ _x[0]=_x[1]=_x[8]=0;
}
/*Performs an inverse 8x8 Type-II DCT transform.
@@ -260,20 +260,20 @@ static void oc_idct8x8_3(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
_y: The buffer to store the result in.
This may be the same as _x.
_x: The input coefficients.*/
-static void oc_idct8x8_10(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- const ogg_int16_t *in;
- ogg_int16_t *end;
- ogg_int16_t *out;
- ogg_int16_t w[64];
+static void oc_idct8x8_10(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ ogg_int16_t w[64];
+ int i;
/*Transform rows of x into columns of w.*/
idct8_4(w,_x);
idct8_3(w+1,_x+8);
idct8_2(w+2,_x+16);
idct8_1(w+3,_x+24);
/*Transform rows of w into columns of y.*/
- for(in=w,out=_y,end=out+8;out<end;in+=8,out++)idct8_4(out,in);
+ for(i=0;i<8;i++)idct8_4(_y+i,w+i*8);
/*Adjust for the scale factor.*/
- for(out=_y,end=out+64;out<end;out++)*out=(ogg_int16_t)(*out+8>>4);
+ for(i=0;i<64;i++)_y[i]=(ogg_int16_t)(_y[i]+8>>4);
+ /*Clear input data for next block.*/
+ _x[0]=_x[1]=_x[2]=_x[3]=_x[8]=_x[9]=_x[10]=_x[16]=_x[17]=_x[24]=0;
}
/*Performs an inverse 8x8 Type-II DCT transform.
@@ -282,28 +282,23 @@ static void oc_idct8x8_10(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
_y: The buffer to store the result in.
This may be the same as _x.
_x: The input coefficients.*/
-static void oc_idct8x8_slow(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- const ogg_int16_t *in;
- ogg_int16_t *end;
- ogg_int16_t *out;
- ogg_int16_t w[64];
+static void oc_idct8x8_slow(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ ogg_int16_t w[64];
+ int i;
/*Transform rows of x into columns of w.*/
- for(in=_x,out=w,end=out+8;out<end;in+=8,out++)idct8(out,in);
+ for(i=0;i<8;i++)idct8(w+i,_x+i*8);
/*Transform rows of w into columns of y.*/
- for(in=w,out=_y,end=out+8;out<end;in+=8,out++)idct8(out,in);
+ for(i=0;i<8;i++)idct8(_y+i,w+i*8);
/*Adjust for the scale factor.*/
- for(out=_y,end=out+64;out<end;out++)*out=(ogg_int16_t)(*out+8>>4);
-}
-
-void oc_idct8x8(const oc_theora_state *_state,ogg_int16_t _y[64],
- int _last_zzi){
- (*_state->opt_vtable.idct8x8)(_y,_last_zzi);
+ for(i=0;i<64;i++)_y[i]=(ogg_int16_t)(_y[i]+8>>4);
+ /*Clear input data for next block.*/
+ for(i=0;i<64;i++)_x[i]=0;
}
/*Performs an inverse 8x8 Type-II DCT transform.
The input is assumed to be scaled by a factor of 4 relative to orthonormal
version of the transform.*/
-void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi){
+void oc_idct8x8_c(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
/*_last_zzi is subtly different from an actual count of the number of
coefficients we decoded for this block.
It contains the value of zzi BEFORE the final token in the block was
@@ -329,7 +324,7 @@ void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi){
gets.
Needless to say we inherited this approach from VP3.*/
/*Then perform the iDCT.*/
- if(_last_zzi<3)oc_idct8x8_3(_y,_y);
- else if(_last_zzi<10)oc_idct8x8_10(_y,_y);
- else oc_idct8x8_slow(_y,_y);
+ if(_last_zzi<=3)oc_idct8x8_3(_y,_x);
+ else if(_last_zzi<=10)oc_idct8x8_10(_y,_x);
+ else oc_idct8x8_slow(_y,_x);
}
diff --git a/thirdparty/libtheora/info.c b/thirdparty/libtheora/info.c
index 6b9762978b..e5cecd2de5 100644
--- a/thirdparty/libtheora/info.c
+++ b/thirdparty/libtheora/info.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: info.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -54,7 +54,7 @@ void th_comment_init(th_comment *_tc){
memset(_tc,0,sizeof(*_tc));
}
-void th_comment_add(th_comment *_tc,char *_comment){
+void th_comment_add(th_comment *_tc,const char *_comment){
char **user_comments;
int *comment_lengths;
int comment_len;
@@ -75,7 +75,7 @@ void th_comment_add(th_comment *_tc,char *_comment){
_tc->user_comments[_tc->comments]=NULL;
}
-void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val){
+void th_comment_add_tag(th_comment *_tc,const char *_tag,const char *_val){
char *comment;
int tag_len;
int val_len;
@@ -91,7 +91,7 @@ void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val){
_ogg_free(comment);
}
-char *th_comment_query(th_comment *_tc,char *_tag,int _count){
+char *th_comment_query(th_comment *_tc,const char *_tag,int _count){
long i;
int found;
int tag_len;
@@ -107,7 +107,7 @@ char *th_comment_query(th_comment *_tc,char *_tag,int _count){
return NULL;
}
-int th_comment_query_count(th_comment *_tc,char *_tag){
+int th_comment_query_count(th_comment *_tc,const char *_tag){
long i;
int tag_len;
int count;
diff --git a/thirdparty/libtheora/internal.c b/thirdparty/libtheora/internal.c
index 0fe4f63e72..afbb6efae7 100644
--- a/thirdparty/libtheora/internal.c
+++ b/thirdparty/libtheora/internal.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: internal.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -97,79 +97,29 @@ int oc_ilog(unsigned _v){
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with chroma decimated in the X and Y directions
- (4:2:0).
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs00(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- int dx;
- int dy;
- dx=_lbmvs[0][0]+_lbmvs[1][0]+_lbmvs[2][0]+_lbmvs[3][0];
- dy=_lbmvs[0][1]+_lbmvs[1][1]+_lbmvs[2][1]+_lbmvs[3][1];
- _cbmvs[0][0]=(signed char)OC_DIV_ROUND_POW2(dx,2,2);
- _cbmvs[0][1]=(signed char)OC_DIV_ROUND_POW2(dy,2,2);
-}
-
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with chroma decimated in the Y direction.
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs01(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- int dx;
- int dy;
- dx=_lbmvs[0][0]+_lbmvs[2][0];
- dy=_lbmvs[0][1]+_lbmvs[2][1];
- _cbmvs[0][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[0][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
- dx=_lbmvs[1][0]+_lbmvs[3][0];
- dy=_lbmvs[1][1]+_lbmvs[3][1];
- _cbmvs[1][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[1][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
-}
-
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with chroma decimated in the X direction (4:2:2).
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs10(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- int dx;
- int dy;
- dx=_lbmvs[0][0]+_lbmvs[1][0];
- dy=_lbmvs[0][1]+_lbmvs[1][1];
- _cbmvs[0][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[0][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
- dx=_lbmvs[2][0]+_lbmvs[3][0];
- dy=_lbmvs[2][1]+_lbmvs[3][1];
- _cbmvs[2][0]=(signed char)OC_DIV_ROUND_POW2(dx,1,1);
- _cbmvs[2][1]=(signed char)OC_DIV_ROUND_POW2(dy,1,1);
+void *oc_aligned_malloc(size_t _sz,size_t _align){
+ unsigned char *p;
+ if(_align-1>UCHAR_MAX||(_align&_align-1)||_sz>~(size_t)0-_align)return NULL;
+ p=(unsigned char *)_ogg_malloc(_sz+_align);
+ if(p!=NULL){
+ int offs;
+ offs=((p-(unsigned char *)0)-1&_align-1);
+ p[offs]=offs;
+ p+=offs+1;
+ }
+ return p;
}
-/*The function used to fill in the chroma plane motion vectors for a macro
- block when 4 different motion vectors are specified in the luma plane.
- This version is for use with no chroma decimation (4:4:4).
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lmbmv: The luma macro-block level motion vector to fill in for use in
- prediction.
- _lbmvs: The luma block-level motion vectors.*/
-static void oc_set_chroma_mvs11(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
- memcpy(_cbmvs,_lbmvs,4*sizeof(_lbmvs[0]));
+void oc_aligned_free(void *_ptr){
+ unsigned char *p;
+ p=(unsigned char *)_ptr;
+ if(p!=NULL){
+ int offs;
+ offs=*--p;
+ _ogg_free(p-offs);
+ }
}
-/*A table of functions used to fill in the chroma plane motion vectors for a
- macro block when 4 different motion vectors are specified in the luma
- plane.*/
-const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS]={
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs00,
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs01,
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs10,
- (oc_set_chroma_mvs_func)oc_set_chroma_mvs11
-};
-
-
void **oc_malloc_2d(size_t _height,size_t _width,size_t _sz){
size_t rowsz;
@@ -181,7 +131,6 @@ void **oc_malloc_2d(size_t _height,size_t _width,size_t _sz){
datsz=rowsz*_height;
/*Alloc array and row pointers.*/
ret=(char *)_ogg_malloc(datsz+colsz);
- if(ret==NULL)return NULL;
/*Initialize the array.*/
if(ret!=NULL){
size_t i;
@@ -204,7 +153,6 @@ void **oc_calloc_2d(size_t _height,size_t _width,size_t _sz){
datsz=rowsz*_height;
/*Alloc array and row pointers.*/
ret=(char *)_ogg_calloc(datsz+colsz,1);
- if(ret==NULL)return NULL;
/*Initialize the array.*/
if(ret!=NULL){
size_t i;
diff --git a/thirdparty/libtheora/internal.h b/thirdparty/libtheora/internal.h
index d81263e13e..53c77b88be 100644
--- a/thirdparty/libtheora/internal.h
+++ b/thirdparty/libtheora/internal.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: internal.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_internal_H)
@@ -19,10 +19,20 @@
# include <stdlib.h>
# include <limits.h>
# if defined(HAVE_CONFIG_H)
-# include <config.h>
+# include "config.h"
# endif
# include "theora/codec.h"
# include "theora/theora.h"
+# include "ocintrin.h"
+
+# if !defined(__GNUC_PREREQ)
+# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+# define __GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+# else
+# define __GNUC_PREREQ(_maj,_min) 0
+# endif
+# endif
# if defined(_MSC_VER)
/*Disable missing EMMS warnings.*/
@@ -31,24 +41,25 @@
# pragma warning(disable:4554)
# endif
/*You, too, gcc.*/
-# if defined(__GNUC_PREREQ)
-# if __GNUC_PREREQ(4,2)
-# pragma GCC diagnostic ignored "-Wparentheses"
-# endif
+# if __GNUC_PREREQ(4,2)
+# pragma GCC diagnostic ignored "-Wparentheses"
# endif
-# include "ocintrin.h"
-# include "huffman.h"
-# include "quant.h"
-
-/*Some assembly constructs require aligned operands.*/
-# if defined(OC_X86_ASM)
+/*Some assembly constructs require aligned operands.
+ The following macros are _only_ intended for structure member declarations.
+ Although they will sometimes work on stack variables, gcc will often silently
+ ignore them.
+ A separate set of macros could be made for manual stack alignment, but we
+ don't actually require it anywhere.*/
+# if defined(OC_X86_ASM)||defined(OC_ARM_ASM)
# if defined(__GNUC__)
# define OC_ALIGN8(expr) expr __attribute__((aligned(8)))
# define OC_ALIGN16(expr) expr __attribute__((aligned(16)))
# elif defined(_MSC_VER)
# define OC_ALIGN8(expr) __declspec (align(8)) expr
# define OC_ALIGN16(expr) __declspec (align(16)) expr
+# else
+# error "Alignment macros required for this platform."
# endif
# endif
# if !defined(OC_ALIGN8)
@@ -60,19 +71,8 @@
-typedef struct oc_sb_flags oc_sb_flags;
-typedef struct oc_border_info oc_border_info;
-typedef struct oc_fragment oc_fragment;
-typedef struct oc_fragment_plane oc_fragment_plane;
-typedef struct oc_base_opt_vtable oc_base_opt_vtable;
-typedef struct oc_base_opt_data oc_base_opt_data;
-typedef struct oc_state_dispatch_vtable oc_state_dispatch_vtable;
-typedef struct oc_theora_state oc_theora_state;
-
-
-
/*This library's version.*/
-# define OC_VENDOR_STRING "Xiph.Org libtheora 1.1 20090822 (Thusnelda)"
+# define OC_VENDOR_STRING "Xiph.Org libtheora 1.2.0alpha 20100924 (Ptalarbvorm)"
/*Theora bitstream version.*/
# define TH_VERSION_MAJOR (3)
@@ -83,315 +83,6 @@ typedef struct oc_theora_state oc_theora_state;
((_info)->version_minor>(_min)||(_info)->version_minor==(_min)&& \
(_info)->version_subminor>=(_sub)))
-/*A keyframe.*/
-#define OC_INTRA_FRAME (0)
-/*A predicted frame.*/
-#define OC_INTER_FRAME (1)
-/*A frame of unknown type (frame type decision has not yet been made).*/
-#define OC_UNKWN_FRAME (-1)
-
-/*The amount of padding to add to the reconstructed frame buffers on all
- sides.
- This is used to allow unrestricted motion vectors without special casing.
- This must be a multiple of 2.*/
-#define OC_UMV_PADDING (16)
-
-/*Frame classification indices.*/
-/*The previous golden frame.*/
-#define OC_FRAME_GOLD (0)
-/*The previous frame.*/
-#define OC_FRAME_PREV (1)
-/*The current frame.*/
-#define OC_FRAME_SELF (2)
-
-/*The input or output buffer.*/
-#define OC_FRAME_IO (3)
-
-/*Macroblock modes.*/
-/*Macro block is invalid: It is never coded.*/
-#define OC_MODE_INVALID (-1)
-/*Encoded difference from the same macro block in the previous frame.*/
-#define OC_MODE_INTER_NOMV (0)
-/*Encoded with no motion compensated prediction.*/
-#define OC_MODE_INTRA (1)
-/*Encoded difference from the previous frame offset by the given motion
- vector.*/
-#define OC_MODE_INTER_MV (2)
-/*Encoded difference from the previous frame offset by the last coded motion
- vector.*/
-#define OC_MODE_INTER_MV_LAST (3)
-/*Encoded difference from the previous frame offset by the second to last
- coded motion vector.*/
-#define OC_MODE_INTER_MV_LAST2 (4)
-/*Encoded difference from the same macro block in the previous golden
- frame.*/
-#define OC_MODE_GOLDEN_NOMV (5)
-/*Encoded difference from the previous golden frame offset by the given motion
- vector.*/
-#define OC_MODE_GOLDEN_MV (6)
-/*Encoded difference from the previous frame offset by the individual motion
- vectors given for each block.*/
-#define OC_MODE_INTER_MV_FOUR (7)
-/*The number of (coded) modes.*/
-#define OC_NMODES (8)
-
-/*Determines the reference frame used for a given MB mode.*/
-#define OC_FRAME_FOR_MODE(_x) \
- OC_UNIBBLE_TABLE32(OC_FRAME_PREV,OC_FRAME_SELF,OC_FRAME_PREV,OC_FRAME_PREV, \
- OC_FRAME_PREV,OC_FRAME_GOLD,OC_FRAME_GOLD,OC_FRAME_PREV,(_x))
-
-/*Constants for the packet state machine common between encoder and decoder.*/
-
-/*Next packet to emit/read: Codec info header.*/
-#define OC_PACKET_INFO_HDR (-3)
-/*Next packet to emit/read: Comment header.*/
-#define OC_PACKET_COMMENT_HDR (-2)
-/*Next packet to emit/read: Codec setup header.*/
-#define OC_PACKET_SETUP_HDR (-1)
-/*No more packets to emit/read.*/
-#define OC_PACKET_DONE (INT_MAX)
-
-
-
-/*Super blocks are 32x32 segments of pixels in a single color plane indexed
- in image order.
- Internally, super blocks are broken up into four quadrants, each of which
- contains a 2x2 pattern of blocks, each of which is an 8x8 block of pixels.
- Quadrants, and the blocks within them, are indexed in a special order called
- a "Hilbert curve" within the super block.
-
- In order to differentiate between the Hilbert-curve indexing strategy and
- the regular image order indexing strategy, blocks indexed in image order
- are called "fragments".
- Fragments are indexed in image order, left to right, then bottom to top,
- from Y' plane to Cb plane to Cr plane.
-
- The co-located fragments in all image planes corresponding to the location
- of a single quadrant of a luma plane super block form a macro block.
- Thus there is only a single set of macro blocks for all planes, each of which
- contains between 6 and 12 fragments, depending on the pixel format.
- Therefore macro block information is kept in a separate set of arrays from
- super blocks to avoid unused space in the other planes.
- The lists are indexed in super block order.
- That is, the macro block corresponding to the macro block mbi in (luma plane)
- super block sbi is at index (sbi<<2|mbi).
- Thus the number of macro blocks in each dimension is always twice the number
- of super blocks, even when only an odd number fall inside the coded frame.
- These "extra" macro blocks are just an artifact of our internal data layout,
- and not part of the coded stream; they are flagged with a negative MB mode.*/
-
-
-
-/*A single quadrant of the map from a super block to fragment numbers.*/
-typedef ptrdiff_t oc_sb_map_quad[4];
-/*A map from a super block to fragment numbers.*/
-typedef oc_sb_map_quad oc_sb_map[4];
-/*A single plane of the map from a macro block to fragment numbers.*/
-typedef ptrdiff_t oc_mb_map_plane[4];
-/*A map from a macro block to fragment numbers.*/
-typedef oc_mb_map_plane oc_mb_map[3];
-/*A motion vector.*/
-typedef signed char oc_mv[2];
-
-
-
-/*Super block information.*/
-struct oc_sb_flags{
- unsigned char coded_fully:1;
- unsigned char coded_partially:1;
- unsigned char quad_valid:4;
-};
-
-
-
-/*Information about a fragment which intersects the border of the displayable
- region.
- This marks which pixels belong to the displayable region.*/
-struct oc_border_info{
- /*A bit mask marking which pixels are in the displayable region.
- Pixel (x,y) corresponds to bit (y<<3|x).*/
- ogg_int64_t mask;
- /*The number of pixels in the displayable region.
- This is always positive, and always less than 64.*/
- int npixels;
-};
-
-
-
-/*Fragment information.*/
-struct oc_fragment{
- /*A flag indicating whether or not this fragment is coded.*/
- unsigned coded:1;
- /*A flag indicating that this entire fragment lies outside the displayable
- region of the frame.
- Note the contrast with an invalid macro block, which is outside the coded
- frame, not just the displayable one.
- There are no fragments outside the coded frame by construction.*/
- unsigned invalid:1;
- /*The index of the quality index used for this fragment's AC coefficients.*/
- unsigned qii:6;
- /*The mode of the macroblock this fragment belongs to.*/
- unsigned mb_mode:3;
- /*The index of the associated border information for fragments which lie
- partially outside the displayable region.
- For fragments completely inside or outside this region, this is -1.
- Note that the C standard requires an explicit signed keyword for bitfield
- types, since some compilers may treat them as unsigned without it.*/
- signed int borderi:5;
- /*The prediction-corrected DC component.
- Note that the C standard requires an explicit signed keyword for bitfield
- types, since some compilers may treat them as unsigned without it.*/
- signed int dc:16;
-};
-
-
-
-/*A description of each fragment plane.*/
-struct oc_fragment_plane{
- /*The number of fragments in the horizontal direction.*/
- int nhfrags;
- /*The number of fragments in the vertical direction.*/
- int nvfrags;
- /*The offset of the first fragment in the plane.*/
- ptrdiff_t froffset;
- /*The total number of fragments in the plane.*/
- ptrdiff_t nfrags;
- /*The number of super blocks in the horizontal direction.*/
- unsigned nhsbs;
- /*The number of super blocks in the vertical direction.*/
- unsigned nvsbs;
- /*The offset of the first super block in the plane.*/
- unsigned sboffset;
- /*The total number of super blocks in the plane.*/
- unsigned nsbs;
-};
-
-
-
-/*The shared (encoder and decoder) functions that have accelerated variants.*/
-struct oc_base_opt_vtable{
- void (*frag_copy)(unsigned char *_dst,
- const unsigned char *_src,int _ystride);
- void (*frag_recon_intra)(unsigned char *_dst,int _ystride,
- const ogg_int16_t _residue[64]);
- void (*frag_recon_inter)(unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
- void (*frag_recon_inter2)(unsigned char *_dst,const unsigned char *_src1,
- const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
- void (*idct8x8)(ogg_int16_t _y[64],int _last_zzi);
- void (*state_frag_recon)(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
- void (*state_frag_copy_list)(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
- void (*state_loop_filter_frag_rows)(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
- void (*restore_fpu)(void);
-};
-
-/*The shared (encoder and decoder) tables that vary according to which variants
- of the above functions are used.*/
-struct oc_base_opt_data{
- const unsigned char *dct_fzig_zag;
-};
-
-
-/*State information common to both the encoder and decoder.*/
-struct oc_theora_state{
- /*The stream information.*/
- th_info info;
- /*Table for shared accelerated functions.*/
- oc_base_opt_vtable opt_vtable;
- /*Table for shared data used by accelerated functions.*/
- oc_base_opt_data opt_data;
- /*CPU flags to detect the presence of extended instruction sets.*/
- ogg_uint32_t cpu_flags;
- /*The fragment plane descriptions.*/
- oc_fragment_plane fplanes[3];
- /*The list of fragments, indexed in image order.*/
- oc_fragment *frags;
- /*The the offset into the reference frame buffer to the upper-left pixel of
- each fragment.*/
- ptrdiff_t *frag_buf_offs;
- /*The motion vector for each fragment.*/
- oc_mv *frag_mvs;
- /*The total number of fragments in a single frame.*/
- ptrdiff_t nfrags;
- /*The list of super block maps, indexed in image order.*/
- oc_sb_map *sb_maps;
- /*The list of super block flags, indexed in image order.*/
- oc_sb_flags *sb_flags;
- /*The total number of super blocks in a single frame.*/
- unsigned nsbs;
- /*The fragments from each color plane that belong to each macro block.
- Fragments are stored in image order (left to right then top to bottom).
- When chroma components are decimated, the extra fragments have an index of
- -1.*/
- oc_mb_map *mb_maps;
- /*The list of macro block modes.
- A negative number indicates the macro block lies entirely outside the
- coded frame.*/
- signed char *mb_modes;
- /*The number of macro blocks in the X direction.*/
- unsigned nhmbs;
- /*The number of macro blocks in the Y direction.*/
- unsigned nvmbs;
- /*The total number of macro blocks.*/
- size_t nmbs;
- /*The list of coded fragments, in coded order.
- Uncoded fragments are stored in reverse order from the end of the list.*/
- ptrdiff_t *coded_fragis;
- /*The number of coded fragments in each plane.*/
- ptrdiff_t ncoded_fragis[3];
- /*The total number of coded fragments.*/
- ptrdiff_t ntotal_coded_fragis;
- /*The index of the buffers being used for each OC_FRAME_* reference frame.*/
- int ref_frame_idx[4];
- /*The actual buffers used for the previously decoded frames.*/
- th_ycbcr_buffer ref_frame_bufs[4];
- /*The storage for the reference frame buffers.*/
- unsigned char *ref_frame_data[4];
- /*The strides for each plane in the reference frames.*/
- int ref_ystride[3];
- /*The number of unique border patterns.*/
- int nborders;
- /*The unique border patterns for all border fragments.
- The borderi field of fragments which straddle the border indexes this
- list.*/
- oc_border_info borders[16];
- /*The frame number of the last keyframe.*/
- ogg_int64_t keyframe_num;
- /*The frame number of the current frame.*/
- ogg_int64_t curframe_num;
- /*The granpos of the current frame.*/
- ogg_int64_t granpos;
- /*The type of the current frame.*/
- unsigned char frame_type;
- /*The bias to add to the frame count when computing granule positions.*/
- unsigned char granpos_bias;
- /*The number of quality indices used in the current frame.*/
- unsigned char nqis;
- /*The quality indices of the current frame.*/
- unsigned char qis[3];
- /*The dequantization tables, stored in zig-zag order, and indexed by
- qi, pli, qti, and zzi.*/
- ogg_uint16_t *dequant_tables[64][3][2];
- OC_ALIGN16(oc_quant_table dequant_table_data[64][3][2]);
- /*Loop filter strength parameters.*/
- unsigned char loop_filter_limits[64];
-};
-
-
-
-/*The function type used to fill in the chroma plane motion vectors for a
- macro block when 4 different motion vectors are specified in the luma
- plane.
- _cbmvs: The chroma block-level motion vectors to fill in.
- _lmbmv: The luma macro-block level motion vector to fill in for use in
- prediction.
- _lbmvs: The luma block-level motion vectors.*/
-typedef void (*oc_set_chroma_mvs_func)(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]);
-
/*A map from the index in the zig zag scan to the coefficient number in a
@@ -409,14 +100,12 @@ extern const unsigned char OC_MB_MAP_IDXS[TH_PF_NFORMATS][12];
/*The number of indices in the oc_mb_map array that can be valid for each of
the various chroma decimation types.*/
extern const unsigned char OC_MB_MAP_NIDXS[TH_PF_NFORMATS];
-/*A table of functions used to fill in the Cb,Cr plane motion vectors for a
- macro block when 4 different motion vectors are specified in the luma
- plane.*/
-extern const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS];
int oc_ilog(unsigned _v);
+void *oc_aligned_malloc(size_t _sz,size_t _align);
+void oc_aligned_free(void *_ptr);
void **oc_malloc_2d(size_t _height,size_t _width,size_t _sz);
void **oc_calloc_2d(size_t _height,size_t _width,size_t _sz);
void oc_free_2d(void *_ptr);
@@ -424,86 +113,4 @@ void oc_free_2d(void *_ptr);
void oc_ycbcr_buffer_flip(th_ycbcr_buffer _dst,
const th_ycbcr_buffer _src);
-int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs);
-void oc_state_clear(oc_theora_state *_state);
-void oc_state_vtable_init_c(oc_theora_state *_state);
-void oc_state_borders_fill_rows(oc_theora_state *_state,int _refi,int _pli,
- int _y0,int _yend);
-void oc_state_borders_fill_caps(oc_theora_state *_state,int _refi,int _pli);
-void oc_state_borders_fill(oc_theora_state *_state,int _refi);
-void oc_state_fill_buffer_ptrs(oc_theora_state *_state,int _buf_idx,
- th_ycbcr_buffer _img);
-int oc_state_mbi_for_pos(oc_theora_state *_state,int _mbx,int _mby);
-int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
- int _pli,int _dx,int _dy);
-
-int oc_state_loop_filter_init(oc_theora_state *_state,int *_bv);
-void oc_state_loop_filter(oc_theora_state *_state,int _frame);
-#if defined(OC_DUMP_IMAGES)
-int oc_state_dump_frame(const oc_theora_state *_state,int _frame,
- const char *_suf);
-#endif
-
-/*Shared accelerated functions.*/
-void oc_frag_copy(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride);
-void oc_frag_recon_intra(const oc_theora_state *_state,
- unsigned char *_dst,int _dst_ystride,const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter(const oc_theora_state *_state,unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter2(const oc_theora_state *_state,
- unsigned char *_dst,const unsigned char *_src1,const unsigned char *_src2,
- int _ystride,const ogg_int16_t _residue[64]);
-void oc_idct8x8(const oc_theora_state *_state,ogg_int16_t _y[64],int _last_zzi);
-void oc_state_frag_recon(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
-void oc_state_loop_filter_frag_rows(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
-void oc_restore_fpu(const oc_theora_state *_state);
-
-/*Default pure-C implementations.*/
-void oc_frag_copy_c(unsigned char *_dst,
- const unsigned char *_src,int _src_ystride);
-void oc_frag_recon_intra_c(unsigned char *_dst,int _dst_ystride,
- const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter_c(unsigned char *_dst,
- const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
-void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
- const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
-void oc_idct8x8_c(ogg_int16_t _y[64],int _last_zzi);
-void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list_c(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
-void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
-void oc_restore_fpu_c(void);
-
-/*We need a way to call a few encoder functions without introducing a link-time
- dependency into the decoder, while still allowing the old alpha API which
- does not distinguish between encoder and decoder objects to be used.
- We do this by placing a function table at the start of the encoder object
- which can dispatch into the encoder library.
- We do a similar thing for the decoder in case we ever decide to split off a
- common base library.*/
-typedef void (*oc_state_clear_func)(theora_state *_th);
-typedef int (*oc_state_control_func)(theora_state *th,int _req,
- void *_buf,size_t _buf_sz);
-typedef ogg_int64_t (*oc_state_granule_frame_func)(theora_state *_th,
- ogg_int64_t _granulepos);
-typedef double (*oc_state_granule_time_func)(theora_state *_th,
- ogg_int64_t _granulepos);
-
-
-struct oc_state_dispatch_vtable{
- oc_state_clear_func clear;
- oc_state_control_func control;
- oc_state_granule_frame_func granule_frame;
- oc_state_granule_time_func granule_time;
-};
-
#endif
diff --git a/thirdparty/libtheora/mathops.c b/thirdparty/libtheora/mathops.c
index d3fb909194..23c8f6e1ba 100644
--- a/thirdparty/libtheora/mathops.c
+++ b/thirdparty/libtheora/mathops.c
@@ -1,10 +1,8 @@
+#include "internal.h"
#include "mathops.h"
-#include <limits.h>
/*The fastest fallback strategy for platforms with fast multiplication appears
to be based on de Bruijn sequences~\cite{LP98}.
- Tests confirmed this to be true even on an ARM11, where it is actually faster
- than using the native clz instruction.
Define OC_ILOG_NODEBRUIJN to use a simpler fallback on platforms where
multiplication or table lookups are too expensive.
@@ -15,8 +13,7 @@
year=1998,
note="\url{http://supertech.csail.mit.edu/papers/debruijn.pdf}"
}*/
-#if !defined(OC_ILOG_NODEBRUIJN)&& \
- !defined(OC_CLZ32)||!defined(OC_CLZ64)&&LONG_MAX<9223372036854775807LL
+#if !defined(OC_ILOG_NODEBRUIJN)&&!defined(OC_CLZ32)
static const unsigned char OC_DEBRUIJN_IDX32[32]={
0, 1,28, 2,29,14,24, 3,30,22,20,15,25,17, 4, 8,
31,27,13,23,21,19,16, 7,26,12,18, 6,11, 5,10, 9
@@ -25,7 +22,7 @@ static const unsigned char OC_DEBRUIJN_IDX32[32]={
int oc_ilog32(ogg_uint32_t _v){
#if defined(OC_CLZ32)
- return (OC_CLZ32_OFFS-OC_CLZ32(_v))&-!!_v;
+ return OC_CLZ32_OFFS-OC_CLZ32(_v)&-!!_v;
#else
/*On a Pentium M, this branchless version tested as the fastest version without
multiplications on 1,000,000,000 random 32-bit integers, edging out a
@@ -51,12 +48,12 @@ int oc_ilog32(ogg_uint32_t _v){
/*This de Bruijn sequence version is faster if you have a fast multiplier.*/
# else
int ret;
- ret=_v>0;
_v|=_v>>1;
_v|=_v>>2;
_v|=_v>>4;
_v|=_v>>8;
_v|=_v>>16;
+ ret=_v&1;
_v=(_v>>1)+1;
ret+=OC_DEBRUIJN_IDX32[_v*0x77CB531U>>27&0x1F];
return ret;
@@ -66,16 +63,21 @@ int oc_ilog32(ogg_uint32_t _v){
int oc_ilog64(ogg_int64_t _v){
#if defined(OC_CLZ64)
- return (OC_CLZ64_OFFS-OC_CLZ64(_v))&-!!_v;
+ return OC_CLZ64_OFFS-OC_CLZ64(_v)&-!!_v;
#else
-# if defined(OC_ILOG_NODEBRUIJN)
+/*If we don't have a fast 64-bit word implementation, split it into two 32-bit
+ halves.*/
+# if defined(OC_ILOG_NODEBRUIJN)|| \
+ defined(OC_CLZ32)||LONG_MAX<9223372036854775807LL
ogg_uint32_t v;
int ret;
int m;
- ret=_v>0;
m=(_v>0xFFFFFFFFU)<<5;
v=(ogg_uint32_t)(_v>>m);
- ret|=m;
+# if defined(OC_CLZ32)
+ ret=m+OC_CLZ32_OFFS-OC_CLZ32(v)&-!!v;
+# elif defined(OC_ILOG_NODEBRUIJN)
+ ret=v>0|m;
m=(v>0xFFFFU)<<4;
v>>=m;
ret|=m;
@@ -90,26 +92,19 @@ int oc_ilog64(ogg_int64_t _v){
ret|=m;
ret+=v>1;
return ret;
-# else
-/*If we don't have a 64-bit word, split it into two 32-bit halves.*/
-# if LONG_MAX<9223372036854775807LL
- ogg_uint32_t v;
- int ret;
- int m;
- ret=_v>0;
- m=(_v>0xFFFFFFFFU)<<5;
- v=(ogg_uint32_t)(_v>>m);
- ret|=m;
+# else
v|=v>>1;
v|=v>>2;
v|=v>>4;
v|=v>>8;
v|=v>>16;
+ ret=v&1|m;
v=(v>>1)+1;
ret+=OC_DEBRUIJN_IDX32[v*0x77CB531U>>27&0x1F];
+# endif
return ret;
-/*Otherwise do it in one 64-bit operation.*/
-# else
+/*Otherwise do it in one 64-bit multiply.*/
+# else
static const unsigned char OC_DEBRUIJN_IDX64[64]={
0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40,
5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57,
@@ -117,17 +112,16 @@ int oc_ilog64(ogg_int64_t _v){
62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58
};
int ret;
- ret=_v>0;
_v|=_v>>1;
_v|=_v>>2;
_v|=_v>>4;
_v|=_v>>8;
_v|=_v>>16;
_v|=_v>>32;
+ ret=(int)_v&1;
_v=(_v>>1)+1;
ret+=OC_DEBRUIJN_IDX64[_v*0x218A392CD3D5DBF>>58&0x3F];
return ret;
-# endif
# endif
#endif
}
@@ -294,3 +288,27 @@ ogg_int64_t oc_blog64(ogg_int64_t _w){
}
return OC_Q57(ipart)+z;
}
+
+/*Polynomial approximation of a binary exponential.
+ Q10 input, Q0 output.*/
+ogg_uint32_t oc_bexp32_q10(int _z){
+ unsigned n;
+ int ipart;
+ ipart=_z>>10;
+ n=(_z&(1<<10)-1)<<4;
+ n=(n*((n*((n*((n*3548>>15)+6817)>>15)+15823)>>15)+22708)>>15)+16384;
+ return 14-ipart>0?n+(1<<13-ipart)>>14-ipart:n<<ipart-14;
+}
+
+/*Polynomial approximation of a binary logarithm.
+ Q0 input, Q10 output.*/
+int oc_blog32_q10(ogg_uint32_t _w){
+ int n;
+ int ipart;
+ int fpart;
+ if(_w<=0)return -1;
+ ipart=OC_ILOGNZ_32(_w);
+ n=(ipart-16>0?_w>>ipart-16:_w<<16-ipart)-32768-16384;
+ fpart=(n*((n*((n*((n*-1402>>15)+2546)>>15)-5216)>>15)+15745)>>15)-6793;
+ return (ipart<<10)+(fpart>>4);
+}
diff --git a/thirdparty/libtheora/mathops.h b/thirdparty/libtheora/mathops.h
index efbc5377b0..a1a4f9df0e 100644
--- a/thirdparty/libtheora/mathops.h
+++ b/thirdparty/libtheora/mathops.h
@@ -2,29 +2,27 @@
# define _mathops_H (1)
# include <ogg/ogg.h>
-# ifdef __GNUC_PREREQ
-# if __GNUC_PREREQ(3,4)
-# include <limits.h>
+# if __GNUC_PREREQ(3,4)
+# include <limits.h>
/*Note the casts to (int) below: this prevents OC_CLZ{32|64}_OFFS from
"upgrading" the type of an entire expression to an (unsigned) size_t.*/
-# if INT_MAX>=2147483647
-# define OC_CLZ32_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
-# define OC_CLZ32(_x) (__builtin_clz(_x))
-# elif LONG_MAX>=2147483647L
-# define OC_CLZ32_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
-# define OC_CLZ32(_x) (__builtin_clzl(_x))
-# endif
-# if INT_MAX>=9223372036854775807LL
-# define OC_CLZ64_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
-# define OC_CLZ64(_x) (__builtin_clz(_x))
-# elif LONG_MAX>=9223372036854775807LL
-# define OC_CLZ64_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
-# define OC_CLZ64(_x) (__builtin_clzl(_x))
-# elif LLONG_MAX>=9223372036854775807LL|| \
- __LONG_LONG_MAX__>=9223372036854775807LL
-# define OC_CLZ64_OFFS ((int)sizeof(unsigned long long)*CHAR_BIT)
-# define OC_CLZ64(_x) (__builtin_clzll(_x))
-# endif
+# if INT_MAX>=2147483647
+# define OC_CLZ32_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
+# define OC_CLZ32(_x) (__builtin_clz(_x))
+# elif LONG_MAX>=2147483647L
+# define OC_CLZ32_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
+# define OC_CLZ32(_x) (__builtin_clzl(_x))
+# endif
+# if INT_MAX>=9223372036854775807LL
+# define OC_CLZ64_OFFS ((int)sizeof(unsigned)*CHAR_BIT)
+# define OC_CLZ64(_x) (__builtin_clz(_x))
+# elif LONG_MAX>=9223372036854775807LL
+# define OC_CLZ64_OFFS ((int)sizeof(unsigned long)*CHAR_BIT)
+# define OC_CLZ64(_x) (__builtin_clzl(_x))
+# elif LLONG_MAX>=9223372036854775807LL|| \
+ __LONG_LONG_MAX__>=9223372036854775807LL
+# define OC_CLZ64_OFFS ((int)sizeof(unsigned long long)*CHAR_BIT)
+# define OC_CLZ64(_x) (__builtin_clzll(_x))
# endif
# endif
@@ -134,8 +132,12 @@ int oc_ilog64(ogg_int64_t _v);
# define OC_STATIC_ILOG_64(_v) (OC_STATIC_ILOG6((ogg_int64_t)(_v)))
#define OC_Q57(_v) ((ogg_int64_t)(_v)<<57)
+#define OC_Q10(_v) ((_v)<<10)
ogg_int64_t oc_bexp64(ogg_int64_t _z);
ogg_int64_t oc_blog64(ogg_int64_t _w);
+ogg_uint32_t oc_bexp32_q10(int _z);
+int oc_blog32_q10(ogg_uint32_t _w);
+
#endif
diff --git a/thirdparty/libtheora/mcenc.c b/thirdparty/libtheora/mcenc.c
index 797e81f4f9..82eb824a80 100644
--- a/thirdparty/libtheora/mcenc.c
+++ b/thirdparty/libtheora/mcenc.c
@@ -88,9 +88,11 @@ static const int OC_SQUARE_SITES[11][8]={
};
-static void oc_mcenc_find_candidates(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
- int _accum[2],int _mbi,int _frame){
+static void oc_mcenc_find_candidates_a(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
+ oc_mv _accum,int _mbi,int _frame){
oc_mb_enc_info *embs;
+ int accum_x;
+ int accum_y;
int a[3][2];
int ncandidates;
unsigned nmbi;
@@ -102,20 +104,24 @@ static void oc_mcenc_find_candidates(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
/*Fill in the first part of set A: the vectors from adjacent blocks.*/
for(i=0;i<embs[_mbi].ncneighbors;i++){
nmbi=embs[_mbi].cneighbors[i];
- _mcenc->candidates[ncandidates][0]=embs[nmbi].analysis_mv[0][_frame][0];
- _mcenc->candidates[ncandidates][1]=embs[nmbi].analysis_mv[0][_frame][1];
+ _mcenc->candidates[ncandidates][0]=
+ OC_MV_X(embs[nmbi].analysis_mv[0][_frame]);
+ _mcenc->candidates[ncandidates][1]=
+ OC_MV_Y(embs[nmbi].analysis_mv[0][_frame]);
ncandidates++;
}
}
+ accum_x=OC_MV_X(_accum);
+ accum_y=OC_MV_Y(_accum);
/*Add a few additional vectors to set A: the vectors used in the previous
frames and the (0,0) vector.*/
- _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,_accum[0],31);
- _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,_accum[1],31);
+ _mcenc->candidates[ncandidates][0]=accum_x;
+ _mcenc->candidates[ncandidates][1]=accum_y;
ncandidates++;
_mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,
- embs[_mbi].analysis_mv[1][_frame][0]+_accum[0],31);
+ OC_MV_X(embs[_mbi].analysis_mv[1][_frame])+accum_x,31);
_mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,
- embs[_mbi].analysis_mv[1][_frame][1]+_accum[1],31);
+ OC_MV_Y(embs[_mbi].analysis_mv[1][_frame])+accum_y,31);
ncandidates++;
_mcenc->candidates[ncandidates][0]=0;
_mcenc->candidates[ncandidates][1]=0;
@@ -131,30 +137,33 @@ static void oc_mcenc_find_candidates(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
OC_SORT2I(a[0][1],a[1][1]);
_mcenc->candidates[0][0]=a[1][0];
_mcenc->candidates[0][1]=a[1][1];
- /*Fill in set B: accelerated predictors for this and adjacent macro blocks.*/
_mcenc->setb0=ncandidates;
- /*The first time through the loop use the current macro block.*/
- nmbi=_mbi;
- for(i=0;;i++){
- _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,
- 2*embs[_mbi].analysis_mv[1][_frame][0]
- -embs[_mbi].analysis_mv[2][_frame][0]+_accum[0],31);
- _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,
- 2*embs[_mbi].analysis_mv[1][_frame][1]
- -embs[_mbi].analysis_mv[2][_frame][1]+_accum[1],31);
- ncandidates++;
- if(i>=embs[_mbi].npneighbors)break;
- nmbi=embs[_mbi].pneighbors[i];
- }
- /*Truncate to full-pel positions.*/
- for(i=0;i<ncandidates;i++){
- _mcenc->candidates[i][0]=OC_DIV2(_mcenc->candidates[i][0]);
- _mcenc->candidates[i][1]=OC_DIV2(_mcenc->candidates[i][1]);
- }
+}
+
+static void oc_mcenc_find_candidates_b(oc_enc_ctx *_enc,oc_mcenc_ctx *_mcenc,
+ oc_mv _accum,int _mbi,int _frame){
+ oc_mb_enc_info *embs;
+ int accum_x;
+ int accum_y;
+ int ncandidates;
+ embs=_enc->mb_info;
+ accum_x=OC_MV_X(_accum);
+ accum_y=OC_MV_Y(_accum);
+ /*Fill in set B: accelerated predictors for this and adjacent macro blocks.*/
+ ncandidates=_mcenc->setb0;
+ /*Use only the current block. Using more did not appear to be helpful
+ with the current selection logic due to escaping the local search too
+ quickly.*/
+ _mcenc->candidates[ncandidates][0]=OC_CLAMPI(-31,
+ 2*OC_MV_X(embs[_mbi].analysis_mv[1][_frame])
+ -OC_MV_X(embs[_mbi].analysis_mv[2][_frame])+accum_x,31);
+ _mcenc->candidates[ncandidates][1]=OC_CLAMPI(-31,
+ 2*OC_MV_Y(embs[_mbi].analysis_mv[1][_frame])
+ -OC_MV_Y(embs[_mbi].analysis_mv[2][_frame])+accum_y,31);
+ ncandidates++;
_mcenc->ncandidates=ncandidates;
}
-#if 0
static unsigned oc_sad16_halfpel(const oc_enc_ctx *_enc,
const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],
int _mvoffset0,int _mvoffset1,const unsigned char *_src,
@@ -170,20 +179,21 @@ static unsigned oc_sad16_halfpel(const oc_enc_ctx *_enc,
}
return err;
}
-#endif
static unsigned oc_satd16_halfpel(const oc_enc_ctx *_enc,
const ptrdiff_t *_frag_buf_offs,const ptrdiff_t _fragis[4],
int _mvoffset0,int _mvoffset1,const unsigned char *_src,
const unsigned char *_ref,int _ystride,unsigned _best_err){
unsigned err;
+ int dc;
int bi;
err=0;
for(bi=0;bi<4;bi++){
ptrdiff_t frag_offs;
frag_offs=_frag_buf_offs[_fragis[bi]];
- err+=oc_enc_frag_satd2_thresh(_enc,_src+frag_offs,_ref+frag_offs+_mvoffset0,
- _ref+frag_offs+_mvoffset1,_ystride,_best_err-err);
+ err+=oc_enc_frag_satd2(_enc,&dc,_src+frag_offs,
+ _ref+frag_offs+_mvoffset0,_ref+frag_offs+_mvoffset1,_ystride);
+ err+=abs(dc);
}
return err;
}
@@ -219,9 +229,17 @@ static int oc_mcenc_ysatd_check_mbcandidate_fullpel(const oc_enc_ctx *_enc,
err=0;
for(bi=0;bi<4;bi++){
ptrdiff_t frag_offs;
+ int dc;
frag_offs=_frag_buf_offs[_fragis[bi]];
- err+=oc_enc_frag_satd_thresh(_enc,
- _src+frag_offs,_ref+frag_offs+mvoffset,_ystride,UINT_MAX);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ err+=oc_enc_frag_satd(_enc,&dc,
+ _src+frag_offs,_ref+frag_offs+mvoffset,_ystride);
+ err+=abs(dc);
+ }
+ else{
+ err+=oc_enc_frag_sad(_enc,
+ _src+frag_offs,_ref+frag_offs+mvoffset,_ystride);
+ }
}
return err;
}
@@ -229,8 +247,11 @@ static int oc_mcenc_ysatd_check_mbcandidate_fullpel(const oc_enc_ctx *_enc,
static unsigned oc_mcenc_ysatd_check_bcandidate_fullpel(const oc_enc_ctx *_enc,
ptrdiff_t _frag_offs,int _dx,int _dy,
const unsigned char *_src,const unsigned char *_ref,int _ystride){
- return oc_enc_frag_satd_thresh(_enc,
- _src+_frag_offs,_ref+_frag_offs+_dx+_dy*_ystride,_ystride,UINT_MAX);
+ unsigned err;
+ int dc;
+ err=oc_enc_frag_satd(_enc,&dc,
+ _src+_frag_offs,_ref+_frag_offs+_dx+_dy*_ystride,_ystride);
+ return err+abs(dc);
}
/*Perform a motion vector search for this macro block against a single
@@ -239,11 +260,14 @@ static unsigned oc_mcenc_ysatd_check_bcandidate_fullpel(const oc_enc_ctx *_enc,
the work can be shared.
The actual motion vector is stored in the appropriate place in the
oc_mb_enc_info structure.
- _mcenc: The motion compensation context.
- _accum: Drop frame/golden MV accumulators.
- _mbi: The macro block index.
- _frame: The frame to search, either OC_FRAME_PREV or OC_FRAME_GOLD.*/
-void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
+ _accum: Drop frame/golden MV accumulators.
+ _mbi: The macro block index.
+ _frame: The frame to use for SATD calculations and refinement,
+ either OC_FRAME_PREV or OC_FRAME_GOLD.
+ _frame_full: The frame to perform the 1px search on, one of OC_FRAME_PREV,
+ OC_FRAME_GOLD, OC_FRAME_PREV_ORIG, or OC_FRAME_GOLD_ORIG.*/
+void oc_mcenc_search_frame(oc_enc_ctx *_enc,oc_mv _accum,int _mbi,int _frame,
+ int _frame_full){
/*Note: Traditionally this search is done using a rate-distortion objective
function of the form D+lambda*R.
However, xiphmont tested this and found it produced a small degredation,
@@ -264,6 +288,7 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
const ptrdiff_t *fragis;
const unsigned char *src;
const unsigned char *ref;
+ const unsigned char *satd_ref;
int ystride;
oc_mb_enc_info *embs;
ogg_int32_t hit_cache[31];
@@ -278,17 +303,18 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
int bi;
embs=_enc->mb_info;
/*Find some candidate motion vectors.*/
- oc_mcenc_find_candidates(_enc,&mcenc,_accum,_mbi,_frame);
+ oc_mcenc_find_candidates_a(_enc,&mcenc,_accum,_mbi,_frame);
/*Clear the cache of locations we've examined.*/
memset(hit_cache,0,sizeof(hit_cache));
/*Start with the median predictor.*/
- candx=mcenc.candidates[0][0];
- candy=mcenc.candidates[0][1];
+ candx=OC_DIV2(mcenc.candidates[0][0]);
+ candy=OC_DIV2(mcenc.candidates[0][1]);
hit_cache[candy+15]|=(ogg_int32_t)1<<candx+15;
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]];
+ ref=_enc->state.ref_frame_data[_frame_full];
+ satd_ref=_enc->state.ref_frame_data[_frame];
ystride=_enc->state.ref_ystride[0];
/*TODO: customize error function for speed/(quality+size) tradeoff.*/
best_err=oc_mcenc_ysad_check_mbcandidate_fullpel(_enc,
@@ -317,8 +343,8 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
t2+=(t2>>OC_YSAD_THRESH2_SCALE_BITS)+OC_YSAD_THRESH2_OFFSET;
/*Examine the candidates in set A.*/
for(ci=1;ci<mcenc.setb0;ci++){
- candx=mcenc.candidates[ci][0];
- candy=mcenc.candidates[ci][1];
+ candx=OC_DIV2(mcenc.candidates[ci][0]);
+ candy=OC_DIV2(mcenc.candidates[ci][1]);
/*If we've already examined this vector, then we would be using it if it
was better than what we are using.*/
hitbit=(ogg_int32_t)1<<candx+15;
@@ -340,10 +366,11 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
}
}
if(best_err>t2){
+ oc_mcenc_find_candidates_b(_enc,&mcenc,_accum,_mbi,_frame);
/*Examine the candidates in set B.*/
for(;ci<mcenc.ncandidates;ci++){
- candx=mcenc.candidates[ci][0];
- candy=mcenc.candidates[ci][1];
+ candx=OC_DIV2(mcenc.candidates[ci][0]);
+ candy=OC_DIV2(mcenc.candidates[ci][1]);
hitbit=(ogg_int32_t)1<<candx+15;
if(hit_cache[candy+15]&hitbit)continue;
hit_cache[candy+15]|=hitbit;
@@ -475,58 +502,50 @@ void oc_mcenc_search_frame(oc_enc_ctx *_enc,int _accum[2],int _mbi,int _frame){
candx=best_vec[0];
candy=best_vec[1];
embs[_mbi].satd[_frame]=oc_mcenc_ysatd_check_mbcandidate_fullpel(_enc,
- frag_buf_offs,fragis,candx,candy,src,ref,ystride);
- embs[_mbi].analysis_mv[0][_frame][0]=(signed char)(candx<<1);
- embs[_mbi].analysis_mv[0][_frame][1]=(signed char)(candy<<1);
- if(_frame==OC_FRAME_PREV){
+ frag_buf_offs,fragis,candx,candy,src,satd_ref,ystride);
+ embs[_mbi].analysis_mv[0][_frame]=OC_MV(candx<<1,candy<<1);
+ if(_frame==OC_FRAME_PREV&&_enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
for(bi=0;bi<4;bi++){
candx=best_block_vec[bi][0];
candy=best_block_vec[bi][1];
embs[_mbi].block_satd[bi]=oc_mcenc_ysatd_check_bcandidate_fullpel(_enc,
- frag_buf_offs[fragis[bi]],candx,candy,src,ref,ystride);
- embs[_mbi].block_mv[bi][0]=(signed char)(candx<<1);
- embs[_mbi].block_mv[bi][1]=(signed char)(candy<<1);
+ frag_buf_offs[fragis[bi]],candx,candy,src,satd_ref,ystride);
+ embs[_mbi].block_mv[bi]=OC_MV(candx<<1,candy<<1);
}
}
}
void oc_mcenc_search(oc_enc_ctx *_enc,int _mbi){
- oc_mv2 *mvs;
- int accum_p[2];
- int accum_g[2];
+ oc_mv2 *mvs;
+ oc_mv accum_p;
+ oc_mv accum_g;
+ oc_mv mv2_p;
mvs=_enc->mb_info[_mbi].analysis_mv;
- if(_enc->prevframe_dropped){
- accum_p[0]=mvs[0][OC_FRAME_PREV][0];
- accum_p[1]=mvs[0][OC_FRAME_PREV][1];
- }
- else accum_p[1]=accum_p[0]=0;
- accum_g[0]=mvs[2][OC_FRAME_GOLD][0];
- accum_g[1]=mvs[2][OC_FRAME_GOLD][1];
- mvs[0][OC_FRAME_PREV][0]-=mvs[2][OC_FRAME_PREV][0];
- mvs[0][OC_FRAME_PREV][1]-=mvs[2][OC_FRAME_PREV][1];
+ if(_enc->prevframe_dropped)accum_p=mvs[0][OC_FRAME_PREV];
+ else accum_p=0;
+ accum_g=mvs[2][OC_FRAME_GOLD];
/*Move the motion vector predictors back a frame.*/
- memmove(mvs+1,mvs,2*sizeof(*mvs));
+ mv2_p=mvs[2][OC_FRAME_PREV];
+ mvs[2][OC_FRAME_GOLD]=mvs[1][OC_FRAME_GOLD];
+ mvs[2][OC_FRAME_PREV]=mvs[1][OC_FRAME_PREV];
+ mvs[1][OC_FRAME_GOLD]=mvs[0][OC_FRAME_GOLD];
+ mvs[1][OC_FRAME_PREV]=OC_MV_SUB(mvs[0][OC_FRAME_PREV],mv2_p);
/*Search the last frame.*/
- oc_mcenc_search_frame(_enc,accum_p,_mbi,OC_FRAME_PREV);
- mvs[2][OC_FRAME_PREV][0]=accum_p[0];
- mvs[2][OC_FRAME_PREV][1]=accum_p[1];
+ oc_mcenc_search_frame(_enc,accum_p,_mbi,OC_FRAME_PREV,OC_FRAME_PREV_ORIG);
+ mvs[2][OC_FRAME_PREV]=accum_p;
/*GOLDEN MVs are different from PREV MVs in that they're each absolute
offsets from some frame in the past rather than relative offsets from the
frame before.
For predictor calculation to make sense, we need them to be in the same
form as PREV MVs.*/
- mvs[1][OC_FRAME_GOLD][0]-=mvs[2][OC_FRAME_GOLD][0];
- mvs[1][OC_FRAME_GOLD][1]-=mvs[2][OC_FRAME_GOLD][1];
- mvs[2][OC_FRAME_GOLD][0]-=accum_g[0];
- mvs[2][OC_FRAME_GOLD][1]-=accum_g[1];
+ mvs[1][OC_FRAME_GOLD]=OC_MV_SUB(mvs[1][OC_FRAME_GOLD],mvs[2][OC_FRAME_GOLD]);
+ mvs[2][OC_FRAME_GOLD]=OC_MV_SUB(mvs[2][OC_FRAME_GOLD],accum_g);
/*Search the golden frame.*/
- oc_mcenc_search_frame(_enc,accum_g,_mbi,OC_FRAME_GOLD);
+ oc_mcenc_search_frame(_enc,accum_g,_mbi,OC_FRAME_GOLD,OC_FRAME_GOLD_ORIG);
/*Put GOLDEN MVs back into absolute offset form.
The newest MV is already an absolute offset.*/
- mvs[2][OC_FRAME_GOLD][0]+=accum_g[0];
- mvs[2][OC_FRAME_GOLD][1]+=accum_g[1];
- mvs[1][OC_FRAME_GOLD][0]+=mvs[2][OC_FRAME_GOLD][0];
- mvs[1][OC_FRAME_GOLD][1]+=mvs[2][OC_FRAME_GOLD][1];
+ mvs[2][OC_FRAME_GOLD]=OC_MV_ADD(mvs[2][OC_FRAME_GOLD],accum_g);
+ mvs[1][OC_FRAME_GOLD]=OC_MV_ADD(mvs[1][OC_FRAME_GOLD],mvs[2][OC_FRAME_GOLD]);
}
#if 0
@@ -543,7 +562,7 @@ static int oc_mcenc_ysad_halfpel_mbrefine(const oc_enc_ctx *_enc,int _mbi,
int sitei;
int err;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_framei]];
+ ref=_enc->state.ref_frame_data[_framei];
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
ystride=_enc->state.ref_ystride[0];
@@ -598,7 +617,7 @@ static unsigned oc_mcenc_ysatd_halfpel_mbrefine(const oc_enc_ctx *_enc,
int sitei;
int err;
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[_frame]];
+ ref=_enc->state.ref_frame_data[_frame];
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
ystride=_enc->state.ref_ystride[0];
@@ -627,8 +646,14 @@ static unsigned oc_mcenc_ysatd_halfpel_mbrefine(const oc_enc_ctx *_enc,
ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy);
mvoffset0=mvoffset_base+(dx&xmask)+(offset_y[site]&ymask);
mvoffset1=mvoffset_base+(dx&~xmask)+(offset_y[site]&~ymask);
- err=oc_satd16_halfpel(_enc,frag_buf_offs,fragis,
- mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+ if(_enc->sp_level<OC_SP_LEVEL_NOSATD){
+ err=oc_satd16_halfpel(_enc,frag_buf_offs,fragis,
+ mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+ }
+ else{
+ err=oc_sad16_halfpel(_enc,frag_buf_offs,fragis,
+ mvoffset0,mvoffset1,src,ref,ystride,_best_err);
+ }
if(err<_best_err){
_best_err=err;
best_site=site;
@@ -643,12 +668,11 @@ void oc_mcenc_refine1mv(oc_enc_ctx *_enc,int _mbi,int _frame){
oc_mb_enc_info *embs;
int vec[2];
embs=_enc->mb_info;
- vec[0]=OC_DIV2(embs[_mbi].analysis_mv[0][_frame][0]);
- vec[1]=OC_DIV2(embs[_mbi].analysis_mv[0][_frame][1]);
+ vec[0]=OC_DIV2(OC_MV_X(embs[_mbi].analysis_mv[0][_frame]));
+ vec[1]=OC_DIV2(OC_MV_Y(embs[_mbi].analysis_mv[0][_frame]));
embs[_mbi].satd[_frame]=oc_mcenc_ysatd_halfpel_mbrefine(_enc,
_mbi,vec,embs[_mbi].satd[_frame],_frame);
- embs[_mbi].analysis_mv[0][_frame][0]=(signed char)vec[0];
- embs[_mbi].analysis_mv[0][_frame][1]=(signed char)vec[1];
+ embs[_mbi].analysis_mv[0][_frame]=OC_MV(vec[0],vec[1]);
}
#if 0
@@ -704,6 +728,7 @@ static unsigned oc_mcenc_ysatd_halfpel_brefine(const oc_enc_ctx *_enc,
best_site=4;
for(sitei=0;sitei<8;sitei++){
unsigned err;
+ int dc;
int site;
int xmask;
int ymask;
@@ -723,8 +748,9 @@ static unsigned oc_mcenc_ysatd_halfpel_brefine(const oc_enc_ctx *_enc,
ymask=OC_SIGNMASK(((_vec[1]<<1)+dy)^dy);
mvoffset0=mvoffset_base+(dx&xmask)+(_offset_y[site]&ymask);
mvoffset1=mvoffset_base+(dx&~xmask)+(_offset_y[site]&~ymask);
- err=oc_enc_frag_satd2_thresh(_enc,_src,
- _ref+mvoffset0,_ref+mvoffset1,_ystride,_best_err);
+ err=oc_enc_frag_satd2(_enc,&dc,_src,
+ _ref+mvoffset0,_ref+mvoffset1,_ystride);
+ err+=abs(dc);
if(err<_best_err){
_best_err=err;
best_site=site;
@@ -748,7 +774,7 @@ void oc_mcenc_refine4mv(oc_enc_ctx *_enc,int _mbi){
frag_buf_offs=_enc->state.frag_buf_offs;
fragis=_enc->state.mb_maps[_mbi][0];
src=_enc->state.ref_frame_data[OC_FRAME_IO];
- ref=_enc->state.ref_frame_data[_enc->state.ref_frame_idx[OC_FRAME_PREV]];
+ ref=_enc->state.ref_frame_data[OC_FRAME_PREV];
offset_y[0]=offset_y[1]=offset_y[2]=-ystride;
offset_y[3]=offset_y[5]=0;
offset_y[6]=offset_y[7]=offset_y[8]=ystride;
@@ -757,11 +783,10 @@ void oc_mcenc_refine4mv(oc_enc_ctx *_enc,int _mbi){
ptrdiff_t frag_offs;
int vec[2];
frag_offs=frag_buf_offs[fragis[bi]];
- vec[0]=OC_DIV2(embs[_mbi].block_mv[bi][0]);
- vec[1]=OC_DIV2(embs[_mbi].block_mv[bi][1]);
+ vec[0]=OC_DIV2(OC_MV_X(embs[_mbi].block_mv[bi]));
+ vec[1]=OC_DIV2(OC_MV_Y(embs[_mbi].block_mv[bi]));
embs[_mbi].block_satd[bi]=oc_mcenc_ysatd_halfpel_brefine(_enc,vec,
src+frag_offs,ref+frag_offs,ystride,offset_y,embs[_mbi].block_satd[bi]);
- embs[_mbi].ref_mv[bi][0]=(signed char)vec[0];
- embs[_mbi].ref_mv[bi][1]=(signed char)vec[1];
+ embs[_mbi].ref_mv[bi]=OC_MV(vec[0],vec[1]);
}
}
diff --git a/thirdparty/libtheora/modedec.h b/thirdparty/libtheora/modedec.h
index ea12c64afd..efe640e263 100644
--- a/thirdparty/libtheora/modedec.h
+++ b/thirdparty/libtheora/modedec.h
@@ -1,614 +1,91 @@
/*File generated by libtheora with OC_COLLECT_METRICS defined at compile time.*/
#if !defined(_modedec_H)
# define _modedec_H (1)
+# include "encint.h"
-# if defined(OC_COLLECT_METRICS)
-typedef struct oc_mode_metrics oc_mode_metrics;
+/*The log of the average quantizer for each of the OC_MODE_RD table rows
+ (e.g., for the represented qi's, and each pli and qti), in Q10 format.
+ The actual statistics used by the encoder will be interpolated from
+ that table based on log_plq for the actual quantization matrix used.*/
+# if !defined(OC_COLLECT_METRICS)
+static const
# endif
-typedef struct oc_mode_rd oc_mode_rd;
-
-
-
-/*The number of extra bits of precision at which to store rate metrics.*/
-# define OC_BIT_SCALE (6)
-/*The number of extra bits of precision at which to store RMSE metrics.
- This must be at least half OC_BIT_SCALE (rounded up).*/
-# define OC_RMSE_SCALE (5)
-/*The number of bins to partition statistics into.*/
-# define OC_SAD_BINS (24)
-/*The number of bits of precision to drop from SAD scores to assign them to a
- bin.*/
-# define OC_SAD_SHIFT (9)
-
-
-
-# if defined(OC_COLLECT_METRICS)
-struct oc_mode_metrics{
- double fragw;
- double satd;
- double rate;
- double rmse;
- double satd2;
- double satdrate;
- double rate2;
- double satdrmse;
- double rmse2;
+ogg_int16_t OC_MODE_LOGQ[OC_LOGQ_BINS][3][2]={
+ { {0x1F05,0x2101},{0x206E,0x2101},{0x206E,0x2101} },
+ { {0x1C9A,0x1EAC},{0x1E0E,0x1EAC},{0x1E0E,0x1EAC} },
+ { {0x1A31,0x1C48},{0x1B6F,0x1C48},{0x1B6F,0x1C48} },
+ { {0x17B0,0x19E7},{0x1938,0x19E7},{0x1938,0x19E7} },
+ { {0x152F,0x178F},{0x16AB,0x178F},{0x16AB,0x178F} },
+ { {0x12F1,0x1534},{0x145D,0x1534},{0x145D,0x1534} },
+ { {0x0FF3,0x1321},{0x11BE,0x1321},{0x11BE,0x1321} },
+ { {0x0E1F,0x1073},{0x0E93,0x1073},{0x0E93,0x1073} }
};
-
-int oc_has_mode_metrics;
-oc_mode_metrics OC_MODE_METRICS[64][3][2][OC_SAD_BINS];
-# endif
-
-
-
-struct oc_mode_rd{
- ogg_int16_t rate;
- ogg_int16_t rmse;
-};
-
-
# if !defined(OC_COLLECT_METRICS)
static const
# endif
-oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
+oc_mode_rd OC_MODE_RD_SATD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
{
{
/*Y' qi=0 INTRA*/
{
- { 87, -66},{ 132, 1611},{ 197, 3474},{ 285, 5130},
- { 376, 6419},{ 450, 7545},{ 521, 8587},{ 600, 9587},
- { 689,10498},{ 790,11348},{ 899,12158},{ 1030,12855},
- { 1166,13459},{ 1276,14052},{ 1353,14732},{ 1444,15425},
- { 1535,16101},{ 1609,16856},{ 1697,17532},{ 1823,17995},
- { 1962,18426},{ 2085,18919},{ 2201,19503},{ 2304,20307}
+ { 57, 1550},{ 121, 2460},{ 185, 3901},{ 336, 5189},
+ { 406, 6243},{ 501, 7329},{ 565, 8292},{ 674, 9257},
+ { 746,10219},{ 843,11056},{ 961,11822},{ 1120,12512},
+ { 1208,13233},{ 1394,13600},{ 1409,14381},{ 1492,15129},
+ { 1593,15804},{ 1639,16573},{ 1731,17161},{ 1844,17707},
+ { 1949,18300},{ 2073,18654},{ 2140,19465},{ 2278,19794}
},
/*Y' qi=0 INTER*/
{
- { 32, -105},{ 40, 1268},{ 54, 2919},{ 91, 4559},
- { 118, 6244},{ 132, 7932},{ 142, 9514},{ 149,10989},
- { 155,12375},{ 161,13679},{ 168,14958},{ 176,16215},
- { 187,17431},{ 196,18623},{ 207,19790},{ 218,20941},
- { 230,22083},{ 246,23213},{ 265,24333},{ 292,25439},
- { 328,26512},{ 372,27538},{ 427,28522},{ 494,29479}
+ { -18, 1274},{ 23, 2505},{ 32, 3612},{ 57, 5153},
+ { 79, 6636},{ 97, 8082},{ 109, 9505},{ 122,10924},
+ { 134,12293},{ 145,13634},{ 158,14942},{ 172,16212},
+ { 186,17422},{ 198,18604},{ 209,19757},{ 218,20875},
+ { 235,21980},{ 253,23056},{ 276,24121},{ 305,25184},
+ { 342,26202},{ 393,27140},{ 439,28140},{ 556,28659}
}
},
{
/*Cb qi=0 INTRA*/
{
- { 1, 6},{ 27, 368},{ 52, 738},{ 67, 1171},
- { 80, 1642},{ 99, 2134},{ 110, 2642},{ 112, 3144},
- { 126, 3578},{ 154, 3967},{ 167, 4387},{ 172, 4839},
- { 191, 5278},{ 208, 5666},{ 220, 6036},{ 223, 6398},
- { 227, 6814},{ 253, 7157},{ 284, 7403},{ 292, 7699},
- { 314, 7983},{ 339, 8203},{ 363, 8460},{ 399, 8919}
+ { 32, 1763},{ 56, 2150},{ 78, 2336},{ 88, 2608},
+ { 105, 2975},{ 121, 3297},{ 113, 3460},{ 126, 3993},
+ { 142, 4432},{ 177, 4733},{ 185, 5058},{ 194, 5447},
+ { 220, 5812},{ 227, 6202},{ 246, 6415},{ 269, 6821},
+ { 279, 7026},{ 313, 7313},{ 321, 7708},{ 316, 8021},
+ { 370, 8203},{ 389, 8573},{ 410, 8607},{ 431, 8816}
},
/*Cb qi=0 INTER*/
{
- { 68, -55},{ 63, 275},{ 58, 602},{ 53, 936},
- { 50, 1290},{ 54, 1691},{ 58, 2116},{ 62, 2553},
- { 67, 2992},{ 72, 3422},{ 78, 3843},{ 84, 4253},
- { 89, 4658},{ 94, 5062},{ 98, 5455},{ 100, 5848},
- { 102, 6231},{ 104, 6604},{ 104, 6982},{ 105, 7359},
- { 105, 7733},{ 104, 8104},{ 105, 8465},{ 111, 8828}
+ { 3, 282},{ 3, 1200},{ 3, 1605},{ 6, 2190},
+ { 15, 2519},{ 18, 2798},{ 21, 3115},{ 25, 3460},
+ { 33, 3839},{ 40, 4217},{ 47, 4592},{ 51, 4958},
+ { 56, 5326},{ 59, 5710},{ 63, 6066},{ 65, 6412},
+ { 67, 6762},{ 68, 7104},{ 70, 7461},{ 72, 7829},
+ { 77, 8200},{ 80, 8566},{ 86, 8906},{ 90, 9203}
}
},
{
/*Cr qi=0 INTRA*/
{
- { 1, 8},{ 23, 375},{ 47, 759},{ 63, 1220},
- { 71, 1693},{ 82, 2171},{ 94, 2652},{ 109, 3103},
- { 125, 3567},{ 133, 3995},{ 151, 4375},{ 168, 4819},
- { 174, 5244},{ 190, 5635},{ 215, 6005},{ 242, 6347},
- { 257, 6758},{ 280, 7068},{ 311, 7336},{ 326, 7652},
- { 346, 7968},{ 372, 8213},{ 388, 8515},{ 408, 9060}
+ { 27, 1720},{ 44, 1920},{ 66, 2255},{ 73, 2429},
+ { 95, 2988},{ 103, 3279},{ 123, 3691},{ 129, 4012},
+ { 151, 4415},{ 150, 4760},{ 183, 5008},{ 193, 5351},
+ { 211, 5788},{ 235, 6134},{ 263, 6400},{ 276, 6711},
+ { 291, 7100},{ 346, 7285},{ 329, 7616},{ 387, 7827},
+ { 361, 8214},{ 430, 8534},{ 429, 8608},{ 450, 8823}
},
/*Cr qi=0 INTER*/
{
- { 69, 0},{ 60, 314},{ 49, 624},{ 45, 943},
- { 45, 1285},{ 49, 1691},{ 55, 2130},{ 62, 2560},
- { 71, 2973},{ 79, 3385},{ 85, 3800},{ 89, 4207},
- { 92, 4620},{ 95, 5037},{ 96, 5436},{ 97, 5839},
- { 98, 6252},{ 99, 6653},{ 99, 7038},{ 103, 7426},
- { 107, 7810},{ 108, 8178},{ 107, 8539},{ 106, 8937}
- }
- }
- },
- {
- {
- /*Y' qi=1 INTRA*/
- {
- { 81, -71},{ 133, 1610},{ 203, 3460},{ 296, 5083},
- { 392, 6342},{ 467, 7454},{ 541, 8486},{ 625, 9466},
- { 716,10352},{ 823,11181},{ 940,11961},{ 1074,12643},
- { 1211,13233},{ 1324,13807},{ 1408,14489},{ 1504,15167},
- { 1598,15824},{ 1679,16544},{ 1788,17161},{ 1928,17579},
- { 2070,17991},{ 2202,18456},{ 2324,19021},{ 2425,19894}
- },
- /*Y' qi=1 INTER*/
- {
- { 34, 4},{ 40, 1307},{ 55, 2914},{ 93, 4555},
- { 120, 6243},{ 134, 7912},{ 144, 9468},{ 152,10918},
- { 158,12275},{ 164,13569},{ 171,14846},{ 180,16098},
- { 191,17310},{ 204,18484},{ 216,19636},{ 228,20779},
- { 242,21912},{ 261,23036},{ 286,24146},{ 320,25221},
- { 363,26265},{ 418,27261},{ 485,28203},{ 551,29148}
- }
- },
- {
- /*Cb qi=1 INTRA*/
- {
- { 1, 6},{ 28, 367},{ 52, 738},{ 68, 1172},
- { 86, 1644},{ 106, 2135},{ 115, 2642},{ 119, 3141},
- { 132, 3569},{ 157, 3951},{ 172, 4366},{ 177, 4819},
- { 194, 5258},{ 211, 5638},{ 224, 6006},{ 233, 6367},
- { 236, 6784},{ 258, 7121},{ 299, 7357},{ 319, 7637},
- { 337, 7921},{ 358, 8141},{ 381, 8367},{ 401, 8768}
- },
- /*Cb qi=1 INTER*/
- {
- { 95, -31},{ 81, 295},{ 67, 614},{ 53, 953},
- { 48, 1305},{ 51, 1700},{ 56, 2125},{ 61, 2563},
- { 67, 3008},{ 73, 3435},{ 79, 3844},{ 85, 4251},
- { 90, 4663},{ 95, 5073},{ 98, 5458},{ 100, 5844},
- { 101, 6231},{ 102, 6606},{ 102, 6980},{ 103, 7347},
- { 104, 7726},{ 105, 8096},{ 105, 8453},{ 105, 8789}
- }
- },
- {
- /*Cr qi=1 INTRA*/
- {
- { 1, 8},{ 25, 375},{ 50, 759},{ 65, 1221},
- { 74, 1695},{ 86, 2172},{ 101, 2651},{ 117, 3101},
- { 129, 3561},{ 135, 3985},{ 153, 4368},{ 171, 4807},
- { 182, 5223},{ 202, 5608},{ 225, 5964},{ 251, 6300},
- { 271, 6697},{ 295, 6978},{ 324, 7235},{ 348, 7558},
- { 367, 7877},{ 394, 8101},{ 413, 8386},{ 409, 8945}
- },
- /*Cr qi=1 INTER*/
- {
- { 66, 11},{ 59, 323},{ 51, 631},{ 44, 949},
- { 44, 1292},{ 49, 1703},{ 56, 2140},{ 62, 2566},
- { 69, 2991},{ 77, 3397},{ 84, 3799},{ 89, 4211},
- { 93, 4634},{ 94, 5049},{ 95, 5444},{ 96, 5854},
- { 94, 6260},{ 95, 6640},{ 96, 7032},{ 101, 7423},
- { 104, 7790},{ 105, 8158},{ 109, 8527},{ 108, 8872}
- }
- }
- },
- {
- {
- /*Y' qi=2 INTRA*/
- {
- { 87, -72},{ 139, 1607},{ 213, 3426},{ 315, 4992},
- { 416, 6217},{ 495, 7315},{ 574, 8317},{ 666, 9265},
- { 763,10124},{ 875,10906},{ 1001,11654},{ 1147,12305},
- { 1289,12865},{ 1407,13424},{ 1503,14076},{ 1610,14724},
- { 1720,15342},{ 1815,16020},{ 1937,16579},{ 2084,16981},
- { 2236,17371},{ 2385,17779},{ 2536,18250},{ 2689,18931}
- },
- /*Y' qi=2 INTER*/
- {
- { 30, -2},{ 40, 1308},{ 57, 2921},{ 96, 4567},
- { 122, 6260},{ 136, 7902},{ 148, 9418},{ 156,10826},
- { 162,12157},{ 169,13448},{ 177,14709},{ 188,15938},
- { 200,17133},{ 213,18295},{ 228,19433},{ 245,20564},
- { 264,21685},{ 289,22790},{ 323,23876},{ 368,24916},
- { 427,25906},{ 499,26837},{ 585,27700},{ 680,28514}
- }
- },
- {
- /*Cb qi=2 INTRA*/
- {
- { 1, 6},{ 30, 367},{ 58, 738},{ 77, 1172},
- { 93, 1645},{ 111, 2137},{ 123, 2642},{ 126, 3133},
- { 136, 3553},{ 162, 3934},{ 178, 4352},{ 183, 4803},
- { 199, 5231},{ 220, 5596},{ 235, 5957},{ 245, 6314},
- { 256, 6718},{ 286, 7048},{ 320, 7285},{ 336, 7568},
- { 366, 7829},{ 387, 8045},{ 405, 8261},{ 445, 8550}
- },
- /*Cb qi=2 INTER*/
- {
- { 115, -61},{ 93, 277},{ 71, 609},{ 54, 963},
- { 49, 1329},{ 53, 1715},{ 58, 2138},{ 63, 2583},
- { 69, 3017},{ 75, 3442},{ 81, 3857},{ 88, 4263},
- { 93, 4667},{ 96, 5065},{ 101, 5451},{ 101, 5832},
- { 102, 6213},{ 103, 6593},{ 103, 6968},{ 104, 7336},
- { 104, 7710},{ 105, 8076},{ 106, 8440},{ 106, 8822}
- }
- },
- {
- /*Cr qi=2 INTRA*/
- {
- { 1, 8},{ 27, 375},{ 54, 759},{ 70, 1222},
- { 79, 1696},{ 89, 2173},{ 106, 2652},{ 123, 3098},
- { 135, 3553},{ 143, 3972},{ 161, 4348},{ 181, 4782},
- { 194, 5189},{ 213, 5565},{ 235, 5907},{ 266, 6229},
- { 286, 6618},{ 311, 6897},{ 339, 7152},{ 362, 7454},
- { 392, 7721},{ 416, 7946},{ 429, 8227},{ 458, 8540}
- },
- /*Cr qi=2 INTER*/
- {
- { 74, 20},{ 63, 330},{ 51, 635},{ 44, 942},
- { 47, 1287},{ 54, 1710},{ 59, 2147},{ 65, 2571},
- { 72, 2996},{ 79, 3413},{ 86, 3820},{ 91, 4230},
- { 93, 4642},{ 95, 5046},{ 95, 5442},{ 95, 5839},
- { 96, 6243},{ 97, 6641},{ 99, 7021},{ 101, 7396},
- { 103, 7764},{ 106, 8138},{ 109, 8507},{ 114, 8851}
- }
- }
- },
- {
- {
- /*Y' qi=3 INTRA*/
- {
- { 91, -67},{ 141, 1606},{ 219, 3405},{ 328, 4929},
- { 433, 6122},{ 515, 7209},{ 598, 8204},{ 693, 9145},
- { 796, 9986},{ 912,10756},{ 1045,11471},{ 1200,12079},
- { 1345,12640},{ 1471,13179},{ 1571,13809},{ 1678,14450},
- { 1798,15047},{ 1905,15701},{ 2043,16205},{ 2202,16569},
- { 2351,16971},{ 2501,17393},{ 2660,17851},{ 2825,18455}
- },
- /*Y' qi=3 INTER*/
- {
- { 53, -164},{ 38, 1314},{ 59, 2917},{ 99, 4563},
- { 124, 6253},{ 139, 7882},{ 150, 9375},{ 159,10749},
- { 166,12059},{ 173,13349},{ 183,14608},{ 194,15826},
- { 208,17003},{ 223,18150},{ 240,19287},{ 259,20411},
- { 284,21508},{ 317,22593},{ 359,23656},{ 414,24671},
- { 483,25634},{ 569,26519},{ 670,27332},{ 786,28072}
- }
- },
- {
- /*Cb qi=3 INTRA*/
- {
- { 1, 5},{ 31, 367},{ 58, 739},{ 78, 1173},
- { 96, 1645},{ 113, 2134},{ 125, 2638},{ 133, 3127},
- { 148, 3542},{ 171, 3915},{ 184, 4328},{ 192, 4776},
- { 209, 5197},{ 230, 5556},{ 245, 5909},{ 252, 6261},
- { 272, 6641},{ 304, 6942},{ 330, 7184},{ 342, 7477},
- { 380, 7736},{ 404, 7962},{ 428, 8151},{ 469, 8430}
- },
- /*Cb qi=3 INTER*/
- {
- { 86, -29},{ 72, 296},{ 58, 618},{ 46, 964},
- { 47, 1338},{ 51, 1743},{ 56, 2158},{ 63, 2594},
- { 69, 3035},{ 77, 3455},{ 84, 3859},{ 89, 4266},
- { 94, 4673},{ 98, 5074},{ 101, 5460},{ 101, 5842},
- { 101, 6217},{ 101, 6593},{ 102, 6964},{ 104, 7325},
- { 103, 7696},{ 103, 8056},{ 104, 8430},{ 103, 8792}
- }
- },
- {
- /*Cr qi=3 INTRA*/
- {
- { 1, 8},{ 27, 374},{ 56, 759},{ 74, 1221},
- { 83, 1696},{ 96, 2173},{ 113, 2650},{ 127, 3091},
- { 140, 3542},{ 151, 3960},{ 164, 4334},{ 188, 4764},
- { 208, 5144},{ 224, 5493},{ 250, 5841},{ 278, 6162},
- { 298, 6548},{ 334, 6816},{ 365, 7045},{ 388, 7343},
- { 419, 7613},{ 443, 7836},{ 455, 8105},{ 484, 8445}
- },
- /*Cr qi=3 INTER*/
- {
- { 76, 26},{ 65, 332},{ 53, 638},{ 45, 945},
- { 45, 1304},{ 53, 1725},{ 60, 2153},{ 68, 2584},
- { 74, 3007},{ 81, 3425},{ 87, 3844},{ 91, 4253},
- { 94, 4657},{ 95, 5061},{ 94, 5462},{ 94, 5856},
- { 95, 6250},{ 96, 6635},{ 97, 7014},{ 101, 7393},
- { 104, 7761},{ 106, 8137},{ 109, 8506},{ 111, 8823}
- }
- }
- },
- {
- {
- /*Y' qi=4 INTRA*/
- {
- { 80, -67},{ 143, 1603},{ 227, 3378},{ 344, 4861},
- { 454, 6026},{ 537, 7104},{ 626, 8089},{ 725, 9006},
- { 830, 9827},{ 950,10581},{ 1089,11270},{ 1257,11826},
- { 1409,12366},{ 1535,12912},{ 1640,13528},{ 1753,14173},
- { 1884,14756},{ 2007,15368},{ 2148,15852},{ 2307,16212},
- { 2464,16591},{ 2614,17019},{ 2785,17455},{ 2970,17963}
- },
- /*Y' qi=4 INTER*/
- {
- { 50, -145},{ 38, 1324},{ 61, 2921},{ 102, 4566},
- { 127, 6248},{ 142, 7845},{ 154, 9300},{ 163,10656},
- { 169,11965},{ 177,13246},{ 188,14495},{ 202,15702},
- { 218,16864},{ 236,18003},{ 256,19124},{ 278,20233},
- { 307,21330},{ 347,22398},{ 398,23437},{ 463,24429},
- { 546,25343},{ 649,26170},{ 767,26935},{ 888,27674}
- }
- },
- {
- /*Cb qi=4 INTRA*/
- {
- { 1, 5},{ 33, 367},{ 61, 739},{ 80, 1173},
- { 98, 1646},{ 114, 2136},{ 126, 2639},{ 137, 3124},
- { 152, 3535},{ 176, 3903},{ 194, 4307},{ 206, 4753},
- { 222, 5165},{ 242, 5508},{ 260, 5857},{ 272, 6205},
- { 294, 6559},{ 332, 6848},{ 356, 7104},{ 364, 7389},
- { 396, 7637},{ 415, 7878},{ 446, 8064},{ 506, 8294}
- },
- /*Cb qi=4 INTER*/
- {
- { 86, -15},{ 73, 308},{ 60, 627},{ 46, 967},
- { 47, 1343},{ 51, 1754},{ 56, 2183},{ 63, 2615},
- { 70, 3044},{ 79, 3459},{ 85, 3866},{ 90, 4276},
- { 94, 4686},{ 97, 5088},{ 100, 5467},{ 102, 5837},
- { 102, 6205},{ 101, 6569},{ 103, 6939},{ 104, 7317},
- { 105, 7690},{ 107, 8043},{ 107, 8394},{ 111, 8736}
- }
- },
- {
- /*Cr qi=4 INTRA*/
- {
- { 1, 7},{ 28, 375},{ 57, 759},{ 79, 1221},
- { 92, 1697},{ 105, 2174},{ 122, 2648},{ 135, 3085},
- { 146, 3530},{ 157, 3947},{ 171, 4316},{ 195, 4737},
- { 218, 5117},{ 239, 5445},{ 268, 5767},{ 295, 6074},
- { 315, 6460},{ 355, 6735},{ 392, 6933},{ 418, 7218},
- { 448, 7495},{ 471, 7688},{ 481, 7954},{ 504, 8313}
- },
- /*Cr qi=4 INTER*/
- {
- { 68, 28},{ 57, 334},{ 47, 639},{ 43, 953},
- { 48, 1314},{ 54, 1736},{ 59, 2169},{ 69, 2592},
- { 78, 3017},{ 84, 3434},{ 88, 3850},{ 92, 4260},
- { 95, 4663},{ 96, 5068},{ 95, 5455},{ 95, 5839},
- { 96, 6243},{ 97, 6626},{ 98, 7006},{ 101, 7390},
- { 104, 7755},{ 108, 8115},{ 111, 8471},{ 110, 8825}
- }
- }
- },
- {
- {
- /*Y' qi=5 INTRA*/
- {
- { 84, -69},{ 147, 1599},{ 237, 3350},{ 360, 4796},
- { 475, 5934},{ 562, 6992},{ 657, 7953},{ 765, 8837},
- { 874, 9641},{ 998,10384},{ 1146,11047},{ 1322,11572},
- { 1484,12076},{ 1617,12609},{ 1731,13203},{ 1856,13806},
- { 1995,14367},{ 2132,14936},{ 2289,15386},{ 2460,15721},
- { 2635,16066},{ 2802,16442},{ 2980,16805},{ 3177,17272}
- },
- /*Y' qi=5 INTER*/
- {
- { 38, -86},{ 37, 1349},{ 64, 2920},{ 105, 4563},
- { 129, 6236},{ 145, 7809},{ 158, 9236},{ 167,10572},
- { 174,11871},{ 182,13141},{ 195,14368},{ 212,15558},
- { 230,16706},{ 250,17828},{ 274,18944},{ 303,20041},
- { 342,21116},{ 394,22152},{ 460,23144},{ 543,24073},
- { 648,24919},{ 773,25673},{ 922,26323},{ 1084,26924}
- }
- },
- {
- /*Cb qi=5 INTRA*/
- {
- { 1, 5},{ 34, 367},{ 63, 739},{ 82, 1174},
- { 102, 1647},{ 119, 2137},{ 134, 2639},{ 145, 3121},
- { 161, 3529},{ 189, 3891},{ 207, 4290},{ 216, 4721},
- { 232, 5113},{ 258, 5455},{ 277, 5798},{ 294, 6124},
- { 322, 6427},{ 352, 6697},{ 370, 6982},{ 384, 7283},
- { 423, 7529},{ 448, 7766},{ 478, 7943},{ 527, 8151}
- },
- /*Cb qi=5 INTER*/
- {
- { 83, -49},{ 69, 284},{ 55, 611},{ 48, 961},
- { 49, 1355},{ 52, 1769},{ 58, 2191},{ 65, 2616},
- { 73, 3041},{ 80, 3460},{ 87, 3868},{ 92, 4276},
- { 95, 4682},{ 98, 5077},{ 100, 5459},{ 102, 5827},
- { 102, 6200},{ 102, 6568},{ 103, 6930},{ 103, 7303},
- { 104, 7672},{ 106, 8032},{ 106, 8391},{ 106, 8727}
- }
- },
- {
- /*Cr qi=5 INTRA*/
- {
- { 1, 8},{ 28, 375},{ 57, 760},{ 81, 1222},
- { 99, 1696},{ 111, 2175},{ 125, 2648},{ 140, 3079},
- { 152, 3520},{ 162, 3927},{ 179, 4294},{ 203, 4714},
- { 225, 5080},{ 254, 5389},{ 286, 5703},{ 318, 5997},
- { 342, 6364},{ 380, 6640},{ 416, 6837},{ 445, 7103},
- { 473, 7370},{ 497, 7562},{ 514, 7811},{ 549, 8148}
- },
- /*Cr qi=5 INTER*/
- {
- { 60, 6},{ 54, 323},{ 46, 638},{ 43, 958},
- { 45, 1329},{ 54, 1749},{ 61, 2175},{ 70, 2600},
- { 79, 3021},{ 85, 3437},{ 89, 3847},{ 93, 4254},
- { 95, 4660},{ 96, 5065},{ 95, 5456},{ 95, 5849},
- { 96, 6243},{ 96, 6621},{ 97, 6996},{ 101, 7366},
- { 104, 7722},{ 107, 8088},{ 111, 8448},{ 119, 8816}
- }
- }
- },
- {
- {
- /*Y' qi=6 INTRA*/
- {
- { 88, -69},{ 151, 1593},{ 251, 3294},{ 387, 4681},
- { 507, 5790},{ 601, 6837},{ 702, 7787},{ 813, 8648},
- { 927, 9427},{ 1059,10152},{ 1213,10787},{ 1399,11284},
- { 1568,11781},{ 1705,12312},{ 1823,12890},{ 1957,13482},
- { 2106,14036},{ 2249,14600},{ 2411,15042},{ 2588,15359},
- { 2772,15699},{ 2947,16062},{ 3127,16429},{ 3320,16849}
- },
- /*Y' qi=6 INTER*/
- {
- { 44, -80},{ 36, 1346},{ 69, 2919},{ 111, 4563},
- { 136, 6216},{ 154, 7746},{ 168, 9139},{ 178,10461},
- { 185,11747},{ 195,13007},{ 211,14229},{ 230,15408},
- { 250,16547},{ 274,17663},{ 302,18769},{ 339,19851},
- { 386,20907},{ 446,21933},{ 527,22884},{ 631,23746},
- { 760,24512},{ 914,25178},{ 1087,25758},{ 1278,26262}
- }
- },
- {
- /*Cb qi=6 INTRA*/
- {
- { 1, 4},{ 36, 367},{ 66, 739},{ 84, 1174},
- { 105, 1648},{ 126, 2139},{ 140, 2639},{ 149, 3116},
- { 164, 3523},{ 194, 3880},{ 217, 4271},{ 226, 4694},
- { 243, 5077},{ 270, 5407},{ 291, 5742},{ 310, 6061},
- { 340, 6340},{ 373, 6609},{ 394, 6890},{ 409, 7189},
- { 444, 7434},{ 469, 7652},{ 499, 7853},{ 559, 8135}
- },
- /*Cb qi=6 INTER*/
- {
- { 68, -46},{ 60, 291},{ 50, 623},{ 49, 971},
- { 50, 1357},{ 55, 1781},{ 61, 2211},{ 69, 2634},
- { 78, 3052},{ 86, 3466},{ 91, 3882},{ 95, 4292},
- { 98, 4691},{ 101, 5080},{ 102, 5458},{ 103, 5830},
- { 103, 6192},{ 104, 6554},{ 104, 6916},{ 106, 7278},
- { 108, 7641},{ 110, 8004},{ 112, 8371},{ 112, 8758}
- }
- },
- {
- /*Cr qi=6 INTRA*/
- {
- { 1, 8},{ 29, 375},{ 59, 760},{ 84, 1223},
- { 99, 1698},{ 112, 2176},{ 129, 2647},{ 143, 3076},
- { 156, 3510},{ 168, 3906},{ 189, 4269},{ 220, 4682},
- { 241, 5047},{ 266, 5342},{ 299, 5649},{ 331, 5954},
- { 357, 6309},{ 393, 6579},{ 431, 6765},{ 467, 6997},
- { 501, 7276},{ 520, 7488},{ 525, 7749},{ 548, 8146}
- },
- /*Cr qi=6 INTER*/
- {
- { 94, 31},{ 69, 335},{ 47, 641},{ 43, 967},
- { 50, 1350},{ 57, 1772},{ 65, 2197},{ 74, 2625},
- { 83, 3043},{ 90, 3454},{ 94, 3867},{ 97, 4273},
- { 98, 4671},{ 99, 5068},{ 99, 5461},{ 98, 5857},
- { 98, 6245},{ 99, 6610},{ 103, 6975},{ 105, 7345},
- { 108, 7712},{ 111, 8073},{ 113, 8415},{ 119, 8768}
- }
- }
- },
- {
- {
- /*Y' qi=7 INTRA*/
- {
- { 92, -70},{ 156, 1590},{ 261, 3267},{ 403, 4618},
- { 529, 5704},{ 628, 6730},{ 736, 7657},{ 856, 8491},
- { 978, 9246},{ 1118, 9943},{ 1281,10550},{ 1472,11028},
- { 1645,11507},{ 1793,12008},{ 1924,12565},{ 2067,13130},
- { 2229,13638},{ 2388,14160},{ 2558,14584},{ 2744,14886},
- { 2932,15194},{ 3116,15531},{ 3311,15858},{ 3538,16197}
- },
- /*Y' qi=7 INTER*/
- {
- { 43, -8},{ 36, 1351},{ 71, 2923},{ 112, 4568},
- { 138, 6201},{ 157, 7705},{ 171, 9083},{ 181,10390},
- { 189,11664},{ 202,12910},{ 220,14121},{ 241,15281},
- { 266,16401},{ 295,17507},{ 328,18608},{ 371,19677},
- { 430,20701},{ 508,21676},{ 604,22588},{ 727,23397},
- { 878,24093},{ 1055,24690},{ 1263,25151},{ 1496,25504}
- }
- },
- {
- /*Cb qi=7 INTRA*/
- {
- { 1, 5},{ 40, 367},{ 72, 740},{ 89, 1175},
- { 108, 1649},{ 129, 2140},{ 143, 2637},{ 154, 3110},
- { 169, 3507},{ 198, 3860},{ 224, 4237},{ 235, 4652},
- { 253, 5037},{ 282, 5358},{ 307, 5674},{ 329, 5986},
- { 361, 6273},{ 393, 6527},{ 419, 6777},{ 435, 7078},
- { 467, 7342},{ 495, 7554},{ 529, 7757},{ 591, 8053}
- },
- /*Cb qi=7 INTER*/
- {
- { 79, -33},{ 68, 299},{ 56, 627},{ 50, 978},
- { 51, 1366},{ 55, 1786},{ 61, 2213},{ 70, 2642},
- { 80, 3062},{ 87, 3474},{ 92, 3886},{ 96, 4292},
- { 99, 4684},{ 102, 5072},{ 103, 5450},{ 104, 5814},
- { 104, 6176},{ 104, 6538},{ 107, 6905},{ 110, 7270},
- { 110, 7625},{ 110, 7978},{ 111, 8340},{ 117, 8674}
- }
- },
- {
- /*Cr qi=7 INTRA*/
- {
- { 2, 7},{ 31, 375},{ 62, 760},{ 87, 1223},
- { 103, 1698},{ 115, 2175},{ 131, 2644},{ 147, 3066},
- { 161, 3494},{ 175, 3889},{ 199, 4250},{ 229, 4653},
- { 250, 5001},{ 279, 5275},{ 311, 5577},{ 343, 5889},
- { 376, 6227},{ 417, 6486},{ 457, 6689},{ 484, 6925},
- { 518, 7174},{ 544, 7393},{ 549, 7662},{ 577, 8050}
- },
- /*Cr qi=7 INTER*/
- {
- { 89, 22},{ 62, 332},{ 45, 641},{ 47, 976},
- { 52, 1363},{ 59, 1779},{ 67, 2203},{ 76, 2628},
- { 84, 3046},{ 90, 3460},{ 94, 3875},{ 98, 4272},
- { 99, 4666},{ 98, 5063},{ 98, 5459},{ 98, 5849},
- { 99, 6226},{ 101, 6594},{ 104, 6957},{ 109, 7324},
- { 109, 7686},{ 111, 8042},{ 115, 8379},{ 119, 8699}
- }
- }
- },
- {
- {
- /*Y' qi=8 INTRA*/
- {
- { 91, -69},{ 160, 1585},{ 274, 3226},{ 423, 4538},
- { 557, 5596},{ 664, 6595},{ 778, 7506},{ 905, 8319},
- { 1038, 9035},{ 1186, 9701},{ 1355,10292},{ 1554,10754},
- { 1739,11196},{ 1904,11639},{ 2047,12184},{ 2194,12763},
- { 2361,13256},{ 2529,13753},{ 2709,14155},{ 2902,14433},
- { 3100,14723},{ 3292,15026},{ 3489,15327},{ 3714,15705}
- },
- /*Y' qi=8 INTER*/
- {
- { 32, -157},{ 33, 1346},{ 74, 2914},{ 116, 4554},
- { 142, 6172},{ 162, 7648},{ 177, 9004},{ 186,10300},
- { 196,11570},{ 210,12808},{ 231,14001},{ 256,15150},
- { 285,16259},{ 319,17352},{ 359,18435},{ 415,19475},
- { 489,20470},{ 584,21400},{ 703,22246},{ 852,22968},
- { 1038,23556},{ 1253,24032},{ 1503,24367},{ 1778,24628}
- }
- },
- {
- /*Cb qi=8 INTRA*/
- {
- { 1, 4},{ 42, 367},{ 75, 740},{ 93, 1176},
- { 111, 1649},{ 128, 2139},{ 144, 2635},{ 157, 3103},
- { 174, 3494},{ 206, 3844},{ 233, 4207},{ 251, 4605},
- { 277, 4980},{ 304, 5284},{ 335, 5584},{ 359, 5888},
- { 393, 6152},{ 432, 6398},{ 455, 6656},{ 471, 6956},
- { 502, 7193},{ 528, 7405},{ 562, 7630},{ 603, 7922}
- },
- /*Cb qi=8 INTER*/
- {
- { 77, -37},{ 68, 299},{ 58, 632},{ 50, 991},
- { 50, 1382},{ 55, 1799},{ 62, 2226},{ 73, 2647},
- { 82, 3066},{ 90, 3480},{ 94, 3891},{ 96, 4296},
- { 98, 4687},{ 101, 5073},{ 103, 5456},{ 104, 5817},
- { 105, 6170},{ 106, 6523},{ 107, 6886},{ 108, 7250},
- { 109, 7600},{ 110, 7955},{ 111, 8305},{ 112, 8641}
- }
- },
- {
- /*Cr qi=8 INTRA*/
- {
- { 2, 7},{ 33, 375},{ 64, 760},{ 92, 1224},
- { 111, 1700},{ 122, 2173},{ 137, 2637},{ 156, 3055},
- { 172, 3476},{ 186, 3856},{ 211, 4211},{ 242, 4597},
- { 263, 4939},{ 292, 5214},{ 335, 5489},{ 376, 5772},
- { 406, 6099},{ 440, 6378},{ 483, 6578},{ 517, 6797},
- { 550, 7049},{ 571, 7283},{ 583, 7560},{ 618, 7967}
- },
- /*Cr qi=8 INTER*/
- {
- { 74, 25},{ 58, 328},{ 43, 637},{ 45, 980},
- { 51, 1371},{ 59, 1788},{ 69, 2207},{ 79, 2630},
- { 86, 3051},{ 91, 3470},{ 95, 3880},{ 97, 4280},
- { 98, 4680},{ 97, 5074},{ 96, 5456},{ 97, 5839},
- { 99, 6219},{ 101, 6583},{ 103, 6945},{ 106, 7312},
- { 110, 7671},{ 114, 8009},{ 115, 8345},{ 117, 8686}
+ { 4, 439},{ 2, 1131},{ 3, 1593},{ 6, 2130},
+ { 14, 2535},{ 17, 2786},{ 21, 3128},{ 27, 3494},
+ { 35, 3875},{ 42, 4256},{ 48, 4637},{ 53, 5019},
+ { 57, 5395},{ 61, 5777},{ 64, 6156},{ 66, 6512},
+ { 68, 6853},{ 71, 7183},{ 77, 7511},{ 81, 7841},
+ { 83, 8192},{ 88, 8510},{ 93, 8834},{ 98, 9138}
}
}
},
@@ -616,557 +93,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=9 INTRA*/
{
- { 104, -68},{ 164, 1580},{ 288, 3173},{ 448, 4439},
- { 587, 5485},{ 702, 6465},{ 824, 7351},{ 958, 8148},
- { 1096, 8845},{ 1253, 9480},{ 1432,10047},{ 1640,10494},
- { 1835,10926},{ 2015,11350},{ 2166,11871},{ 2321,12428},
- { 2508,12876},{ 2684,13345},{ 2866,13741},{ 3069,13991},
- { 3281,14243},{ 3487,14518},{ 3689,14813},{ 3911,15175}
+ { 76, 777},{ 178, 1995},{ 340, 3162},{ 591, 4097},
+ { 746, 4973},{ 916, 5847},{ 1047, 6687},{ 1218, 7430},
+ { 1385, 8079},{ 1566, 8685},{ 1755, 9167},{ 1992, 9572},
+ { 2164,10023},{ 2395,10270},{ 2536,10755},{ 2694,11285},
+ { 2895,11580},{ 3029,12143},{ 3182,12543},{ 3377,12800},
+ { 3525,13228},{ 3718,13463},{ 3878,13852},{ 4077,14001}
},
/*Y' qi=9 INTER*/
{
- { 47, -140},{ 34, 1348},{ 77, 2915},{ 119, 4552},
- { 145, 6150},{ 166, 7600},{ 182, 8936},{ 192,10221},
- { 203,11482},{ 220,12711},{ 244,13886},{ 274,15012},
- { 308,16111},{ 349,17190},{ 401,18244},{ 470,19257},
- { 561,20209},{ 680,21069},{ 830,21822},{ 1010,22463},
- { 1227,22971},{ 1482,23328},{ 1769,23544},{ 2077,23655}
+ { 10, 770},{ 45, 1845},{ 59, 3227},{ 99, 4708},
+ { 135, 6092},{ 164, 7425},{ 190, 8729},{ 218, 9991},
+ { 246,11234},{ 281,12427},{ 315,13573},{ 354,14678},
+ { 402,15734},{ 467,16728},{ 543,17709},{ 639,18610},
+ { 736,19503},{ 855,20312},{ 995,21033},{ 1151,21656},
+ { 1341,22130},{ 1525,22582},{ 1735,22922},{ 1922,23102}
}
},
{
/*Cb qi=9 INTRA*/
{
- { 1, 5},{ 43, 367},{ 76, 740},{ 95, 1176},
- { 114, 1649},{ 135, 2138},{ 153, 2629},{ 165, 3091},
- { 184, 3481},{ 217, 3831},{ 244, 4187},{ 260, 4572},
- { 290, 4930},{ 320, 5231},{ 351, 5521},{ 379, 5812},
- { 414, 6055},{ 452, 6307},{ 483, 6564},{ 502, 6848},
- { 525, 7115},{ 554, 7321},{ 589, 7533},{ 626, 7833}
+ { 41, 1227},{ 70, 1452},{ 102, 1697},{ 110, 1967},
+ { 134, 2326},{ 153, 2695},{ 160, 3007},{ 196, 3393},
+ { 232, 3769},{ 266, 4067},{ 297, 4376},{ 326, 4728},
+ { 351, 5040},{ 390, 5299},{ 398, 5538},{ 443, 5900},
+ { 448, 6107},{ 506, 6370},{ 519, 6636},{ 525, 6953},
+ { 567, 7177},{ 625, 7386},{ 622, 7613},{ 654, 7764}
},
/*Cb qi=9 INTER*/
{
- { 101, -43},{ 81, 298},{ 62, 637},{ 49, 989},
- { 51, 1381},{ 56, 1806},{ 65, 2231},{ 74, 2653},
- { 84, 3071},{ 91, 3482},{ 95, 3892},{ 97, 4293},
- { 99, 4684},{ 101, 5066},{ 103, 5437},{ 103, 5793},
- { 103, 6148},{ 104, 6511},{ 105, 6867},{ 107, 7221},
- { 110, 7572},{ 111, 7926},{ 112, 8283},{ 116, 8625}
+ { 7, 377},{ 2, 1102},{ 7, 1262},{ 19, 1693},
+ { 22, 1957},{ 27, 2302},{ 35, 2654},{ 43, 3034},
+ { 52, 3431},{ 58, 3826},{ 63, 4207},{ 67, 4570},
+ { 71, 4927},{ 75, 5283},{ 79, 5624},{ 82, 5944},
+ { 85, 6279},{ 88, 6616},{ 94, 6955},{ 102, 7284},
+ { 108, 7622},{ 116, 7944},{ 124, 8293},{ 133, 8568}
}
},
{
/*Cr qi=9 INTRA*/
{
- { 2, 7},{ 35, 375},{ 66, 761},{ 93, 1224},
- { 112, 1700},{ 126, 2173},{ 144, 2633},{ 165, 3047},
- { 183, 3458},{ 199, 3835},{ 224, 4191},{ 257, 4558},
- { 283, 4887},{ 309, 5176},{ 351, 5446},{ 397, 5713},
- { 433, 6017},{ 469, 6283},{ 508, 6480},{ 546, 6687},
- { 579, 6945},{ 600, 7182},{ 610, 7434},{ 623, 7793}
+ { 38, 1217},{ 61, 1473},{ 88, 1650},{ 100, 1908},
+ { 137, 2400},{ 147, 2777},{ 176, 3149},{ 205, 3433},
+ { 227, 3772},{ 249, 4092},{ 286, 4370},{ 313, 4746},
+ { 342, 5053},{ 368, 5261},{ 411, 5530},{ 442, 5859},
+ { 494, 6061},{ 526, 6340},{ 532, 6646},{ 580, 6799},
+ { 567, 7203},{ 649, 7357},{ 625, 7559},{ 660, 7709}
},
/*Cr qi=9 INTER*/
{
- { 77, 15},{ 57, 330},{ 45, 640},{ 48, 980},
- { 54, 1380},{ 61, 1802},{ 70, 2220},{ 80, 2639},
- { 87, 3057},{ 92, 3474},{ 94, 3882},{ 98, 4282},
- { 98, 4675},{ 97, 5062},{ 97, 5450},{ 98, 5829},
- { 100, 6197},{ 101, 6561},{ 104, 6927},{ 107, 7289},
- { 113, 7638},{ 117, 7978},{ 119, 8311},{ 117, 8629}
- }
- }
- },
- {
- {
- /*Y' qi=10 INTRA*/
- {
- { 101, -69},{ 168, 1574},{ 299, 3143},{ 465, 4386},
- { 610, 5410},{ 736, 6353},{ 866, 7207},{ 1006, 7982},
- { 1153, 8655},{ 1319, 9261},{ 1504, 9812},{ 1719,10248},
- { 1928,10653},{ 2116,11056},{ 2282,11550},{ 2458,12070},
- { 2654,12492},{ 2846,12923},{ 3043,13291},{ 3249,13537},
- { 3466,13764},{ 3682,13999},{ 3896,14268},{ 4145,14548}
- },
- /*Y' qi=10 INTER*/
- {
- { 48, -94},{ 34, 1355},{ 81, 2920},{ 124, 4545},
- { 151, 6113},{ 174, 7532},{ 190, 8850},{ 201,10125},
- { 214,11379},{ 235,12591},{ 264,13745},{ 299,14859},
- { 338,15948},{ 388,17008},{ 456,18029},{ 546,18988},
- { 661,19877},{ 808,20666},{ 993,21321},{ 1218,21835},
- { 1481,22203},{ 1783,22420},{ 2117,22504},{ 2469,22481}
- }
- },
- {
- /*Cb qi=10 INTRA*/
- {
- { 2, 4},{ 44, 367},{ 79, 740},{ 99, 1178},
- { 117, 1652},{ 137, 2141},{ 156, 2630},{ 170, 3089},
- { 192, 3474},{ 227, 3813},{ 259, 4157},{ 282, 4526},
- { 310, 4860},{ 342, 5140},{ 377, 5425},{ 400, 5714},
- { 436, 5952},{ 475, 6194},{ 496, 6468},{ 522, 6748},
- { 559, 6996},{ 587, 7216},{ 617, 7433},{ 673, 7678}
- },
- /*Cb qi=10 INTER*/
- {
- { 87, -37},{ 72, 301},{ 58, 636},{ 49, 995},
- { 51, 1394},{ 57, 1819},{ 66, 2241},{ 78, 2660},
- { 87, 3074},{ 93, 3482},{ 97, 3891},{ 99, 4294},
- { 101, 4678},{ 103, 5050},{ 105, 5414},{ 106, 5773},
- { 107, 6134},{ 108, 6485},{ 110, 6832},{ 113, 7187},
- { 113, 7547},{ 114, 7887},{ 117, 8230},{ 112, 8590}
- }
- },
- {
- /*Cr qi=10 INTRA*/
- {
- { 2, 7},{ 38, 375},{ 69, 761},{ 96, 1224},
- { 116, 1701},{ 131, 2175},{ 148, 2634},{ 168, 3041},
- { 190, 3439},{ 211, 3802},{ 238, 4151},{ 271, 4506},
- { 297, 4824},{ 331, 5103},{ 373, 5360},{ 415, 5632},
- { 459, 5928},{ 500, 6176},{ 535, 6386},{ 573, 6586},
- { 608, 6834},{ 629, 7079},{ 642, 7337},{ 686, 7680}
- },
- /*Cr qi=10 INTER*/
- {
- { 81, 34},{ 63, 333},{ 50, 633},{ 48, 987},
- { 53, 1397},{ 61, 1820},{ 71, 2237},{ 83, 2651},
- { 91, 3065},{ 95, 3479},{ 98, 3882},{ 100, 4279},
- { 101, 4673},{ 101, 5054},{ 100, 5429},{ 101, 5801},
- { 102, 6173},{ 104, 6541},{ 108, 6904},{ 110, 7264},
- { 114, 7609},{ 119, 7945},{ 123, 8275},{ 128, 8615}
- }
- }
- },
- {
- {
- /*Y' qi=11 INTRA*/
- {
- { 110, -66},{ 176, 1564},{ 316, 3087},{ 492, 4296},
- { 645, 5299},{ 781, 6217},{ 924, 7039},{ 1075, 7776},
- { 1232, 8421},{ 1410, 9005},{ 1607, 9532},{ 1834, 9929},
- { 2053,10300},{ 2249,10697},{ 2427,11184},{ 2619,11682},
- { 2826,12083},{ 3019,12508},{ 3225,12869},{ 3452,13064},
- { 3670,13280},{ 3890,13519},{ 4123,13750},{ 4367,14059}
- },
- /*Y' qi=11 INTER*/
- {
- { 72, -115},{ 32, 1354},{ 83, 2911},{ 126, 4534},
- { 154, 6080},{ 178, 7475},{ 194, 8779},{ 205,10047},
- { 222,11290},{ 246,12488},{ 281,13621},{ 322,14714},
- { 372,15786},{ 436,16821},{ 519,17813},{ 628,18728},
- { 770,19549},{ 950,20254},{ 1175,20800},{ 1443,21197},
- { 1752,21446},{ 2095,21555},{ 2457,21553},{ 2808,21544}
- }
- },
- {
- /*Cb qi=11 INTRA*/
- {
- { 2, 4},{ 45, 367},{ 81, 740},{ 101, 1177},
- { 121, 1650},{ 142, 2136},{ 159, 2621},{ 174, 3075},
- { 199, 3451},{ 234, 3778},{ 265, 4117},{ 297, 4473},
- { 333, 4789},{ 367, 5054},{ 402, 5319},{ 427, 5613},
- { 462, 5871},{ 503, 6107},{ 532, 6336},{ 560, 6584},
- { 601, 6842},{ 631, 7092},{ 662, 7292},{ 721, 7497}
- },
- /*Cb qi=11 INTER*/
- {
- { 117, -24},{ 93, 308},{ 69, 638},{ 52, 993},
- { 52, 1395},{ 58, 1822},{ 68, 2246},{ 80, 2665},
- { 89, 3082},{ 94, 3492},{ 96, 3900},{ 98, 4299},
- { 101, 4679},{ 103, 5047},{ 104, 5405},{ 106, 5763},
- { 106, 6120},{ 107, 6474},{ 109, 6823},{ 112, 7163},
- { 115, 7516},{ 117, 7868},{ 118, 8213},{ 119, 8561}
- }
- },
- {
- /*Cr qi=11 INTRA*/
- {
- { 2, 7},{ 40, 375},{ 75, 761},{ 100, 1224},
- { 119, 1700},{ 137, 2169},{ 154, 2622},{ 178, 3025},
- { 198, 3416},{ 220, 3770},{ 255, 4114},{ 294, 4459},
- { 323, 4756},{ 359, 5028},{ 399, 5292},{ 438, 5556},
- { 483, 5827},{ 518, 6073},{ 551, 6298},{ 598, 6501},
- { 634, 6754},{ 652, 6997},{ 670, 7211},{ 689, 7560}
- },
- /*Cr qi=11 INTER*/
- {
- { 75, 30},{ 61, 334},{ 51, 639},{ 49, 995},
- { 53, 1403},{ 62, 1821},{ 73, 2237},{ 84, 2654},
- { 91, 3070},{ 95, 3485},{ 96, 3890},{ 98, 4287},
- { 98, 4672},{ 99, 5050},{ 99, 5427},{ 100, 5798},
- { 103, 6169},{ 105, 6528},{ 107, 6881},{ 113, 7233},
- { 118, 7580},{ 121, 7916},{ 125, 8240},{ 130, 8551}
- }
- }
- },
- {
- {
- /*Y' qi=12 INTRA*/
- {
- { 104, -69},{ 182, 1557},{ 335, 3040},{ 521, 4205},
- { 684, 5178},{ 831, 6068},{ 986, 6854},{ 1151, 7559},
- { 1323, 8169},{ 1523, 8704},{ 1736, 9192},{ 1978, 9558},
- { 2213, 9908},{ 2421,10298},{ 2613,10757},{ 2822,11208},
- { 3042,11585},{ 3250,11991},{ 3474,12308},{ 3710,12480},
- { 3939,12687},{ 4174,12902},{ 4416,13102},{ 4672,13369}
- },
- /*Y' qi=12 INTER*/
- {
- { 52, -91},{ 34, 1355},{ 86, 2911},{ 129, 4518},
- { 159, 6037},{ 184, 7405},{ 200, 8694},{ 213, 9955},
- { 232,11185},{ 263,12360},{ 304,13479},{ 354,14555},
- { 415,15601},{ 495,16608},{ 601,17549},{ 738,18400},
- { 915,19136},{ 1139,19724},{ 1414,20150},{ 1731,20412},
- { 2090,20520},{ 2473,20509},{ 2851,20442},{ 3227,20328}
- }
- },
- {
- /*Cb qi=12 INTRA*/
- {
- { 1, 4},{ 46, 367},{ 85, 740},{ 109, 1178},
- { 126, 1650},{ 145, 2134},{ 165, 2617},{ 182, 3061},
- { 209, 3428},{ 245, 3749},{ 281, 4077},{ 316, 4417},
- { 354, 4718},{ 392, 4970},{ 430, 5217},{ 456, 5501},
- { 490, 5771},{ 534, 5996},{ 571, 6207},{ 600, 6458},
- { 644, 6697},{ 675, 6942},{ 707, 7151},{ 766, 7342}
- },
- /*Cb qi=12 INTER*/
- {
- { 84, -24},{ 73, 311},{ 60, 644},{ 52, 998},
- { 53, 1398},{ 60, 1825},{ 71, 2249},{ 83, 2665},
- { 90, 3081},{ 94, 3490},{ 97, 3893},{ 99, 4286},
- { 102, 4663},{ 104, 5032},{ 105, 5393},{ 106, 5751},
- { 107, 6102},{ 108, 6445},{ 111, 6788},{ 113, 7136},
- { 114, 7483},{ 117, 7828},{ 121, 8163},{ 122, 8496}
- }
- },
- {
- /*Cr qi=12 INTRA*/
- {
- { 3, 7},{ 41, 375},{ 78, 761},{ 106, 1225},
- { 124, 1700},{ 140, 2167},{ 163, 2616},{ 188, 3010},
- { 213, 3385},{ 240, 3718},{ 271, 4062},{ 309, 4406},
- { 345, 4691},{ 387, 4956},{ 430, 5212},{ 469, 5467},
- { 513, 5729},{ 554, 5970},{ 587, 6176},{ 633, 6395},
- { 673, 6659},{ 692, 6868},{ 712, 7061},{ 758, 7259}
- },
- /*Cr qi=12 INTER*/
- {
- { 73, 31},{ 59, 335},{ 48, 638},{ 50, 998},
- { 56, 1410},{ 65, 1827},{ 75, 2240},{ 85, 2657},
- { 92, 3073},{ 95, 3485},{ 97, 3888},{ 99, 4279},
- { 98, 4663},{ 99, 5042},{ 101, 5412},{ 102, 5779},
- { 105, 6142},{ 107, 6498},{ 108, 6848},{ 113, 7198},
- { 118, 7540},{ 121, 7867},{ 127, 8188},{ 132, 8508}
- }
- }
- },
- {
- {
- /*Y' qi=13 INTRA*/
- {
- { 109, -68},{ 187, 1551},{ 347, 3010},{ 541, 4153},
- { 709, 5107},{ 864, 5975},{ 1026, 6745},{ 1194, 7433},
- { 1375, 8021},{ 1581, 8550},{ 1803, 9026},{ 2054, 9371},
- { 2301, 9713},{ 2522,10082},{ 2728,10515},{ 2949,10956},
- { 3184,11297},{ 3408,11653},{ 3643,11946},{ 3886,12100},
- { 4124,12277},{ 4377,12459},{ 4632,12635},{ 4898,12861}
- },
- /*Y' qi=13 INTER*/
- {
- { 48, -78},{ 35, 1357},{ 89, 2914},{ 133, 4512},
- { 164, 6004},{ 190, 7348},{ 207, 8627},{ 222, 9881},
- { 247,11096},{ 284,12251},{ 333,13350},{ 392,14407},
- { 466,15426},{ 565,16391},{ 696,17279},{ 865,18058},
- { 1085,18689},{ 1358,19156},{ 1684,19456},{ 2050,19605},
- { 2447,19614},{ 2855,19524},{ 3243,19398},{ 3611,19201}
- }
- },
- {
- /*Cb qi=13 INTRA*/
- {
- { 2, 4},{ 47, 367},{ 86, 741},{ 108, 1179},
- { 127, 1651},{ 150, 2133},{ 173, 2611},{ 194, 3050},
- { 222, 3417},{ 262, 3733},{ 303, 4048},{ 337, 4375},
- { 378, 4657},{ 420, 4897},{ 456, 5148},{ 486, 5422},
- { 518, 5682},{ 558, 5903},{ 592, 6113},{ 623, 6372},
- { 662, 6628},{ 700, 6833},{ 751, 6989},{ 805, 7147}
- },
- /*Cb qi=13 INTER*/
- {
- { 94, -34},{ 78, 303},{ 60, 638},{ 51, 994},
- { 54, 1406},{ 61, 1836},{ 73, 2253},{ 84, 2668},
- { 92, 3082},{ 96, 3492},{ 99, 3894},{ 101, 4284},
- { 103, 4659},{ 105, 5023},{ 106, 5376},{ 108, 5726},
- { 109, 6070},{ 110, 6418},{ 113, 6765},{ 117, 7105},
- { 119, 7448},{ 122, 7784},{ 126, 8119},{ 131, 8463}
- }
- },
- {
- /*Cr qi=13 INTRA*/
- {
- { 3, 7},{ 43, 375},{ 80, 762},{ 110, 1226},
- { 131, 1701},{ 149, 2166},{ 172, 2610},{ 196, 2999},
- { 221, 3359},{ 254, 3679},{ 292, 4005},{ 332, 4329},
- { 369, 4612},{ 408, 4880},{ 456, 5139},{ 500, 5388},
- { 544, 5631},{ 581, 5877},{ 615, 6101},{ 660, 6316},
- { 692, 6594},{ 714, 6795},{ 736, 6997},{ 789, 7290}
- },
- /*Cr qi=13 INTER*/
- {
- { 73, 28},{ 61, 336},{ 46, 642},{ 50, 1003},
- { 58, 1414},{ 67, 1832},{ 79, 2245},{ 87, 2660},
- { 93, 3075},{ 97, 3484},{ 99, 3888},{ 100, 4277},
- { 100, 4651},{ 100, 5027},{ 101, 5403},{ 102, 5765},
- { 105, 6116},{ 109, 6470},{ 113, 6825},{ 119, 7163},
- { 124, 7497},{ 127, 7827},{ 131, 8137},{ 135, 8437}
- }
- }
- },
- {
- {
- /*Y' qi=14 INTRA*/
- {
- { 113, -68},{ 191, 1545},{ 358, 2981},{ 559, 4104},
- { 733, 5044},{ 896, 5890},{ 1066, 6636},{ 1241, 7304},
- { 1428, 7886},{ 1642, 8402},{ 1872, 8871},{ 2128, 9219},
- { 2380, 9547},{ 2609, 9908},{ 2825,10321},{ 3055,10728},
- { 3294,11076},{ 3523,11425},{ 3766,11689},{ 4013,11845},
- { 4254,12022},{ 4506,12209},{ 4759,12383},{ 5013,12637}
- },
- /*Y' qi=14 INTER*/
- {
- { 58, -82},{ 38, 1362},{ 93, 2914},{ 138, 4492},
- { 171, 5962},{ 198, 7289},{ 216, 8559},{ 234, 9804},
- { 263,11005},{ 306,12143},{ 363,13222},{ 434,14259},
- { 523,15255},{ 639,16188},{ 794,17021},{ 1000,17717},
- { 1262,18260},{ 1575,18645},{ 1943,18841},{ 2356,18872},
- { 2782,18802},{ 3194,18682},{ 3576,18559},{ 3923,18447}
- }
- },
- {
- /*Cb qi=14 INTRA*/
- {
- { 2, 3},{ 50, 367},{ 91, 741},{ 114, 1180},
- { 134, 1651},{ 157, 2131},{ 181, 2601},{ 208, 3028},
- { 239, 3391},{ 279, 3706},{ 322, 4000},{ 361, 4309},
- { 406, 4587},{ 445, 4822},{ 482, 5067},{ 515, 5344},
- { 546, 5612},{ 589, 5821},{ 626, 6020},{ 655, 6276},
- { 701, 6523},{ 748, 6717},{ 796, 6876},{ 815, 7151}
- },
- /*Cb qi=14 INTER*/
- {
- { 80, -43},{ 68, 301},{ 56, 644},{ 50, 1004},
- { 54, 1412},{ 63, 1836},{ 75, 2253},{ 87, 2670},
- { 94, 3083},{ 98, 3487},{ 101, 3885},{ 103, 4271},
- { 106, 4645},{ 107, 5004},{ 108, 5358},{ 109, 5705},
- { 112, 6047},{ 115, 6388},{ 118, 6731},{ 121, 7081},
- { 126, 7421},{ 129, 7747},{ 132, 8076},{ 137, 8419}
- }
- },
- {
- /*Cr qi=14 INTRA*/
- {
- { 3, 6},{ 45, 375},{ 85, 762},{ 116, 1226},
- { 138, 1700},{ 158, 2163},{ 180, 2602},{ 206, 2985},
- { 236, 3333},{ 270, 3639},{ 310, 3956},{ 359, 4258},
- { 397, 4524},{ 430, 4802},{ 478, 5068},{ 527, 5316},
- { 572, 5560},{ 613, 5802},{ 654, 6012},{ 699, 6216},
- { 734, 6489},{ 755, 6707},{ 775, 6898},{ 841, 7111}
- },
- /*Cr qi=14 INTER*/
- {
- { 78, 0},{ 59, 322},{ 46, 649},{ 51, 1016},
- { 58, 1422},{ 68, 1839},{ 81, 2253},{ 90, 2666},
- { 95, 3080},{ 98, 3486},{ 101, 3881},{ 102, 4268},
- { 102, 4644},{ 103, 5017},{ 105, 5382},{ 106, 5743},
- { 108, 6093},{ 112, 6442},{ 118, 6791},{ 124, 7130},
- { 127, 7463},{ 133, 7784},{ 138, 8085},{ 142, 8395}
- }
- }
- },
- {
- {
- /*Y' qi=15 INTRA*/
- {
- { 111, -66},{ 197, 1538},{ 370, 2949},{ 579, 4050},
- { 762, 4968},{ 933, 5798},{ 1112, 6520},{ 1299, 7161},
- { 1497, 7725},{ 1723, 8219},{ 1967, 8654},{ 2234, 8990},
- { 2499, 9302},{ 2740, 9637},{ 2968,10039},{ 3215,10414},
- { 3473,10709},{ 3721,11015},{ 3971,11270},{ 4228,11402},
- { 4487,11543},{ 4752,11707},{ 5011,11871},{ 5290,12099}
- },
- /*Y' qi=15 INTER*/
- {
- { 59, -113},{ 37, 1349},{ 95, 2904},{ 139, 4478},
- { 174, 5929},{ 201, 7244},{ 220, 8505},{ 241, 9736},
- { 275,10922},{ 327,12040},{ 395,13097},{ 477,14114},
- { 585,15071},{ 730,15947},{ 917,16714},{ 1162,17326},
- { 1468,17770},{ 1833,18029},{ 2251,18111},{ 2694,18068},
- { 3125,17968},{ 3529,17845},{ 3908,17713},{ 4260,17587}
- }
- },
- {
- /*Cb qi=15 INTRA*/
- {
- { 2, 3},{ 51, 367},{ 94, 741},{ 120, 1180},
- { 140, 1651},{ 160, 2129},{ 184, 2591},{ 213, 3010},
- { 246, 3371},{ 289, 3680},{ 335, 3969},{ 374, 4274},
- { 418, 4546},{ 460, 4783},{ 498, 5019},{ 532, 5280},
- { 565, 5553},{ 608, 5765},{ 647, 5958},{ 683, 6193},
- { 732, 6433},{ 782, 6620},{ 832, 6769},{ 848, 7027}
- },
- /*Cb qi=15 INTER*/
- {
- { 71, -52},{ 63, 296},{ 54, 644},{ 50, 1010},
- { 53, 1417},{ 64, 1837},{ 77, 2253},{ 88, 2666},
- { 95, 3079},{ 98, 3487},{ 100, 3882},{ 103, 4264},
- { 106, 4633},{ 108, 4991},{ 109, 5343},{ 109, 5693},
- { 112, 6038},{ 114, 6371},{ 119, 6709},{ 123, 7051},
- { 125, 7385},{ 130, 7716},{ 135, 8050},{ 140, 8374}
- }
- },
- {
- /*Cr qi=15 INTRA*/
- {
- { 2, 6},{ 47, 375},{ 87, 763},{ 119, 1225},
- { 143, 1699},{ 162, 2158},{ 185, 2595},{ 213, 2971},
- { 246, 3315},{ 279, 3618},{ 320, 3920},{ 372, 4210},
- { 409, 4480},{ 446, 4756},{ 496, 5017},{ 542, 5263},
- { 590, 5487},{ 639, 5721},{ 687, 5923},{ 724, 6132},
- { 753, 6417},{ 781, 6622},{ 805, 6806},{ 856, 6977}
- },
- /*Cr qi=15 INTER*/
- {
- { 71, 3},{ 61, 326},{ 52, 651},{ 50, 1017},
- { 58, 1422},{ 69, 1837},{ 82, 2251},{ 90, 2668},
- { 95, 3080},{ 98, 3484},{ 101, 3877},{ 102, 4257},
- { 102, 4632},{ 101, 5005},{ 103, 5370},{ 106, 5733},
- { 110, 6082},{ 116, 6424},{ 120, 6774},{ 124, 7106},
- { 130, 7427},{ 135, 7748},{ 141, 8052},{ 147, 8333}
- }
- }
- },
- {
- {
- /*Y' qi=16 INTRA*/
- {
- { 114, -63},{ 206, 1525},{ 396, 2887},{ 618, 3945},
- { 816, 4832},{ 1002, 5626},{ 1196, 6319},{ 1401, 6923},
- { 1616, 7458},{ 1857, 7928},{ 2121, 8334},{ 2405, 8645},
- { 2685, 8934},{ 2938, 9255},{ 3175, 9638},{ 3433, 9990},
- { 3707,10263},{ 3958,10577},{ 4218,10807},{ 4488,10906},
- { 4760,11028},{ 5037,11148},{ 5306,11286},{ 5625,11463}
- },
- /*Y' qi=16 INTER*/
- {
- { 69, -153},{ 39, 1348},{ 98, 2894},{ 144, 4448},
- { 181, 5872},{ 209, 7167},{ 228, 8422},{ 254, 9644},
- { 297,10810},{ 359,11908},{ 438,12944},{ 539,13930},
- { 672,14842},{ 850,15650},{ 1085,16318},{ 1391,16793},
- { 1769,17082},{ 2200,17198},{ 2659,17174},{ 3116,17072},
- { 3547,16948},{ 3943,16819},{ 4299,16701},{ 4611,16644}
- }
- },
- {
- /*Cb qi=16 INTRA*/
- {
- { 3, 4},{ 54, 367},{ 97, 742},{ 122, 1181},
- { 143, 1651},{ 168, 2123},{ 197, 2575},{ 226, 2985},
- { 263, 3338},{ 314, 3631},{ 367, 3903},{ 409, 4200},
- { 453, 4468},{ 491, 4703},{ 528, 4932},{ 566, 5188},
- { 601, 5459},{ 647, 5672},{ 693, 5844},{ 734, 6058},
- { 784, 6305},{ 836, 6460},{ 882, 6602},{ 905, 6891}
- },
- /*Cb qi=16 INTER*/
- {
- { 75, -64},{ 67, 292},{ 56, 645},{ 51, 1016},
- { 54, 1421},{ 66, 1842},{ 79, 2257},{ 89, 2670},
- { 95, 3082},{ 98, 3488},{ 101, 3879},{ 104, 4258},
- { 106, 4623},{ 108, 4974},{ 109, 5321},{ 113, 5664},
- { 116, 6001},{ 117, 6341},{ 123, 6677},{ 128, 7004},
- { 130, 7336},{ 136, 7671},{ 143, 7996},{ 148, 8310}
- }
- },
- {
- /*Cr qi=16 INTRA*/
- {
- { 4, 7},{ 50, 375},{ 90, 763},{ 124, 1225},
- { 148, 1698},{ 168, 2154},{ 195, 2582},{ 227, 2948},
- { 263, 3279},{ 302, 3575},{ 343, 3865},{ 394, 4137},
- { 439, 4402},{ 482, 4672},{ 533, 4925},{ 579, 5165},
- { 626, 5382},{ 675, 5616},{ 725, 5812},{ 769, 5991},
- { 810, 6242},{ 848, 6430},{ 868, 6615},{ 944, 6732}
- },
- /*Cr qi=16 INTER*/
- {
- { 78, 11},{ 62, 327},{ 49, 650},{ 50, 1025},
- { 59, 1431},{ 72, 1841},{ 83, 2253},{ 90, 2671},
- { 95, 3084},{ 98, 3487},{ 100, 3879},{ 101, 4254},
- { 102, 4625},{ 103, 4994},{ 106, 5355},{ 108, 5708},
- { 111, 6058},{ 115, 6400},{ 121, 6733},{ 128, 7058},
- { 134, 7374},{ 140, 7691},{ 146, 7993},{ 146, 8317}
- }
- }
- },
- {
- {
- /*Y' qi=17 INTRA*/
- {
- { 112, -59},{ 210, 1515},{ 409, 2850},{ 640, 3882},
- { 844, 4748},{ 1038, 5529},{ 1240, 6206},{ 1452, 6803},
- { 1676, 7330},{ 1925, 7792},{ 2194, 8201},{ 2483, 8512},
- { 2766, 8801},{ 3027, 9121},{ 3279, 9482},{ 3548, 9810},
- { 3825,10069},{ 4088,10345},{ 4362,10544},{ 4638,10644},
- { 4915,10744},{ 5196,10850},{ 5471,10981},{ 5802,11136}
- },
- /*Y' qi=17 INTER*/
- {
- { 70, -147},{ 45, 1349},{ 106, 2894},{ 155, 4425},
- { 195, 5818},{ 225, 7099},{ 247, 8348},{ 278, 9565},
- { 328,10717},{ 399,11794},{ 491,12807},{ 609,13760},
- { 766,14623},{ 984,15349},{ 1274,15902},{ 1642,16256},
- { 2082,16411},{ 2563,16409},{ 3048,16315},{ 3508,16194},
- { 3924,16064},{ 4306,15938},{ 4656,15828},{ 4966,15733}
- }
- },
- {
- /*Cb qi=17 INTRA*/
- {
- { 3, 4},{ 57, 367},{ 101, 742},{ 126, 1182},
- { 148, 1650},{ 175, 2118},{ 207, 2565},{ 241, 2966},
- { 279, 3307},{ 331, 3588},{ 389, 3845},{ 435, 4132},
- { 474, 4408},{ 517, 4641},{ 560, 4869},{ 602, 5122},
- { 638, 5389},{ 672, 5610},{ 716, 5787},{ 758, 6002},
- { 817, 6226},{ 869, 6393},{ 916, 6530},{ 950, 6799}
- },
- /*Cb qi=17 INTER*/
- {
- { 105, -65},{ 86, 288},{ 66, 638},{ 54, 1014},
- { 59, 1427},{ 71, 1844},{ 86, 2257},{ 95, 2668},
- { 100, 3075},{ 103, 3476},{ 106, 3867},{ 110, 4241},
- { 112, 4598},{ 114, 4948},{ 117, 5294},{ 121, 5633},
- { 123, 5968},{ 126, 6301},{ 131, 6637},{ 136, 6968},
- { 144, 7287},{ 152, 7606},{ 158, 7931},{ 162, 8262}
- }
- },
- {
- /*Cr qi=17 INTRA*/
- {
- { 4, 6},{ 55, 376},{ 97, 765},{ 128, 1226},
- { 152, 1696},{ 175, 2144},{ 204, 2568},{ 241, 2928},
- { 282, 3250},{ 323, 3530},{ 368, 3811},{ 420, 4089},
- { 463, 4347},{ 505, 4609},{ 562, 4860},{ 609, 5094},
- { 655, 5303},{ 709, 5535},{ 759, 5740},{ 803, 5913},
- { 844, 6153},{ 879, 6350},{ 905, 6527},{ 972, 6637}
- },
- /*Cr qi=17 INTER*/
- {
- { 88, 8},{ 68, 330},{ 51, 653},{ 54, 1028},
- { 65, 1433},{ 77, 1845},{ 89, 2257},{ 96, 2669},
- { 100, 3081},{ 102, 3481},{ 105, 3867},{ 106, 4245},
- { 108, 4613},{ 110, 4971},{ 112, 5328},{ 115, 5679},
- { 120, 6019},{ 127, 6355},{ 133, 6686},{ 140, 7007},
- { 149, 7316},{ 158, 7618},{ 166, 7924},{ 170, 8232}
+ { 5, 408},{ 3, 1197},{ 7, 1275},{ 16, 1695},
+ { 22, 1979},{ 30, 2324},{ 38, 2691},{ 47, 3071},
+ { 53, 3462},{ 59, 3857},{ 64, 4255},{ 69, 4612},
+ { 74, 4975},{ 76, 5347},{ 81, 5694},{ 86, 6020},
+ { 91, 6357},{ 96, 6687},{ 102, 7020},{ 108, 7351},
+ { 115, 7663},{ 122, 7979},{ 125, 8298},{ 136, 8576}
}
}
},
@@ -1174,557 +155,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=18 INTRA*/
{
- { 122, -58},{ 216, 1506},{ 425, 2815},{ 665, 3822},
- { 882, 4666},{ 1088, 5425},{ 1301, 6084},{ 1529, 6653},
- { 1766, 7162},{ 2026, 7611},{ 2312, 7987},{ 2612, 8278},
- { 2913, 8551},{ 3196, 8840},{ 3454, 9184},{ 3734, 9490},
- { 4030, 9725},{ 4305, 9973},{ 4585,10162},{ 4864,10251},
- { 5150,10324},{ 5443,10420},{ 5727,10536},{ 6053,10682}
+ { 83, 534},{ 261, 1697},{ 507, 2691},{ 852, 3418},
+ { 1127, 4094},{ 1378, 4775},{ 1626, 5442},{ 1905, 5975},
+ { 2164, 6468},{ 2445, 6913},{ 2704, 7301},{ 3001, 7631},
+ { 3285, 7934},{ 3536, 8217},{ 3837, 8489},{ 4076, 8814},
+ { 4325, 9046},{ 4590, 9313},{ 4794, 9546},{ 5062, 9751},
+ { 5285, 9963},{ 5578,10079},{ 5777,10302},{ 6054,10296}
},
/*Y' qi=18 INTER*/
{
- { 66, -143},{ 47, 1351},{ 108, 2886},{ 158, 4401},
- { 200, 5775},{ 232, 7044},{ 256, 8288},{ 292, 9493},
- { 351,10625},{ 434,11679},{ 541,12665},{ 681,13578},
- { 875,14379},{ 1136,15025},{ 1483,15475},{ 1914,15709},
- { 2399,15767},{ 2907,15699},{ 3400,15579},{ 3852,15453},
- { 4259,15332},{ 4630,15221},{ 4976,15121},{ 5294,15061}
+ { 33, 490},{ 62, 1599},{ 96, 3015},{ 164, 4378},
+ { 225, 5633},{ 285, 6831},{ 351, 7999},{ 427, 9133},
+ { 526,10181},{ 652,11141},{ 829,11991},{ 1049,12732},
+ { 1310,13367},{ 1592,13896},{ 1881,14350},{ 2207,14667},
+ { 2529,14877},{ 2873,14980},{ 3231,14949},{ 3571,14926},
+ { 3922,14816},{ 4246,14715},{ 4559,14579},{ 4778,14590}
}
},
{
/*Cb qi=18 INTRA*/
{
- { 2, 3},{ 61, 367},{ 107, 743},{ 131, 1182},
- { 155, 1648},{ 183, 2110},{ 220, 2542},{ 260, 2927},
- { 303, 3265},{ 359, 3540},{ 416, 3785},{ 462, 4063},
- { 506, 4334},{ 553, 4567},{ 595, 4797},{ 636, 5049},
- { 676, 5304},{ 717, 5516},{ 759, 5698},{ 801, 5904},
- { 861, 6133},{ 911, 6311},{ 962, 6443},{ 1021, 6645}
+ { 55, 825},{ 95, 1021},{ 131, 1276},{ 150, 1618},
+ { 180, 1958},{ 220, 2306},{ 256, 2608},{ 322, 2939},
+ { 385, 3239},{ 436, 3530},{ 475, 3771},{ 518, 4078},
+ { 557, 4348},{ 604, 4592},{ 620, 4851},{ 676, 5083},
+ { 704, 5363},{ 739, 5582},{ 788, 5782},{ 819, 6000},
+ { 893, 6158},{ 940, 6418},{ 984, 6499},{ 1035, 6596}
},
/*Cb qi=18 INTER*/
{
- { 126, 5},{ 95, 326},{ 66, 643},{ 55, 1015},
- { 60, 1427},{ 73, 1843},{ 87, 2256},{ 96, 2667},
- { 101, 3073},{ 104, 3470},{ 108, 3853},{ 111, 4226},
- { 114, 4584},{ 117, 4928},{ 119, 5274},{ 122, 5612},
- { 126, 5942},{ 130, 6271},{ 136, 6606},{ 141, 6931},
- { 148, 7247},{ 156, 7568},{ 164, 7891},{ 173, 8211}
+ { -2, 642},{ 12, 771},{ 20, 1054},{ 29, 1394},
+ { 35, 1721},{ 45, 2080},{ 53, 2450},{ 63, 2835},
+ { 73, 3225},{ 81, 3596},{ 87, 3952},{ 95, 4300},
+ { 102, 4634},{ 109, 4959},{ 115, 5283},{ 120, 5608},
+ { 130, 5931},{ 139, 6254},{ 152, 6571},{ 163, 6887},
+ { 179, 7204},{ 191, 7508},{ 198, 7834},{ 224, 8066}
}
},
{
/*Cr qi=18 INTRA*/
{
- { 4, 6},{ 59, 376},{ 104, 765},{ 133, 1226},
- { 156, 1692},{ 184, 2136},{ 218, 2548},{ 260, 2893},
- { 308, 3204},{ 348, 3481},{ 397, 3751},{ 448, 4024},
- { 490, 4281},{ 541, 4523},{ 593, 4776},{ 634, 5022},
- { 685, 5236},{ 748, 5455},{ 812, 5638},{ 856, 5818},
- { 891, 6048},{ 928, 6230},{ 961, 6405},{ 1055, 6449}
+ { 49, 780},{ 86, 986},{ 120, 1261},{ 137, 1588},
+ { 183, 1998},{ 228, 2339},{ 291, 2670},{ 334, 2938},
+ { 376, 3239},{ 412, 3522},{ 459, 3783},{ 490, 4113},
+ { 547, 4321},{ 593, 4571},{ 640, 4828},{ 675, 5137},
+ { 730, 5254},{ 774, 5524},{ 821, 5754},{ 859, 5911},
+ { 887, 6178},{ 982, 6266},{ 941, 6536},{ 996, 6630}
},
/*Cr qi=18 INTER*/
{
- { 81, 34},{ 68, 342},{ 57, 652},{ 59, 1027},
- { 67, 1439},{ 80, 1848},{ 91, 2257},{ 97, 2670},
- { 100, 3076},{ 103, 3473},{ 106, 3857},{ 108, 4231},
- { 109, 4599},{ 110, 4958},{ 113, 5307},{ 119, 5650},
- { 125, 5991},{ 130, 6325},{ 138, 6651},{ 147, 6971},
- { 153, 7278},{ 162, 7578},{ 172, 7874},{ 177, 8156}
- }
- }
- },
- {
- {
- /*Y' qi=19 INTRA*/
- {
- { 128, -55},{ 228, 1495},{ 448, 2775},{ 699, 3758},
- { 931, 4571},{ 1154, 5296},{ 1386, 5914},{ 1636, 6450},
- { 1894, 6930},{ 2177, 7342},{ 2479, 7698},{ 2792, 7976},
- { 3099, 8235},{ 3392, 8517},{ 3658, 8853},{ 3938, 9155},
- { 4242, 9371},{ 4527, 9605},{ 4810, 9781},{ 5089, 9853},
- { 5378, 9920},{ 5674,10009},{ 5972,10110},{ 6336,10196}
- },
- /*Y' qi=19 INTER*/
- {
- { 69, -147},{ 49, 1353},{ 111, 2883},{ 162, 4381},
- { 205, 5737},{ 237, 6996},{ 264, 8232},{ 307, 9421},
- { 376,10534},{ 472,11567},{ 596,12525},{ 761,13395},
- { 990,14130},{ 1298,14694},{ 1695,15053},{ 2172,15195},
- { 2696,15173},{ 3213,15075},{ 3696,14948},{ 4141,14829},
- { 4541,14721},{ 4910,14609},{ 5245,14506},{ 5536,14399}
- }
- },
- {
- /*Cb qi=19 INTRA*/
- {
- { 3, 3},{ 61, 367},{ 109, 743},{ 135, 1182},
- { 161, 1646},{ 191, 2101},{ 229, 2524},{ 273, 2898},
- { 318, 3221},{ 376, 3490},{ 436, 3731},{ 487, 3994},
- { 539, 4251},{ 584, 4485},{ 621, 4721},{ 664, 4967},
- { 709, 5225},{ 752, 5431},{ 801, 5595},{ 846, 5796},
- { 912, 6011},{ 959, 6193},{ 1015, 6321},{ 1121, 6504}
- },
- /*Cb qi=19 INTER*/
- {
- { 126, 4},{ 97, 329},{ 69, 649},{ 56, 1017},
- { 61, 1432},{ 74, 1846},{ 88, 2255},{ 98, 2663},
- { 103, 3065},{ 106, 3460},{ 110, 3844},{ 114, 4211},
- { 117, 4564},{ 120, 4911},{ 122, 5253},{ 125, 5588},
- { 129, 5916},{ 135, 6241},{ 142, 6567},{ 149, 6885},
- { 155, 7206},{ 163, 7527},{ 174, 7843},{ 188, 8145}
- }
- },
- {
- /*Cr qi=19 INTRA*/
- {
- { 5, 6},{ 61, 376},{ 106, 765},{ 135, 1225},
- { 160, 1689},{ 192, 2126},{ 229, 2531},{ 271, 2869},
- { 321, 3168},{ 370, 3433},{ 421, 3704},{ 476, 3965},
- { 520, 4212},{ 572, 4452},{ 629, 4691},{ 671, 4939},
- { 724, 5152},{ 792, 5347},{ 858, 5510},{ 895, 5696},
- { 939, 5905},{ 991, 6056},{ 1027, 6244},{ 1127, 6333}
- },
- /*Cr qi=19 INTER*/
- {
- { 80, 45},{ 66, 344},{ 55, 654},{ 56, 1030},
- { 66, 1440},{ 80, 1850},{ 91, 2259},{ 98, 2668},
- { 102, 3072},{ 104, 3466},{ 107, 3845},{ 109, 4215},
- { 110, 4578},{ 112, 4933},{ 116, 5283},{ 122, 5625},
- { 129, 5963},{ 136, 6287},{ 143, 6611},{ 151, 6927},
- { 160, 7229},{ 170, 7528},{ 181, 7818},{ 191, 8092}
- }
- }
- },
- {
- {
- /*Y' qi=20 INTRA*/
- {
- { 129, -50},{ 238, 1481},{ 469, 2728},{ 730, 3684},
- { 974, 4473},{ 1213, 5171},{ 1463, 5763},{ 1729, 6281},
- { 2002, 6744},{ 2299, 7146},{ 2613, 7492},{ 2940, 7746},
- { 3265, 7978},{ 3571, 8228},{ 3853, 8543},{ 4156, 8815},
- { 4476, 9001},{ 4775, 9218},{ 5070, 9373},{ 5352, 9446},
- { 5649, 9510},{ 5956, 9580},{ 6268, 9660},{ 6647, 9705}
- },
- /*Y' qi=20 INTER*/
- {
- { 64, -93},{ 52, 1340},{ 116, 2862},{ 170, 4344},
- { 216, 5678},{ 249, 6928},{ 281, 8155},{ 333, 9326},
- { 418,10410},{ 533,11411},{ 683,12329},{ 890,13127},
- { 1183,13750},{ 1579,14162},{ 2066,14357},{ 2611,14370},
- { 3159,14284},{ 3675,14167},{ 4142,14053},{ 4568,13953},
- { 4961,13852},{ 5320,13755},{ 5649,13675},{ 5933,13610}
- }
- },
- {
- /*Cb qi=20 INTRA*/
- {
- { 3, 3},{ 62, 367},{ 112, 743},{ 140, 1183},
- { 165, 1646},{ 196, 2099},{ 235, 2517},{ 284, 2883},
- { 334, 3198},{ 393, 3460},{ 457, 3690},{ 509, 3945},
- { 560, 4198},{ 605, 4435},{ 647, 4658},{ 699, 4888},
- { 742, 5155},{ 788, 5350},{ 835, 5517},{ 880, 5730},
- { 956, 5914},{ 1007, 6060},{ 1053, 6199},{ 1158, 6358}
- },
- /*Cb qi=20 INTER*/
- {
- { 128, -6},{ 96, 322},{ 66, 653},{ 54, 1025},
- { 63, 1431},{ 79, 1844},{ 91, 2256},{ 99, 2665},
- { 104, 3065},{ 107, 3455},{ 111, 3831},{ 115, 4189},
- { 120, 4539},{ 123, 4885},{ 126, 5219},{ 130, 5548},
- { 135, 5876},{ 141, 6199},{ 149, 6519},{ 156, 6837},
- { 166, 7153},{ 179, 7468},{ 189, 7784},{ 194, 8102}
- }
- },
- {
- /*Cr qi=20 INTRA*/
- {
- { 4, 6},{ 63, 376},{ 109, 765},{ 139, 1225},
- { 165, 1689},{ 199, 2124},{ 239, 2523},{ 285, 2852},
- { 340, 3140},{ 388, 3398},{ 438, 3662},{ 499, 3914},
- { 547, 4155},{ 596, 4392},{ 652, 4634},{ 699, 4877},
- { 759, 5074},{ 824, 5257},{ 883, 5428},{ 936, 5589},
- { 986, 5790},{ 1030, 5960},{ 1074, 6119},{ 1172, 6191}
- },
- /*Cr qi=20 INTER*/
- {
- { 92, 40},{ 70, 345},{ 55, 658},{ 57, 1034},
- { 69, 1441},{ 84, 1852},{ 94, 2261},{ 98, 2669},
- { 102, 3074},{ 105, 3465},{ 107, 3841},{ 110, 4206},
- { 112, 4562},{ 116, 4915},{ 121, 5260},{ 127, 5591},
- { 134, 5920},{ 142, 6246},{ 153, 6562},{ 163, 6870},
- { 173, 7170},{ 186, 7463},{ 198, 7746},{ 199, 8030}
- }
- }
- },
- {
- {
- /*Y' qi=21 INTRA*/
- {
- { 130, -51},{ 244, 1476},{ 483, 2705},{ 756, 3635},
- { 1013, 4396},{ 1266, 5070},{ 1530, 5647},{ 1806, 6153},
- { 2093, 6600},{ 2411, 6976},{ 2739, 7299},{ 3079, 7534},
- { 3422, 7744},{ 3738, 7987},{ 4032, 8274},{ 4348, 8533},
- { 4675, 8721},{ 4989, 8909},{ 5291, 9051},{ 5577, 9111},
- { 5879, 9163},{ 6190, 9228},{ 6506, 9286},{ 6899, 9295}
- },
- /*Y' qi=21 INTER*/
- {
- { 64, -56},{ 55, 1341},{ 119, 2859},{ 174, 4324},
- { 223, 5640},{ 258, 6880},{ 295, 8096},{ 359, 9246},
- { 460,10302},{ 595,11268},{ 778,12131},{ 1032,12857},
- { 1387,13385},{ 1850,13683},{ 2399,13774},{ 2976,13729},
- { 3527,13619},{ 4034,13504},{ 4492,13401},{ 4912,13291},
- { 5298,13209},{ 5648,13137},{ 5974,13046},{ 6308,12977}
- }
- },
- {
- /*Cb qi=21 INTRA*/
- {
- { 4, 3},{ 64, 367},{ 114, 743},{ 141, 1183},
- { 166, 1645},{ 201, 2092},{ 247, 2502},{ 299, 2856},
- { 352, 3158},{ 413, 3412},{ 480, 3642},{ 536, 3893},
- { 588, 4137},{ 637, 4367},{ 678, 4598},{ 725, 4834},
- { 774, 5083},{ 827, 5269},{ 883, 5420},{ 930, 5633},
- { 999, 5829},{ 1057, 5959},{ 1113, 6082},{ 1200, 6265}
- },
- /*Cb qi=21 INTER*/
- {
- { 109, -8},{ 84, 321},{ 62, 654},{ 54, 1028},
- { 64, 1434},{ 80, 1847},{ 92, 2259},{ 100, 2664},
- { 105, 3060},{ 109, 3445},{ 114, 3815},{ 118, 4172},
- { 122, 4519},{ 126, 4861},{ 128, 5194},{ 133, 5520},
- { 139, 5847},{ 146, 6169},{ 155, 6487},{ 166, 6801},
- { 177, 7114},{ 189, 7423},{ 201, 7729},{ 208, 8035}
- }
- },
- {
- /*Cr qi=21 INTRA*/
- {
- { 4, 6},{ 64, 377},{ 111, 766},{ 144, 1225},
- { 174, 1683},{ 206, 2114},{ 248, 2506},{ 302, 2824},
- { 357, 3099},{ 404, 3357},{ 455, 3622},{ 519, 3867},
- { 573, 4098},{ 625, 4331},{ 683, 4571},{ 733, 4802},
- { 793, 4994},{ 863, 5173},{ 926, 5337},{ 978, 5492},
- { 1030, 5685},{ 1079, 5856},{ 1126, 6027},{ 1217, 6159}
- },
- /*Cr qi=21 INTER*/
- {
- { 82, 29},{ 67, 341},{ 55, 660},{ 58, 1038},
- { 71, 1443},{ 85, 1851},{ 95, 2258},{ 99, 2666},
- { 103, 3069},{ 107, 3456},{ 110, 3826},{ 112, 4188},
- { 114, 4544},{ 118, 4891},{ 124, 5231},{ 132, 5567},
- { 139, 5894},{ 148, 6210},{ 159, 6520},{ 171, 6822},
- { 185, 7111},{ 196, 7403},{ 209, 7691},{ 225, 7945}
- }
- }
- },
- {
- {
- /*Y' qi=22 INTRA*/
- {
- { 128, -45},{ 254, 1463},{ 507, 2662},{ 794, 3562},
- { 1070, 4292},{ 1340, 4941},{ 1622, 5492},{ 1920, 5968},
- { 2229, 6387},{ 2565, 6742},{ 2911, 7047},{ 3263, 7264},
- { 3615, 7464},{ 3944, 7689},{ 4258, 7950},{ 4591, 8183},
- { 4934, 8347},{ 5259, 8517},{ 5573, 8634},{ 5870, 8683},
- { 6186, 8723},{ 6508, 8762},{ 6831, 8801},{ 7232, 8830}
- },
- /*Y' qi=22 INTER*/
- {
- { 77, -48},{ 57, 1343},{ 122, 2853},{ 180, 4299},
- { 231, 5597},{ 269, 6826},{ 314, 8025},{ 393, 9150},
- { 512,10179},{ 673,11103},{ 894,11908},{ 1207,12542},
- { 1635,12956},{ 2166,13148},{ 2755,13167},{ 3345,13088},
- { 3895,12966},{ 4386,12848},{ 4832,12746},{ 5252,12647},
- { 5634,12563},{ 5978,12497},{ 6299,12412},{ 6633,12338}
- }
- },
- {
- /*Cb qi=22 INTRA*/
- {
- { 4, 3},{ 66, 367},{ 122, 744},{ 153, 1182},
- { 177, 1640},{ 213, 2080},{ 263, 2475},{ 323, 2811},
- { 382, 3103},{ 451, 3346},{ 522, 3568},{ 581, 3814},
- { 633, 4054},{ 674, 4288},{ 719, 4523},{ 768, 4756},
- { 823, 4979},{ 883, 5162},{ 937, 5325},{ 996, 5510},
- { 1070, 5687},{ 1129, 5807},{ 1193, 5929},{ 1311, 6099}
- },
- /*Cb qi=22 INTER*/
- {
- { 107, -5},{ 83, 322},{ 61, 653},{ 55, 1030},
- { 66, 1436},{ 81, 1845},{ 94, 2253},{ 102, 2656},
- { 107, 3050},{ 111, 3435},{ 115, 3804},{ 119, 4158},
- { 124, 4501},{ 128, 4835},{ 132, 5164},{ 138, 5490},
- { 146, 5812},{ 154, 6128},{ 163, 6442},{ 174, 6754},
- { 188, 7060},{ 205, 7361},{ 219, 7662},{ 233, 7953}
- }
- },
- {
- /*Cr qi=22 INTRA*/
- {
- { 4, 6},{ 67, 378},{ 118, 767},{ 151, 1222},
- { 182, 1675},{ 221, 2097},{ 269, 2476},{ 329, 2774},
- { 389, 3039},{ 444, 3292},{ 500, 3545},{ 560, 3788},
- { 615, 4020},{ 671, 4251},{ 734, 4484},{ 781, 4712},
- { 850, 4887},{ 925, 5060},{ 981, 5229},{ 1031, 5369},
- { 1092, 5549},{ 1148, 5715},{ 1200, 5861},{ 1291, 5943}
- },
- /*Cr qi=22 INTER*/
- {
- { 88, 34},{ 69, 340},{ 57, 657},{ 60, 1039},
- { 73, 1445},{ 87, 1851},{ 96, 2257},{ 100, 2662},
- { 103, 3058},{ 107, 3442},{ 111, 3812},{ 115, 4172},
- { 118, 4524},{ 123, 4864},{ 129, 5199},{ 136, 5531},
- { 145, 5855},{ 156, 6168},{ 170, 6468},{ 184, 6765},
- { 193, 7066},{ 207, 7353},{ 222, 7628},{ 230, 7900}
- }
- }
- },
- {
- {
- /*Y' qi=23 INTRA*/
- {
- { 126, -40},{ 257, 1458},{ 521, 2636},{ 825, 3501},
- { 1111, 4207},{ 1391, 4842},{ 1684, 5385},{ 1992, 5858},
- { 2311, 6277},{ 2653, 6626},{ 3005, 6929},{ 3366, 7134},
- { 3729, 7311},{ 4071, 7526},{ 4396, 7770},{ 4734, 7986},
- { 5086, 8131},{ 5421, 8286},{ 5735, 8404},{ 6033, 8456},
- { 6357, 8486},{ 6682, 8525},{ 7003, 8573},{ 7387, 8604}
- },
- /*Y' qi=23 INTER*/
- {
- { 64, -57},{ 60, 1345},{ 124, 2853},{ 185, 4284},
- { 239, 5565},{ 282, 6783},{ 336, 7967},{ 429, 9069},
- { 568,10063},{ 758,10943},{ 1028,11679},{ 1407,12216},
- { 1909,12520},{ 2502,12616},{ 3126,12573},{ 3722,12461},
- { 4258,12344},{ 4742,12236},{ 5185,12136},{ 5590,12052},
- { 5970,11980},{ 6315,11901},{ 6631,11826},{ 6954,11769}
- }
- },
- {
- /*Cb qi=23 INTRA*/
- {
- { 3, 3},{ 70, 367},{ 124, 744},{ 151, 1182},
- { 181, 1637},{ 222, 2071},{ 276, 2460},{ 343, 2785},
- { 403, 3072},{ 468, 3317},{ 542, 3534},{ 605, 3773},
- { 659, 4009},{ 703, 4243},{ 747, 4479},{ 795, 4707},
- { 852, 4923},{ 908, 5105},{ 972, 5254},{ 1043, 5423},
- { 1118, 5594},{ 1172, 5731},{ 1240, 5853},{ 1365, 6005}
- },
- /*Cb qi=23 INTER*/
- {
- { 109, -10},{ 87, 325},{ 63, 650},{ 57, 1031},
- { 67, 1439},{ 83, 1847},{ 96, 2253},{ 103, 2652},
- { 109, 3041},{ 114, 3421},{ 117, 3789},{ 122, 4141},
- { 128, 4480},{ 134, 4811},{ 139, 5138},{ 144, 5463},
- { 152, 5781},{ 161, 6096},{ 174, 6404},{ 185, 6714},
- { 198, 7023},{ 216, 7320},{ 233, 7621},{ 245, 7935}
- }
- },
- {
- /*Cr qi=23 INTRA*/
- {
- { 5, 6},{ 70, 379},{ 122, 768},{ 155, 1222},
- { 187, 1671},{ 231, 2088},{ 283, 2459},{ 346, 2750},
- { 411, 3009},{ 465, 3261},{ 523, 3509},{ 585, 3746},
- { 639, 3980},{ 695, 4219},{ 754, 4449},{ 803, 4671},
- { 873, 4840},{ 953, 5001},{ 1015, 5156},{ 1071, 5286},
- { 1137, 5464},{ 1191, 5629},{ 1249, 5782},{ 1359, 5885}
- },
- /*Cr qi=23 INTER*/
- {
- { 84, 29},{ 69, 343},{ 58, 660},{ 62, 1041},
- { 75, 1448},{ 88, 1853},{ 97, 2258},{ 102, 2659},
- { 105, 3050},{ 108, 3430},{ 113, 3799},{ 116, 4155},
- { 121, 4505},{ 126, 4845},{ 132, 5176},{ 142, 5504},
- { 153, 5826},{ 165, 6133},{ 180, 6432},{ 197, 6722},
- { 212, 7005},{ 226, 7287},{ 244, 7555},{ 258, 7828}
- }
- }
- },
- {
- {
- /*Y' qi=24 INTRA*/
- {
- { 125, -34},{ 268, 1444},{ 547, 2590},{ 866, 3422},
- { 1172, 4098},{ 1476, 4702},{ 1790, 5222},{ 2117, 5678},
- { 2453, 6080},{ 2811, 6418},{ 3178, 6700},{ 3552, 6895},
- { 3928, 7055},{ 4286, 7243},{ 4627, 7477},{ 4981, 7674},
- { 5344, 7802},{ 5683, 7944},{ 6009, 8043},{ 6313, 8082},
- { 6633, 8111},{ 6959, 8151},{ 7280, 8197},{ 7660, 8221}
- },
- /*Y' qi=24 INTER*/
- {
- { 62, -63},{ 68, 1345},{ 134, 2840},{ 199, 4245},
- { 256, 5508},{ 304, 6715},{ 371, 7880},{ 484, 8950},
- { 652, 9899},{ 892,10709},{ 1238,11334},{ 1722,11722},
- { 2326,11875},{ 2983,11864},{ 3616,11783},{ 4189,11678},
- { 4707,11570},{ 5178,11476},{ 5617,11395},{ 6017,11319},
- { 6380,11252},{ 6720,11185},{ 7044,11126},{ 7377,11118}
- }
- },
- {
- /*Cb qi=24 INTRA*/
- {
- { 4, 3},{ 75, 367},{ 132, 745},{ 159, 1182},
- { 187, 1634},{ 230, 2061},{ 289, 2439},{ 361, 2753},
- { 425, 3034},{ 492, 3278},{ 566, 3490},{ 630, 3720},
- { 686, 3956},{ 732, 4190},{ 777, 4420},{ 829, 4637},
- { 894, 4840},{ 958, 5012},{ 1023, 5155},{ 1090, 5326},
- { 1165, 5502},{ 1226, 5622},{ 1299, 5717},{ 1408, 5887}
- },
- /*Cb qi=24 INTER*/
- {
- { 110, 35},{ 92, 337},{ 70, 651},{ 63, 1033},
- { 74, 1440},{ 91, 1846},{ 102, 2248},{ 109, 2644},
- { 114, 3031},{ 120, 3404},{ 127, 3762},{ 133, 4109},
- { 138, 4445},{ 144, 4772},{ 151, 5094},{ 159, 5411},
- { 168, 5728},{ 180, 6037},{ 195, 6338},{ 210, 6640},
- { 227, 6944},{ 249, 7236},{ 272, 7528},{ 299, 7809}
- }
- },
- {
- /*Cr qi=24 INTRA*/
- {
- { 5, 6},{ 72, 380},{ 124, 770},{ 158, 1222},
- { 195, 1668},{ 240, 2079},{ 297, 2438},{ 367, 2715},
- { 433, 2966},{ 488, 3218},{ 549, 3467},{ 609, 3701},
- { 664, 3935},{ 728, 4165},{ 792, 4379},{ 845, 4586},
- { 917, 4744},{ 995, 4898},{ 1063, 5049},{ 1120, 5187},
- { 1190, 5359},{ 1249, 5522},{ 1304, 5672},{ 1397, 5806}
- },
- /*Cr qi=24 INTER*/
- {
- { 91, 56},{ 73, 353},{ 61, 664},{ 66, 1045},
- { 80, 1449},{ 95, 1851},{ 103, 2250},{ 107, 2648},
- { 111, 3038},{ 116, 3413},{ 120, 3774},{ 124, 4128},
- { 130, 4471},{ 138, 4802},{ 145, 5130},{ 156, 5453},
- { 171, 5764},{ 187, 6061},{ 204, 6355},{ 220, 6643},
- { 238, 6923},{ 254, 7204},{ 275, 7475},{ 289, 7752}
- }
- }
- },
- {
- {
- /*Y' qi=25 INTRA*/
- {
- { 125, -28},{ 285, 1426},{ 582, 2540},{ 917, 3351},
- { 1244, 3997},{ 1569, 4570},{ 1903, 5071},{ 2258, 5498},
- { 2626, 5866},{ 3002, 6182},{ 3382, 6448},{ 3770, 6623},
- { 4162, 6760},{ 4528, 6934},{ 4882, 7144},{ 5249, 7328},
- { 5610, 7453},{ 5958, 7578},{ 6291, 7672},{ 6597, 7708},
- { 6928, 7715},{ 7258, 7737},{ 7575, 7781},{ 7950, 7829}
- },
- /*Y' qi=25 INTER*/
- {
- { 64, -16},{ 72, 1348},{ 139, 2832},{ 206, 4218},
- { 268, 5465},{ 322, 6659},{ 403, 7803},{ 540, 8838},
- { 747, 9734},{ 1044,10465},{ 1473,10981},{ 2048,11249},
- { 2717,11311},{ 3397,11257},{ 4025,11161},{ 4589,11052},
- { 5099,10947},{ 5560,10859},{ 5989,10786},{ 6389,10717},
- { 6753,10652},{ 7078,10592},{ 7389,10535},{ 7697,10460}
- }
- },
- {
- /*Cb qi=25 INTRA*/
- {
- { 3, 3},{ 78, 368},{ 133, 745},{ 159, 1180},
- { 193, 1627},{ 242, 2046},{ 304, 2411},{ 381, 2714},
- { 456, 2983},{ 527, 3224},{ 598, 3437},{ 667, 3655},
- { 726, 3888},{ 776, 4117},{ 826, 4333},{ 883, 4543},
- { 954, 4727},{ 1019, 4878},{ 1095, 5014},{ 1171, 5187},
- { 1255, 5342},{ 1319, 5458},{ 1396, 5546},{ 1536, 5678}
- },
- /*Cb qi=25 INTER*/
- {
- { 117, 32},{ 89, 342},{ 67, 660},{ 64, 1037},
- { 77, 1441},{ 93, 1845},{ 105, 2243},{ 113, 2633},
- { 120, 3016},{ 125, 3387},{ 131, 3739},{ 137, 4080},
- { 144, 4416},{ 152, 4741},{ 160, 5057},{ 169, 5369},
- { 180, 5680},{ 193, 5990},{ 209, 6294},{ 227, 6594},
- { 249, 6888},{ 269, 7180},{ 294, 7467},{ 317, 7768}
- }
- },
- {
- /*Cr qi=25 INTRA*/
- {
- { 6, 6},{ 74, 380},{ 129, 770},{ 165, 1220},
- { 201, 1658},{ 253, 2061},{ 315, 2410},{ 388, 2676},
- { 462, 2920},{ 523, 3166},{ 584, 3404},{ 647, 3637},
- { 701, 3870},{ 769, 4086},{ 838, 4296},{ 898, 4491},
- { 980, 4627},{ 1065, 4759},{ 1126, 4920},{ 1187, 5058},
- { 1283, 5180},{ 1347, 5332},{ 1404, 5475},{ 1527, 5534}
- },
- /*Cr qi=25 INTER*/
- {
- { 92, 41},{ 75, 347},{ 64, 664},{ 70, 1045},
- { 85, 1448},{ 98, 1849},{ 105, 2245},{ 110, 2637},
- { 115, 3023},{ 120, 3395},{ 126, 3753},{ 131, 4102},
- { 136, 4439},{ 145, 4768},{ 156, 5094},{ 168, 5410},
- { 184, 5717},{ 203, 6010},{ 221, 6300},{ 239, 6577},
- { 262, 6847},{ 282, 7123},{ 303, 7390},{ 322, 7665}
- }
- }
- },
- {
- {
- /*Y' qi=26 INTRA*/
- {
- { 130, -24},{ 292, 1423},{ 594, 2525},{ 943, 3307},
- { 1289, 3921},{ 1633, 4467},{ 1991, 4943},{ 2368, 5348},
- { 2753, 5696},{ 3148, 5991},{ 3545, 6247},{ 3942, 6415},
- { 4342, 6535},{ 4726, 6690},{ 5093, 6883},{ 5466, 7047},
- { 5840, 7159},{ 6202, 7274},{ 6545, 7351},{ 6855, 7375},
- { 7186, 7384},{ 7517, 7416},{ 7840, 7447},{ 8238, 7450}
- },
- /*Y' qi=26 INTER*/
- {
- { 52, 16},{ 75, 1336},{ 143, 2815},{ 213, 4191},
- { 278, 5427},{ 339, 6611},{ 436, 7734},{ 600, 8732},
- { 843, 9579},{ 1195,10243},{ 1702,10660},{ 2355,10825},
- { 3070,10820},{ 3755,10743},{ 4372,10643},{ 4925,10538},
- { 5426,10440},{ 5882,10354},{ 6296,10290},{ 6686,10224},
- { 7049,10163},{ 7380,10113},{ 7672,10062},{ 7937,10021}
- }
- },
- {
- /*Cb qi=26 INTRA*/
- {
- { 4, 3},{ 79, 368},{ 138, 745},{ 167, 1180},
- { 200, 1623},{ 252, 2034},{ 322, 2389},{ 403, 2682},
- { 480, 2941},{ 558, 3176},{ 631, 3393},{ 700, 3608},
- { 766, 3825},{ 819, 4046},{ 868, 4265},{ 926, 4472},
- { 1002, 4645},{ 1070, 4800},{ 1151, 4924},{ 1242, 5063},
- { 1325, 5221},{ 1393, 5338},{ 1464, 5431},{ 1595, 5559}
- },
- /*Cb qi=26 INTER*/
- {
- { 98, 33},{ 83, 343},{ 65, 662},{ 65, 1037},
- { 80, 1437},{ 96, 1839},{ 107, 2238},{ 115, 2628},
- { 122, 3007},{ 128, 3373},{ 134, 3722},{ 142, 4060},
- { 149, 4390},{ 158, 4713},{ 167, 5029},{ 178, 5341},
- { 191, 5647},{ 208, 5948},{ 227, 6244},{ 247, 6539},
- { 269, 6833},{ 295, 7114},{ 328, 7388},{ 369, 7658}
- }
- },
- {
- /*Cr qi=26 INTRA*/
- {
- { 5, 6},{ 75, 380},{ 133, 769},{ 172, 1217},
- { 212, 1652},{ 266, 2048},{ 333, 2384},{ 412, 2643},
- { 490, 2880},{ 552, 3124},{ 616, 3365},{ 681, 3594},
- { 739, 3816},{ 810, 4024},{ 880, 4224},{ 945, 4405},
- { 1029, 4538},{ 1114, 4674},{ 1183, 4822},{ 1254, 4946},
- { 1346, 5063},{ 1417, 5201},{ 1478, 5345},{ 1597, 5411}
- },
- /*Cr qi=26 INTER*/
- {
- { 97, 29},{ 75, 342},{ 62, 667},{ 70, 1047},
- { 87, 1447},{ 100, 1846},{ 107, 2242},{ 113, 2633},
- { 118, 3016},{ 123, 3382},{ 128, 3737},{ 135, 4082},
- { 142, 4417},{ 151, 4746},{ 162, 5066},{ 176, 5377},
- { 194, 5679},{ 217, 5963},{ 239, 6244},{ 260, 6522},
- { 284, 6789},{ 309, 7052},{ 335, 7313},{ 355, 7582}
+ { 0, 741},{ 9, 743},{ 16, 1034},{ 26, 1385},
+ { 39, 1741},{ 48, 2090},{ 56, 2459},{ 64, 2850},
+ { 72, 3242},{ 81, 3622},{ 89, 3980},{ 98, 4323},
+ { 104, 4667},{ 110, 5005},{ 118, 5337},{ 126, 5675},
+ { 137, 5998},{ 146, 6311},{ 156, 6621},{ 170, 6914},
+ { 181, 7205},{ 196, 7490},{ 203, 7779},{ 232, 8012}
}
}
},
@@ -1732,557 +217,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=27 INTRA*/
{
- { 118, -10},{ 308, 1404},{ 630, 2473},{ 997, 3227},
- { 1360, 3819},{ 1719, 4354},{ 2086, 4829},{ 2470, 5233},
- { 2863, 5576},{ 3267, 5870},{ 3677, 6117},{ 4085, 6268},
- { 4499, 6376},{ 4888, 6521},{ 5257, 6705},{ 5638, 6865},
- { 6020, 6962},{ 6394, 7056},{ 6744, 7130},{ 7051, 7158},
- { 7386, 7164},{ 7717, 7185},{ 8042, 7209},{ 8444, 7206}
+ { 121, 378},{ 379, 1464},{ 810, 2335},{ 1447, 2725},
+ { 1851, 3194},{ 2311, 3655},{ 2747, 4081},{ 3211, 4393},
+ { 3640, 4672},{ 4056, 4933},{ 4427, 5150},{ 4842, 5259},
+ { 5220, 5381},{ 5584, 5443},{ 5925, 5648},{ 6233, 5783},
+ { 6547, 5944},{ 6905, 6056},{ 7203, 6181},{ 7526, 6207},
+ { 7800, 6330},{ 8175, 6312},{ 8415, 6437},{ 8705, 6459}
},
/*Y' qi=27 INTER*/
{
- { 54, 19},{ 77, 1333},{ 147, 2806},{ 221, 4166},
- { 290, 5390},{ 360, 6564},{ 474, 7665},{ 664, 8630},
- { 949, 9423},{ 1370,10002},{ 1958,10323},{ 2670,10414},
- { 3406,10375},{ 4086,10285},{ 4691,10182},{ 5233,10085},
- { 5724, 9994},{ 6169, 9918},{ 6582, 9863},{ 6962, 9813},
- { 7316, 9759},{ 7645, 9707},{ 7948, 9660},{ 8262, 9623}
+ { 48, 199},{ 90, 1458},{ 167, 2824},{ 291, 4050},
+ { 434, 5144},{ 638, 6133},{ 901, 7011},{ 1249, 7743},
+ { 1726, 8280},{ 2317, 8616},{ 2957, 8789},{ 3561, 8896},
+ { 4126, 8936},{ 4646, 8933},{ 5115, 8931},{ 5579, 8890},
+ { 6008, 8804},{ 6411, 8744},{ 6774, 8646},{ 7153, 8549},
+ { 7475, 8462},{ 7790, 8372},{ 8069, 8280},{ 8299, 8278}
}
},
{
/*Cb qi=27 INTRA*/
{
- { 4, 3},{ 79, 368},{ 137, 745},{ 166, 1180},
- { 200, 1622},{ 253, 2030},{ 324, 2381},{ 407, 2671},
- { 487, 2925},{ 567, 3156},{ 640, 3372},{ 712, 3580},
- { 782, 3792},{ 833, 4015},{ 887, 4227},{ 954, 4422},
- { 1031, 4592},{ 1103, 4738},{ 1187, 4856},{ 1280, 4990},
- { 1371, 5135},{ 1442, 5244},{ 1520, 5321},{ 1684, 5398}
+ { 75, 612},{ 117, 751},{ 160, 1068},{ 195, 1406},
+ { 240, 1741},{ 305, 2066},{ 364, 2359},{ 454, 2639},
+ { 538, 2899},{ 609, 3149},{ 664, 3384},{ 730, 3625},
+ { 785, 3860},{ 836, 4094},{ 872, 4312},{ 948, 4507},
+ { 1023, 4677},{ 1081, 4843},{ 1165, 4985},{ 1238, 5092},
+ { 1316, 5235},{ 1418, 5345},{ 1430, 5478},{ 1505, 5538}
},
/*Cb qi=27 INTER*/
{
- { 113, 20},{ 90, 338},{ 66, 661},{ 67, 1034},
- { 82, 1438},{ 97, 1842},{ 108, 2238},{ 115, 2624},
- { 123, 3000},{ 130, 3361},{ 138, 3708},{ 146, 4040},
- { 155, 4367},{ 164, 4688},{ 174, 4999},{ 186, 5306},
- { 203, 5609},{ 222, 5908},{ 243, 6202},{ 268, 6494},
- { 295, 6781},{ 326, 7058},{ 367, 7319},{ 420, 7551}
+ { 16, 637},{ 13, 634},{ 32, 869},{ 46, 1230},
+ { 55, 1583},{ 67, 1950},{ 79, 2320},{ 93, 2690},
+ { 107, 3052},{ 120, 3399},{ 133, 3733},{ 146, 4054},
+ { 162, 4367},{ 175, 4679},{ 191, 4984},{ 211, 5285},
+ { 232, 5581},{ 252, 5875},{ 276, 6155},{ 305, 6433},
+ { 333, 6706},{ 364, 6967},{ 398, 7244},{ 474, 7394}
}
},
{
/*Cr qi=27 INTRA*/
{
- { 5, 6},{ 75, 380},{ 133, 770},{ 173, 1217},
- { 214, 1650},{ 268, 2040},{ 337, 2375},{ 418, 2631},
- { 496, 2862},{ 558, 3104},{ 625, 3346},{ 692, 3571},
- { 753, 3786},{ 825, 3989},{ 896, 4182},{ 969, 4352},
- { 1059, 4479},{ 1144, 4614},{ 1212, 4757},{ 1284, 4871},
- { 1380, 4982},{ 1457, 5125},{ 1528, 5267},{ 1651, 5346}
+ { 64, 632},{ 107, 763},{ 147, 1054},{ 176, 1411},
+ { 255, 1770},{ 324, 2079},{ 411, 2359},{ 475, 2621},
+ { 545, 2880},{ 590, 3158},{ 647, 3425},{ 709, 3648},
+ { 766, 3878},{ 831, 4082},{ 911, 4260},{ 960, 4493},
+ { 1042, 4558},{ 1115, 4760},{ 1200, 4852},{ 1280, 4950},
+ { 1327, 5186},{ 1445, 5157},{ 1443, 5431},{ 1518, 5493}
},
/*Cr qi=27 INTER*/
{
- { 92, 24},{ 74, 341},{ 61, 669},{ 71, 1049},
- { 88, 1448},{ 100, 1849},{ 107, 2243},{ 113, 2631},
- { 119, 3010},{ 125, 3373},{ 131, 3723},{ 137, 4064},
- { 146, 4396},{ 159, 4720},{ 172, 5033},{ 189, 5340},
- { 210, 5636},{ 233, 5920},{ 256, 6197},{ 282, 6465},
- { 310, 6730},{ 332, 7000},{ 359, 7259},{ 385, 7515}
- }
- }
- },
- {
- {
- /*Y' qi=28 INTRA*/
- {
- { 116, -8},{ 314, 1400},{ 640, 2458},{ 1013, 3197},
- { 1386, 3768},{ 1762, 4279},{ 2151, 4733},{ 2558, 5117},
- { 2970, 5442},{ 3393, 5714},{ 3820, 5935},{ 4243, 6069},
- { 4671, 6161},{ 5074, 6289},{ 5456, 6457},{ 5849, 6598},
- { 6244, 6689},{ 6632, 6777},{ 6984, 6833},{ 7294, 6855},
- { 7625, 6862},{ 7961, 6875},{ 8302, 6890},{ 8720, 6883}
- },
- /*Y' qi=28 INTER*/
- {
- { 54, 8},{ 81, 1333},{ 154, 2793},{ 231, 4138},
- { 304, 5352},{ 384, 6512},{ 519, 7585},{ 743, 8508},
- { 1082, 9236},{ 1587, 9717},{ 2267, 9928},{ 3034, 9944},
- { 3775, 9878},{ 4438, 9786},{ 5031, 9686},{ 5563, 9601},
- { 6042, 9523},{ 6481, 9456},{ 6890, 9405},{ 7266, 9356},
- { 7614, 9313},{ 7933, 9265},{ 8238, 9220},{ 8545, 9193}
- }
- },
- {
- /*Cb qi=28 INTRA*/
- {
- { 3, 3},{ 80, 368},{ 138, 746},{ 168, 1179},
- { 208, 1615},{ 268, 2014},{ 345, 2354},{ 432, 2637},
- { 515, 2884},{ 595, 3108},{ 669, 3323},{ 745, 3533},
- { 818, 3740},{ 876, 3953},{ 932, 4160},{ 1003, 4349},
- { 1088, 4501},{ 1154, 4648},{ 1241, 4768},{ 1349, 4889},
- { 1441, 5023},{ 1524, 5113},{ 1611, 5187},{ 1783, 5283}
- },
- /*Cb qi=28 INTER*/
- {
- { 117, 29},{ 91, 341},{ 65, 663},{ 68, 1038},
- { 85, 1440},{ 100, 1841},{ 110, 2234},{ 119, 2616},
- { 127, 2985},{ 135, 3342},{ 142, 3685},{ 151, 4015},
- { 162, 4337},{ 174, 4652},{ 186, 4960},{ 201, 5264},
- { 218, 5567},{ 239, 5863},{ 266, 6149},{ 295, 6434},
- { 328, 6715},{ 371, 6976},{ 409, 7239},{ 460, 7477}
- }
- },
- {
- /*Cr qi=28 INTRA*/
- {
- { 6, 7},{ 79, 381},{ 138, 771},{ 178, 1215},
- { 222, 1644},{ 285, 2026},{ 359, 2347},{ 441, 2597},
- { 521, 2827},{ 588, 3066},{ 655, 3303},{ 725, 3523},
- { 791, 3728},{ 870, 3920},{ 950, 4103},{ 1030, 4265},
- { 1121, 4388},{ 1198, 4520},{ 1266, 4659},{ 1356, 4759},
- { 1461, 4865},{ 1540, 4993},{ 1619, 5115},{ 1786, 5160}
- },
- /*Cr qi=28 INTER*/
- {
- { 96, 18},{ 78, 340},{ 66, 672},{ 74, 1051},
- { 90, 1450},{ 103, 1845},{ 110, 2235},{ 116, 2619},
- { 122, 2995},{ 129, 3356},{ 137, 3702},{ 146, 4038},
- { 156, 4365},{ 168, 4684},{ 182, 4995},{ 203, 5297},
- { 227, 5588},{ 253, 5866},{ 282, 6131},{ 311, 6394},
- { 339, 6664},{ 366, 6918},{ 400, 7171},{ 424, 7450}
- }
- }
- },
- {
- {
- /*Y' qi=29 INTRA*/
- {
- { 112, 7},{ 334, 1382},{ 681, 2410},{ 1081, 3112},
- { 1484, 3650},{ 1894, 4128},{ 2316, 4547},{ 2749, 4905},
- { 3188, 5208},{ 3634, 5458},{ 4079, 5666},{ 4517, 5791},
- { 4952, 5870},{ 5359, 5983},{ 5754, 6137},{ 6165, 6268},
- { 6568, 6351},{ 6958, 6423},{ 7320, 6471},{ 7638, 6490},
- { 7979, 6490},{ 8313, 6499},{ 8651, 6517},{ 9085, 6499}
- },
- /*Y' qi=29 INTER*/
- {
- { 55, 15},{ 85, 1336},{ 160, 2780},{ 242, 4104},
- { 323, 5302},{ 418, 6443},{ 586, 7480},{ 859, 8342},
- { 1278, 8982},{ 1888, 9347},{ 2658, 9457},{ 3457, 9425},
- { 4192, 9343},{ 4842, 9247},{ 5417, 9162},{ 5935, 9086},
- { 6404, 9011},{ 6841, 8952},{ 7241, 8907},{ 7609, 8867},
- { 7953, 8832},{ 8267, 8792},{ 8562, 8740},{ 8836, 8701}
- }
- },
- {
- /*Cb qi=29 INTRA*/
- {
- { 5, 3},{ 84, 368},{ 144, 746},{ 176, 1175},
- { 219, 1604},{ 285, 1991},{ 372, 2318},{ 462, 2591},
- { 546, 2833},{ 628, 3058},{ 704, 3274},{ 788, 3473},
- { 870, 3664},{ 935, 3865},{ 995, 4059},{ 1072, 4239},
- { 1167, 4388},{ 1248, 4518},{ 1334, 4634},{ 1429, 4765},
- { 1536, 4884},{ 1628, 4964},{ 1716, 5038},{ 1885, 5128}
- },
- /*Cb qi=29 INTER*/
- {
- { 126, 25},{ 95, 340},{ 69, 662},{ 71, 1039},
- { 88, 1440},{ 102, 1839},{ 113, 2227},{ 122, 2604},
- { 132, 2969},{ 141, 3320},{ 151, 3659},{ 161, 3985},
- { 172, 4301},{ 186, 4612},{ 200, 4917},{ 219, 5213},
- { 241, 5509},{ 265, 5800},{ 296, 6081},{ 329, 6360},
- { 369, 6633},{ 414, 6899},{ 465, 7148},{ 520, 7387}
- }
- },
- {
- /*Cr qi=29 INTRA*/
- {
- { 6, 7},{ 82, 382},{ 142, 772},{ 185, 1211},
- { 233, 1632},{ 303, 2000},{ 388, 2306},{ 475, 2550},
- { 556, 2779},{ 627, 3007},{ 707, 3237},{ 778, 3459},
- { 843, 3654},{ 927, 3834},{ 1012, 4012},{ 1101, 4152},
- { 1197, 4262},{ 1275, 4399},{ 1359, 4511},{ 1455, 4596},
- { 1562, 4708},{ 1644, 4833},{ 1719, 4954},{ 1888, 4988}
- },
- /*Cr qi=29 INTER*/
- {
- { 101, 28},{ 81, 343},{ 67, 673},{ 75, 1053},
- { 93, 1450},{ 106, 1844},{ 113, 2230},{ 119, 2610},
- { 127, 2980},{ 135, 3334},{ 143, 3676},{ 153, 4007},
- { 165, 4330},{ 180, 4645},{ 201, 4951},{ 224, 5243},
- { 253, 5522},{ 284, 5794},{ 314, 6060},{ 345, 6322},
- { 381, 6578},{ 419, 6828},{ 455, 7073},{ 495, 7316}
- }
- }
- },
- {
- {
- /*Y' qi=30 INTRA*/
- {
- { 112, 8},{ 335, 1380},{ 682, 2401},{ 1083, 3093},
- { 1489, 3619},{ 1902, 4092},{ 2332, 4511},{ 2777, 4865},
- { 3231, 5156},{ 3693, 5394},{ 4153, 5585},{ 4605, 5689},
- { 5049, 5764},{ 5468, 5871},{ 5875, 6004},{ 6295, 6120},
- { 6706, 6201},{ 7099, 6273},{ 7461, 6311},{ 7785, 6320},
- { 8128, 6322},{ 8469, 6331},{ 8806, 6342},{ 9220, 6338}
- },
- /*Y' qi=30 INTER*/
- {
- { 58, 8},{ 90, 1340},{ 169, 2771},{ 257, 4079},
- { 345, 5266},{ 459, 6387},{ 660, 7383},{ 990, 8180},
- { 1496, 8726},{ 2203, 8992},{ 3029, 9038},{ 3833, 8984},
- { 4549, 8900},{ 5183, 8813},{ 5745, 8735},{ 6250, 8674},
- { 6715, 8619},{ 7138, 8565},{ 7529, 8528},{ 7899, 8495},
- { 8234, 8465},{ 8550, 8429},{ 8856, 8395},{ 9160, 8374}
- }
- },
- {
- /*Cb qi=30 INTRA*/
- {
- { 7, 3},{ 88, 369},{ 149, 747},{ 185, 1175},
- { 232, 1599},{ 304, 1976},{ 392, 2293},{ 486, 2557},
- { 573, 2797},{ 656, 3027},{ 735, 3243},{ 819, 3442},
- { 903, 3629},{ 966, 3828},{ 1025, 4027},{ 1105, 4204},
- { 1201, 4343},{ 1282, 4469},{ 1379, 4575},{ 1486, 4689},
- { 1588, 4813},{ 1678, 4900},{ 1767, 4969},{ 1911, 5080}
- },
- /*Cb qi=30 INTER*/
- {
- { 120, 23},{ 96, 336},{ 72, 661},{ 75, 1043},
- { 91, 1441},{ 105, 1837},{ 117, 2221},{ 127, 2592},
- { 137, 2953},{ 148, 3301},{ 159, 3635},{ 170, 3959},
- { 184, 4271},{ 199, 4578},{ 216, 4879},{ 238, 5175},
- { 262, 5466},{ 294, 5750},{ 332, 6027},{ 373, 6298},
- { 421, 6559},{ 473, 6805},{ 526, 7053},{ 587, 7298}
- }
- },
- {
- /*Cr qi=30 INTRA*/
- {
- { 10, 7},{ 89, 384},{ 147, 773},{ 192, 1211},
- { 245, 1627},{ 322, 1984},{ 412, 2280},{ 501, 2520},
- { 583, 2750},{ 654, 2982},{ 736, 3207},{ 810, 3419},
- { 873, 3614},{ 957, 3794},{ 1048, 3965},{ 1139, 4102},
- { 1237, 4208},{ 1327, 4328},{ 1408, 4448},{ 1496, 4545},
- { 1604, 4652},{ 1699, 4760},{ 1780, 4877},{ 1937, 4942}
- },
- /*Cr qi=30 INTER*/
- {
- { 115, 26},{ 89, 342},{ 70, 672},{ 79, 1055},
- { 96, 1451},{ 108, 1841},{ 116, 2222},{ 124, 2599},
- { 132, 2965},{ 141, 3316},{ 151, 3655},{ 163, 3984},
- { 178, 4301},{ 197, 4609},{ 219, 4909},{ 247, 5195},
- { 280, 5469},{ 317, 5734},{ 351, 5991},{ 383, 6248},
- { 423, 6500},{ 467, 6744},{ 502, 6995},{ 558, 7226}
- }
- }
- },
- {
- {
- /*Y' qi=31 INTRA*/
- {
- { 116, 20},{ 359, 1361},{ 732, 2350},{ 1162, 3010},
- { 1597, 3507},{ 2042, 3950},{ 2503, 4339},{ 2974, 4670},
- { 3446, 4951},{ 3922, 5179},{ 4394, 5357},{ 4858, 5454},
- { 5313, 5519},{ 5734, 5626},{ 6154, 5755},{ 6585, 5859},
- { 7004, 5928},{ 7408, 5998},{ 7775, 6039},{ 8102, 6048},
- { 8442, 6051},{ 8790, 6054},{ 9136, 6057},{ 9554, 6041}
- },
- /*Y' qi=31 INTER*/
- {
- { 53, 12},{ 90, 1340},{ 169, 2765},{ 259, 4062},
- { 353, 5236},{ 483, 6340},{ 713, 7305},{ 1086, 8059},
- { 1651, 8548},{ 2423, 8751},{ 3288, 8754},{ 4106, 8674},
- { 4827, 8572},{ 5451, 8482},{ 6007, 8407},{ 6514, 8344},
- { 6970, 8282},{ 7397, 8225},{ 7795, 8193},{ 8159, 8161},
- { 8498, 8120},{ 8814, 8093},{ 9127, 8066},{ 9432, 8040}
- }
- },
- {
- /*Cb qi=31 INTRA*/
- {
- { 7, 3},{ 88, 369},{ 149, 746},{ 185, 1173},
- { 234, 1595},{ 308, 1967},{ 399, 2278},{ 494, 2537},
- { 583, 2774},{ 669, 2997},{ 755, 3204},{ 847, 3390},
- { 936, 3569},{ 1008, 3759},{ 1078, 3942},{ 1162, 4104},
- { 1262, 4238},{ 1352, 4364},{ 1442, 4470},{ 1557, 4567},
- { 1676, 4674},{ 1759, 4781},{ 1850, 4853},{ 2043, 4897}
- },
- /*Cb qi=31 INTER*/
- {
- { 121, 23},{ 96, 335},{ 72, 660},{ 74, 1043},
- { 90, 1440},{ 105, 1834},{ 116, 2217},{ 127, 2586},
- { 138, 2945},{ 148, 3293},{ 159, 3626},{ 172, 3945},
- { 185, 4256},{ 202, 4559},{ 223, 4856},{ 245, 5150},
- { 272, 5440},{ 306, 5719},{ 346, 5989},{ 391, 6253},
- { 443, 6511},{ 510, 6743},{ 583, 6965},{ 651, 7182}
- }
- },
- {
- /*Cr qi=31 INTRA*/
- {
- { 10, 7},{ 88, 384},{ 147, 773},{ 192, 1209},
- { 247, 1622},{ 326, 1974},{ 417, 2262},{ 509, 2500},
- { 596, 2726},{ 670, 2949},{ 754, 3170},{ 836, 3370},
- { 912, 3548},{ 999, 3724},{ 1093, 3888},{ 1198, 4000},
- { 1304, 4095},{ 1384, 4230},{ 1470, 4347},{ 1577, 4422},
- { 1696, 4513},{ 1798, 4620},{ 1869, 4746},{ 1991, 4798}
- },
- /*Cr qi=31 INTER*/
- {
- { 113, 32},{ 88, 345},{ 69, 674},{ 79, 1055},
- { 96, 1451},{ 108, 1839},{ 115, 2218},{ 123, 2592},
- { 132, 2957},{ 141, 3308},{ 151, 3643},{ 163, 3968},
- { 179, 4285},{ 200, 4590},{ 225, 4886},{ 254, 5169},
- { 291, 5436},{ 330, 5696},{ 368, 5951},{ 409, 6200},
- { 452, 6448},{ 493, 6695},{ 536, 6940},{ 571, 7204}
- }
- }
- },
- {
- {
- /*Y' qi=32 INTRA*/
- {
- { 123, 26},{ 370, 1356},{ 756, 2321},{ 1211, 2944},
- { 1674, 3408},{ 2148, 3826},{ 2639, 4193},{ 3138, 4504},
- { 3634, 4765},{ 4133, 4973},{ 4625, 5137},{ 5101, 5225},
- { 5567, 5274},{ 6002, 5363},{ 6437, 5482},{ 6885, 5566},
- { 7312, 5625},{ 7723, 5686},{ 8101, 5721},{ 8429, 5732},
- { 8769, 5728},{ 9120, 5726},{ 9472, 5723},{ 9918, 5700}
- },
- /*Y' qi=32 INTER*/
- {
- { 54, -3},{ 95, 1343},{ 179, 2750},{ 276, 4027},
- { 382, 5185},{ 543, 6256},{ 830, 7161},{ 1301, 7815},
- { 2003, 8172},{ 2883, 8266},{ 3779, 8217},{ 4578, 8127},
- { 5274, 8035},{ 5886, 7952},{ 6430, 7887},{ 6929, 7835},
- { 7380, 7779},{ 7796, 7737},{ 8190, 7705},{ 8552, 7672},
- { 8896, 7640},{ 9210, 7612},{ 9510, 7589},{ 9746, 7552}
- }
- },
- {
- /*Cb qi=32 INTRA*/
- {
- { 6, 3},{ 89, 369},{ 153, 746},{ 193, 1167},
- { 247, 1577},{ 330, 1935},{ 429, 2236},{ 528, 2494},
- { 620, 2732},{ 712, 2948},{ 801, 3146},{ 898, 3325},
- { 999, 3489},{ 1078, 3664},{ 1155, 3832},{ 1251, 3985},
- { 1360, 4115},{ 1451, 4236},{ 1549, 4338},{ 1667, 4433},
- { 1797, 4522},{ 1891, 4613},{ 1989, 4687},{ 2162, 4776}
- },
- /*Cb qi=32 INTER*/
- {
- { 116, -1},{ 98, 321},{ 80, 656},{ 80, 1042},
- { 96, 1438},{ 110, 1827},{ 122, 2205},{ 133, 2570},
- { 144, 2925},{ 157, 3268},{ 170, 3597},{ 185, 3911},
- { 202, 4216},{ 221, 4516},{ 244, 4809},{ 273, 5096},
- { 308, 5376},{ 350, 5644},{ 401, 5907},{ 459, 6160},
- { 520, 6401},{ 592, 6630},{ 676, 6837},{ 758, 7050}
- }
- },
- {
- /*Cr qi=32 INTRA*/
- {
- { 12, 7},{ 91, 386},{ 152, 773},{ 201, 1202},
- { 261, 1603},{ 347, 1942},{ 447, 2223},{ 540, 2460},
- { 626, 2684},{ 711, 2901},{ 801, 3115},{ 887, 3312},
- { 969, 3480},{ 1068, 3633},{ 1176, 3779},{ 1283, 3885},
- { 1392, 3969},{ 1485, 4090},{ 1573, 4206},{ 1686, 4274},
- { 1813, 4354},{ 1911, 4459},{ 2004, 4563},{ 2162, 4590}
- },
- /*Cr qi=32 INTER*/
- {
- { 129, 5},{ 98, 334},{ 75, 673},{ 84, 1055},
- { 101, 1448},{ 113, 1832},{ 121, 2206},{ 129, 2577},
- { 140, 2937},{ 151, 3282},{ 163, 3614},{ 179, 3932},
- { 198, 4240},{ 221, 4542},{ 252, 4830},{ 290, 5102},
- { 329, 5364},{ 373, 5618},{ 420, 5864},{ 468, 6105},
- { 513, 6351},{ 564, 6587},{ 624, 6810},{ 697, 7017}
- }
- }
- },
- {
- {
- /*Y' qi=33 INTRA*/
- {
- { 115, 36},{ 388, 1338},{ 791, 2289},{ 1258, 2899},
- { 1732, 3352},{ 2220, 3760},{ 2730, 4117},{ 3244, 4415},
- { 3751, 4662},{ 4261, 4858},{ 4766, 5012},{ 5249, 5094},
- { 5719, 5141},{ 6159, 5225},{ 6597, 5333},{ 7044, 5416},
- { 7474, 5472},{ 7893, 5531},{ 8268, 5570},{ 8591, 5580},
- { 8931, 5578},{ 9283, 5579},{ 9634, 5582},{10067, 5560}
- },
- /*Y' qi=33 INTER*/
- {
- { 65, -14},{ 102, 1345},{ 190, 2736},{ 294, 3999},
- { 411, 5146},{ 597, 6192},{ 934, 7045},{ 1488, 7622},
- { 2281, 7895},{ 3213, 7937},{ 4108, 7871},{ 4883, 7784},
- { 5556, 7709},{ 6150, 7643},{ 6685, 7585},{ 7176, 7539},
- { 7620, 7502},{ 8034, 7466},{ 8427, 7435},{ 8793, 7409},
- { 9136, 7386},{ 9446, 7364},{ 9743, 7339},{10025, 7303}
- }
- },
- {
- /*Cb qi=33 INTRA*/
- {
- { 5, 3},{ 92, 369},{ 159, 746},{ 203, 1163},
- { 263, 1564},{ 353, 1911},{ 458, 2204},{ 557, 2460},
- { 650, 2697},{ 744, 2913},{ 836, 3110},{ 934, 3292},
- { 1036, 3454},{ 1125, 3616},{ 1204, 3781},{ 1298, 3932},
- { 1410, 4058},{ 1507, 4170},{ 1606, 4265},{ 1725, 4358},
- { 1853, 4445},{ 1955, 4535},{ 2067, 4597},{ 2258, 4663}
- },
- /*Cb qi=33 INTER*/
- {
- { 109, 37},{ 94, 343},{ 81, 662},{ 85, 1042},
- { 102, 1436},{ 116, 1823},{ 128, 2195},{ 141, 2554},
- { 154, 2906},{ 167, 3246},{ 183, 3570},{ 202, 3881},
- { 220, 4185},{ 241, 4482},{ 268, 4772},{ 302, 5053},
- { 341, 5328},{ 388, 5592},{ 446, 5846},{ 507, 6096},
- { 581, 6328},{ 670, 6534},{ 762, 6731},{ 842, 6922}
- }
- },
- {
- /*Cr qi=33 INTRA*/
- {
- { 11, 7},{ 93, 387},{ 158, 774},{ 211, 1197},
- { 278, 1589},{ 372, 1917},{ 475, 2191},{ 569, 2429},
- { 658, 2655},{ 744, 2868},{ 835, 3083},{ 926, 3271},
- { 1010, 3430},{ 1110, 3586},{ 1224, 3724},{ 1336, 3826},
- { 1449, 3908},{ 1547, 4021},{ 1636, 4136},{ 1751, 4200},
- { 1886, 4277},{ 1977, 4384},{ 2070, 4474},{ 2232, 4510}
- },
- /*Cr qi=33 INTER*/
- {
- { 77, 9},{ 90, 347},{ 80, 674},{ 91, 1053},
- { 107, 1444},{ 119, 1825},{ 127, 2196},{ 137, 2563},
- { 149, 2919},{ 161, 3259},{ 176, 3588},{ 194, 3905},
- { 217, 4209},{ 246, 4504},{ 280, 4786},{ 320, 5055},
- { 364, 5316},{ 409, 5565},{ 460, 5804},{ 517, 6039},
- { 578, 6264},{ 640, 6489},{ 701, 6721},{ 772, 6948}
- }
- }
- },
- {
- {
- /*Y' qi=34 INTRA*/
- {
- { 124, 40},{ 401, 1333},{ 823, 2262},{ 1318, 2842},
- { 1823, 3265},{ 2339, 3650},{ 2872, 3991},{ 3405, 4274},
- { 3926, 4513},{ 4448, 4704},{ 4961, 4845},{ 5450, 4921},
- { 5925, 4971},{ 6372, 5053},{ 6813, 5160},{ 7264, 5242},
- { 7704, 5291},{ 8124, 5346},{ 8500, 5382},{ 8831, 5384},
- { 9178, 5380},{ 9525, 5387},{ 9869, 5389},{10310, 5356}
- },
- /*Y' qi=34 INTER*/
- {
- { 64, -17},{ 101, 1344},{ 190, 2730},{ 299, 3981},
- { 430, 5110},{ 648, 6127},{ 1036, 6933},{ 1664, 7445},
- { 2535, 7652},{ 3504, 7653},{ 4402, 7572},{ 5173, 7479},
- { 5843, 7400},{ 6441, 7334},{ 6976, 7280},{ 7464, 7231},
- { 7910, 7189},{ 8332, 7157},{ 8730, 7125},{ 9091, 7103},
- { 9422, 7086},{ 9753, 7061},{10067, 7036},{10316, 7029}
- }
- },
- {
- /*Cb qi=34 INTRA*/
- {
- { 5, 3},{ 91, 369},{ 158, 746},{ 204, 1162},
- { 266, 1561},{ 358, 1903},{ 466, 2189},{ 570, 2439},
- { 665, 2671},{ 765, 2880},{ 864, 3069},{ 970, 3238},
- { 1079, 3392},{ 1174, 3545},{ 1265, 3693},{ 1360, 3841},
- { 1471, 3968},{ 1572, 4083},{ 1675, 4181},{ 1804, 4255},
- { 1939, 4332},{ 2048, 4411},{ 2155, 4484},{ 2339, 4584}
- },
- /*Cb qi=34 INTER*/
- {
- { 99, 44},{ 92, 345},{ 82, 661},{ 86, 1043},
- { 101, 1436},{ 116, 1821},{ 128, 2191},{ 140, 2549},
- { 154, 2898},{ 168, 3235},{ 185, 3556},{ 203, 3865},
- { 224, 4166},{ 248, 4457},{ 278, 4741},{ 315, 5021},
- { 361, 5289},{ 416, 5546},{ 483, 5792},{ 559, 6025},
- { 651, 6237},{ 752, 6432},{ 849, 6626},{ 967, 6790}
- }
- },
- {
- /*Cr qi=34 INTRA*/
- {
- { 11, 7},{ 93, 387},{ 158, 773},{ 212, 1195},
- { 282, 1584},{ 378, 1909},{ 483, 2179},{ 578, 2414},
- { 671, 2633},{ 766, 2837},{ 866, 3038},{ 960, 3223},
- { 1049, 3376},{ 1158, 3520},{ 1285, 3644},{ 1400, 3740},
- { 1505, 3828},{ 1616, 3928},{ 1713, 4030},{ 1820, 4104},
- { 1957, 4185},{ 2063, 4280},{ 2160, 4355},{ 2320, 4341}
- },
- /*Cr qi=34 INTER*/
- {
- { 78, 11},{ 89, 347},{ 79, 674},{ 90, 1053},
- { 106, 1444},{ 117, 1823},{ 127, 2192},{ 137, 2558},
- { 149, 2912},{ 163, 3249},{ 178, 3574},{ 197, 3888},
- { 222, 4189},{ 252, 4481},{ 293, 4755},{ 341, 5013},
- { 386, 5268},{ 436, 5512},{ 498, 5743},{ 563, 5970},
- { 622, 6200},{ 694, 6415},{ 776, 6622},{ 871, 6818}
- }
- }
- },
- {
- {
- /*Y' qi=35 INTRA*/
- {
- { 116, 51},{ 433, 1312},{ 881, 2221},{ 1406, 2771},
- { 1948, 3156},{ 2511, 3501},{ 3085, 3811},{ 3654, 4066},
- { 4212, 4273},{ 4763, 4444},{ 5298, 4572},{ 5799, 4638},
- { 6285, 4678},{ 6747, 4746},{ 7203, 4838},{ 7673, 4905},
- { 8124, 4950},{ 8552, 5003},{ 8938, 5027},{ 9275, 5026},
- { 9628, 5019},{ 9981, 5024},{10331, 5030},{10795, 5000}
- },
- /*Y' qi=35 INTER*/
- {
- { 71, -10},{ 108, 1348},{ 203, 2710},{ 325, 3938},
- { 485, 5040},{ 766, 6000},{ 1267, 6706},{ 2048, 7089},
- { 3037, 7191},{ 4032, 7146},{ 4903, 7061},{ 5648, 6977},
- { 6301, 6912},{ 6884, 6857},{ 7413, 6812},{ 7898, 6775},
- { 8342, 6739},{ 8764, 6710},{ 9160, 6688},{ 9519, 6668},
- { 9859, 6646},{10190, 6625},{10492, 6612},{10755, 6595}
- }
- },
- {
- /*Cb qi=35 INTRA*/
- {
- { 6, 3},{ 95, 369},{ 164, 746},{ 214, 1156},
- { 287, 1542},{ 390, 1869},{ 504, 2143},{ 611, 2388},
- { 712, 2613},{ 822, 2811},{ 937, 2987},{ 1055, 3147},
- { 1174, 3285},{ 1286, 3420},{ 1386, 3560},{ 1488, 3698},
- { 1604, 3814},{ 1714, 3916},{ 1825, 4008},{ 1958, 4088},
- { 2101, 4159},{ 2224, 4226},{ 2339, 4292},{ 2538, 4383}
- },
- /*Cb qi=35 INTER*/
- {
- { 98, 41},{ 90, 348},{ 86, 665},{ 92, 1042},
- { 108, 1432},{ 122, 1812},{ 136, 2175},{ 151, 2528},
- { 165, 2872},{ 182, 3202},{ 202, 3516},{ 225, 3819},
- { 251, 4112},{ 281, 4398},{ 320, 4675},{ 367, 4944},
- { 421, 5204},{ 493, 5450},{ 579, 5679},{ 672, 5892},
- { 785, 6082},{ 906, 6258},{ 1026, 6432},{ 1153, 6592}
- }
- },
- {
- /*Cr qi=35 INTRA*/
- {
- { 12, 7},{ 98, 388},{ 166, 773},{ 226, 1187},
- { 306, 1563},{ 411, 1874},{ 524, 2134},{ 622, 2365},
- { 721, 2577},{ 826, 2768},{ 947, 2946},{ 1066, 3106},
- { 1163, 3250},{ 1274, 3395},{ 1417, 3508},{ 1539, 3590},
- { 1639, 3671},{ 1754, 3765},{ 1865, 3855},{ 1979, 3921},
- { 2127, 3998},{ 2249, 4085},{ 2346, 4172},{ 2473, 4210}
- },
- /*Cr qi=35 INTER*/
- {
- { 86, 12},{ 94, 354},{ 85, 677},{ 96, 1052},
- { 113, 1439},{ 125, 1811},{ 135, 2177},{ 147, 2537},
- { 160, 2884},{ 177, 3215},{ 195, 3535},{ 219, 3842},
- { 252, 4133},{ 292, 4413},{ 339, 4680},{ 396, 4928},
- { 455, 5169},{ 514, 5408},{ 588, 5626},{ 672, 5835},
- { 750, 6051},{ 837, 6257},{ 943, 6442},{ 1073, 6595}
+ { 12, 688},{ 11, 660},{ 28, 869},{ 46, 1227},
+ { 60, 1598},{ 68, 1954},{ 79, 2318},{ 93, 2693},
+ { 108, 3054},{ 123, 3406},{ 138, 3748},{ 151, 4078},
+ { 165, 4400},{ 180, 4716},{ 197, 5024},{ 217, 5314},
+ { 243, 5599},{ 275, 5866},{ 301, 6128},{ 327, 6394},
+ { 352, 6644},{ 375, 6894},{ 376, 7180},{ 458, 7334}
}
}
},
@@ -2290,557 +279,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=36 INTRA*/
{
- { 116, 52},{ 432, 1312},{ 881, 2215},{ 1407, 2759},
- { 1948, 3140},{ 2511, 3484},{ 3090, 3789},{ 3672, 4036},
- { 4243, 4236},{ 4803, 4397},{ 5346, 4517},{ 5856, 4581},
- { 6350, 4614},{ 6821, 4675},{ 7286, 4763},{ 7754, 4832},
- { 8201, 4875},{ 8631, 4922},{ 9015, 4948},{ 9351, 4945},
- { 9706, 4941},{10061, 4948},{10408, 4949},{10878, 4923}
+ { 156, 263},{ 484, 1370},{ 1174, 2110},{ 1914, 2456},
+ { 2601, 2695},{ 3221, 2984},{ 3865, 3284},{ 4450, 3530},
+ { 4979, 3739},{ 5470, 3928},{ 5905, 4080},{ 6375, 4200},
+ { 6761, 4373},{ 7175, 4429},{ 7615, 4616},{ 8069, 4687},
+ { 8417, 4820},{ 8813, 4908},{ 9211, 5001},{ 9508, 5073},
+ { 9888, 5133},{10209, 5140},{10529, 5196},{10830, 5173}
},
/*Y' qi=36 INTER*/
{
- { 63, -16},{ 114, 1332},{ 216, 2690},{ 343, 3914},
- { 515, 5009},{ 829, 5939},{ 1399, 6586},{ 2263, 6901},
- { 3290, 6967},{ 4272, 6920},{ 5115, 6847},{ 5839, 6779},
- { 6478, 6726},{ 7051, 6685},{ 7571, 6649},{ 8050, 6614},
- { 8495, 6587},{ 8908, 6567},{ 9298, 6550},{ 9673, 6530},
- {10005, 6512},{10324, 6499},{10640, 6483},{10936, 6487}
+ { 68, 151},{ 107, 1413},{ 262, 2665},{ 542, 3715},
+ { 946, 4584},{ 1508, 5279},{ 2167, 5829},{ 2968, 6179},
+ { 3758, 6392},{ 4481, 6517},{ 5139, 6577},{ 5706, 6636},
+ { 6271, 6612},{ 6746, 6585},{ 7216, 6533},{ 7622, 6496},
+ { 8045, 6403},{ 8393, 6389},{ 8799, 6272},{ 9062, 6281},
+ { 9436, 6184},{ 9637, 6238},{ 9864, 6215},{10147, 6215}
}
},
{
/*Cb qi=36 INTRA*/
{
- { 6, 3},{ 98, 370},{ 170, 746},{ 225, 1150},
- { 306, 1527},{ 416, 1845},{ 534, 2116},{ 642, 2363},
- { 743, 2591},{ 851, 2794},{ 964, 2972},{ 1081, 3133},
- { 1198, 3275},{ 1311, 3410},{ 1411, 3547},{ 1519, 3680},
- { 1642, 3789},{ 1750, 3892},{ 1860, 3982},{ 1998, 4054},
- { 2141, 4129},{ 2256, 4204},{ 2372, 4278},{ 2567, 4356}
+ { 91, 385},{ 138, 613},{ 205, 932},{ 265, 1239},
+ { 353, 1549},{ 443, 1839},{ 518, 2104},{ 655, 2341},
+ { 764, 2559},{ 876, 2756},{ 967, 2950},{ 1088, 3107},
+ { 1184, 3266},{ 1295, 3396},{ 1375, 3548},{ 1502, 3664},
+ { 1610, 3764},{ 1731, 3844},{ 1839, 3938},{ 1954, 4016},
+ { 2069, 4100},{ 2207, 4167},{ 2274, 4253},{ 2374, 4289}
},
/*Cb qi=36 INTER*/
{
- { 107, 30},{ 96, 346},{ 88, 667},{ 100, 1039},
- { 115, 1426},{ 128, 1804},{ 142, 2164},{ 158, 2512},
- { 176, 2851},{ 195, 3178},{ 218, 3491},{ 243, 3791},
- { 270, 4084},{ 307, 4365},{ 348, 4638},{ 397, 4908},
- { 464, 5157},{ 545, 5392},{ 635, 5620},{ 734, 5831},
- { 854, 6015},{ 993, 6170},{ 1124, 6327},{ 1234, 6502}
+ { 59, 18},{ 56, 463},{ 50, 790},{ 76, 1155},
+ { 90, 1515},{ 108, 1877},{ 125, 2226},{ 150, 2562},
+ { 177, 2890},{ 203, 3203},{ 231, 3501},{ 259, 3789},
+ { 289, 4074},{ 325, 4348},{ 367, 4608},{ 418, 4857},
+ { 486, 5093},{ 574, 5307},{ 677, 5494},{ 784, 5688},
+ { 914, 5844},{ 1033, 6004},{ 1142, 6179},{ 1307, 6220}
}
},
{
/*Cr qi=36 INTRA*/
{
- { 12, 7},{ 102, 388},{ 172, 773},{ 239, 1182},
- { 328, 1546},{ 439, 1848},{ 554, 2106},{ 651, 2341},
- { 747, 2561},{ 850, 2757},{ 972, 2934},{ 1086, 3097},
- { 1182, 3245},{ 1302, 3382},{ 1447, 3491},{ 1572, 3567},
- { 1677, 3641},{ 1793, 3733},{ 1899, 3828},{ 2013, 3894},
- { 2163, 3967},{ 2283, 4059},{ 2387, 4142},{ 2559, 4145}
+ { 87, 376},{ 132, 616},{ 190, 931},{ 268, 1260},
+ { 358, 1550},{ 457, 1833},{ 592, 2082},{ 685, 2318},
+ { 781, 2548},{ 867, 2757},{ 968, 2953},{ 1080, 3124},
+ { 1173, 3255},{ 1282, 3390},{ 1410, 3477},{ 1528, 3593},
+ { 1645, 3612},{ 1766, 3739},{ 1885, 3789},{ 1954, 3892},
+ { 2115, 3987},{ 2202, 4052},{ 2280, 4172},{ 2379, 4213}
},
/*Cr qi=36 INTER*/
{
- { 98, -10},{ 96, 347},{ 89, 676},{ 102, 1048},
- { 118, 1433},{ 130, 1804},{ 141, 2167},{ 154, 2523},
- { 171, 2866},{ 190, 3194},{ 212, 3508},{ 240, 3809},
- { 276, 4099},{ 320, 4377},{ 372, 4638},{ 428, 4887},
- { 492, 5122},{ 560, 5353},{ 638, 5572},{ 725, 5779},
- { 814, 5985},{ 902, 6192},{ 1013, 6377},{ 1155, 6527}
- }
- }
- },
- {
- {
- /*Y' qi=37 INTRA*/
- {
- { 109, 58},{ 445, 1302},{ 927, 2177},{ 1489, 2689},
- { 2053, 3052},{ 2632, 3387},{ 3230, 3683},{ 3830, 3922},
- { 4417, 4114},{ 4992, 4266},{ 5546, 4375},{ 6067, 4430},
- { 6571, 4459},{ 7046, 4516},{ 7513, 4599},{ 7991, 4663},
- { 8445, 4706},{ 8883, 4749},{ 9273, 4771},{ 9612, 4770},
- { 9970, 4765},{10325, 4773},{10672, 4778},{11106, 4758}
- },
- /*Y' qi=37 INTER*/
- {
- { 56, -14},{ 114, 1333},{ 218, 2683},{ 354, 3894},
- { 550, 4966},{ 916, 5854},{ 1569, 6437},{ 2520, 6685},
- { 3596, 6704},{ 4585, 6635},{ 5424, 6556},{ 6147, 6489},
- { 6787, 6437},{ 7358, 6395},{ 7876, 6358},{ 8361, 6325},
- { 8807, 6294},{ 9229, 6271},{ 9631, 6253},{10002, 6238},
- {10356, 6228},{10678, 6212},{10975, 6197},{11274, 6185}
- }
- },
- {
- /*Cb qi=37 INTRA*/
- {
- { 6, 3},{ 99, 370},{ 171, 746},{ 227, 1149},
- { 309, 1522},{ 421, 1836},{ 541, 2104},{ 652, 2347},
- { 757, 2572},{ 871, 2768},{ 989, 2936},{ 1111, 3087},
- { 1238, 3223},{ 1357, 3352},{ 1465, 3486},{ 1576, 3612},
- { 1709, 3705},{ 1828, 3801},{ 1937, 3895},{ 2076, 3967},
- { 2220, 4035},{ 2345, 4104},{ 2466, 4173},{ 2680, 4265}
- },
- /*Cb qi=37 INTER*/
- {
- { 111, 27},{ 97, 344},{ 87, 667},{ 99, 1038},
- { 115, 1425},{ 128, 1802},{ 143, 2160},{ 159, 2506},
- { 176, 2843},{ 198, 3167},{ 220, 3477},{ 247, 3774},
- { 280, 4061},{ 321, 4338},{ 368, 4608},{ 427, 4867},
- { 501, 5109},{ 595, 5332},{ 701, 5544},{ 818, 5738},
- { 956, 5905},{ 1105, 6066},{ 1248, 6217},{ 1381, 6353}
- }
- },
- {
- /*Cr qi=37 INTRA*/
- {
- { 12, 7},{ 102, 388},{ 173, 773},{ 242, 1180},
- { 331, 1541},{ 444, 1839},{ 562, 2095},{ 662, 2326},
- { 763, 2540},{ 871, 2728},{ 1003, 2892},{ 1130, 3045},
- { 1230, 3188},{ 1350, 3321},{ 1503, 3418},{ 1634, 3492},
- { 1737, 3568},{ 1856, 3653},{ 1970, 3744},{ 2091, 3802},
- { 2247, 3871},{ 2371, 3962},{ 2477, 4041},{ 2655, 4052}
- },
- /*Cr qi=37 INTER*/
- {
- { 89, -9},{ 97, 347},{ 88, 677},{ 102, 1048},
- { 118, 1432},{ 130, 1802},{ 141, 2163},{ 154, 2517},
- { 172, 2857},{ 192, 3181},{ 216, 3494},{ 246, 3793},
- { 286, 4074},{ 337, 4343},{ 395, 4600},{ 464, 4837},
- { 534, 5066},{ 608, 5289},{ 694, 5501},{ 788, 5704},
- { 893, 5901},{ 1010, 6088},{ 1151, 6249},{ 1331, 6374}
- }
- }
- },
- {
- {
- /*Y' qi=38 INTRA*/
- {
- { 107, 65},{ 476, 1286},{ 968, 2148},{ 1548, 2641},
- { 2141, 2979},{ 2757, 3289},{ 3390, 3564},{ 4020, 3784},
- { 4632, 3957},{ 5224, 4097},{ 5794, 4201},{ 6326, 4250},
- { 6828, 4274},{ 7309, 4322},{ 7790, 4401},{ 8271, 4463},
- { 8729, 4498},{ 9165, 4540},{ 9552, 4566},{ 9901, 4560},
- {10266, 4552},{10617, 4563},{10964, 4572},{11393, 4567}
- },
- /*Y' qi=38 INTER*/
- {
- { 57, -13},{ 118, 1332},{ 233, 2665},{ 386, 3856},
- { 620, 4899},{ 1070, 5722},{ 1849, 6211},{ 2898, 6384},
- { 3989, 6376},{ 4947, 6311},{ 5754, 6249},{ 6454, 6199},
- { 7077, 6161},{ 7640, 6132},{ 8159, 6101},{ 8639, 6076},
- { 9081, 6054},{ 9502, 6037},{ 9900, 6027},{10274, 6012},
- {10621, 5999},{10938, 5991},{11237, 5977},{11557, 5966}
- }
- },
- {
- /*Cb qi=38 INTRA*/
- {
- { 8, 3},{ 104, 370},{ 179, 744},{ 243, 1139},
- { 338, 1498},{ 458, 1801},{ 584, 2060},{ 700, 2297},
- { 812, 2514},{ 935, 2699},{ 1061, 2858},{ 1189, 3007},
- { 1321, 3141},{ 1446, 3266},{ 1563, 3388},{ 1684, 3512},
- { 1816, 3614},{ 1942, 3702},{ 2055, 3793},{ 2201, 3857},
- { 2357, 3923},{ 2477, 3994},{ 2593, 4061},{ 2768, 4178}
- },
- /*Cb qi=38 INTER*/
- {
- { 118, 24},{ 102, 342},{ 91, 663},{ 101, 1040},
- { 116, 1427},{ 131, 1799},{ 147, 2152},{ 168, 2491},
- { 191, 2822},{ 215, 3139},{ 244, 3441},{ 276, 3731},
- { 316, 4013},{ 363, 4286},{ 423, 4546},{ 495, 4795},
- { 584, 5028},{ 691, 5242},{ 814, 5439},{ 959, 5608},
- { 1119, 5759},{ 1277, 5906},{ 1449, 6035},{ 1655, 6144}
- }
- },
- {
- /*Cr qi=38 INTRA*/
- {
- { 12, 6},{ 106, 387},{ 182, 771},{ 261, 1168},
- { 364, 1514},{ 483, 1802},{ 603, 2053},{ 707, 2282},
- { 817, 2489},{ 933, 2670},{ 1074, 2825},{ 1210, 2967},
- { 1320, 3104},{ 1444, 3229},{ 1599, 3324},{ 1735, 3396},
- { 1846, 3464},{ 1971, 3547},{ 2086, 3646},{ 2206, 3711},
- { 2366, 3773},{ 2499, 3859},{ 2603, 3945},{ 2766, 3952}
- },
- /*Cr qi=38 INTER*/
- {
- { 86, -9},{ 91, 352},{ 85, 680},{ 102, 1053},
- { 119, 1435},{ 132, 1799},{ 146, 2153},{ 162, 2501},
- { 183, 2835},{ 209, 3154},{ 240, 3458},{ 278, 3751},
- { 327, 4025},{ 388, 4284},{ 455, 4532},{ 529, 4766},
- { 616, 4980},{ 711, 5188},{ 815, 5386},{ 920, 5583},
- { 1042, 5770},{ 1186, 5936},{ 1348, 6080},{ 1542, 6196}
- }
- }
- },
- {
- {
- /*Y' qi=39 INTRA*/
- {
- { 103, 66},{ 479, 1283},{ 998, 2125},{ 1610, 2591},
- { 2223, 2913},{ 2855, 3214},{ 3501, 3482},{ 4146, 3698},
- { 4772, 3868},{ 5376, 3999},{ 5956, 4095},{ 6496, 4140},
- { 7008, 4162},{ 7499, 4209},{ 7987, 4282},{ 8478, 4338},
- { 8947, 4374},{ 9385, 4417},{ 9783, 4437},{10143, 4433},
- {10504, 4424},{10866, 4435},{11225, 4444},{11665, 4430}
- },
- /*Y' qi=39 INTER*/
- {
- { 56, 2},{ 118, 1332},{ 235, 2660},{ 395, 3843},
- { 653, 4867},{ 1153, 5652},{ 2003, 6089},{ 3113, 6214},
- { 4228, 6178},{ 5189, 6102},{ 6002, 6031},{ 6707, 5976},
- { 7336, 5936},{ 7901, 5900},{ 8424, 5870},{ 8915, 5844},
- { 9361, 5822},{ 9784, 5807},{10187, 5794},{10571, 5778},
- {10931, 5763},{11264, 5751},{11582, 5742},{11916, 5730}
- }
- },
- {
- /*Cb qi=39 INTRA*/
- {
- { 8, 3},{ 104, 370},{ 179, 744},{ 244, 1138},
- { 340, 1496},{ 461, 1796},{ 588, 2053},{ 705, 2288},
- { 820, 2503},{ 945, 2684},{ 1073, 2840},{ 1210, 2981},
- { 1352, 3106},{ 1480, 3225},{ 1603, 3342},{ 1728, 3464},
- { 1865, 3559},{ 1990, 3645},{ 2106, 3734},{ 2258, 3796},
- { 2413, 3856},{ 2540, 3920},{ 2667, 3986},{ 2887, 4060}
- },
- /*Cb qi=39 INTER*/
- {
- { 119, 19},{ 103, 340},{ 90, 664},{ 100, 1040},
- { 115, 1426},{ 131, 1797},{ 148, 2148},{ 169, 2486},
- { 192, 2816},{ 217, 3131},{ 247, 3432},{ 282, 3721},
- { 324, 3999},{ 374, 4268},{ 435, 4526},{ 520, 4766},
- { 621, 4990},{ 738, 5194},{ 878, 5376},{ 1035, 5543},
- { 1202, 5686},{ 1374, 5819},{ 1545, 5950},{ 1729, 6064}
- }
- },
- {
- /*Cr qi=39 INTRA*/
- {
- { 12, 6},{ 106, 387},{ 182, 771},{ 262, 1167},
- { 365, 1512},{ 486, 1798},{ 608, 2047},{ 713, 2274},
- { 824, 2479},{ 945, 2655},{ 1091, 2804},{ 1231, 2941},
- { 1346, 3073},{ 1475, 3194},{ 1633, 3282},{ 1778, 3345},
- { 1891, 3414},{ 2013, 3501},{ 2138, 3584},{ 2266, 3640},
- { 2428, 3701},{ 2568, 3782},{ 2674, 3863},{ 2816, 3894}
- },
- /*Cr qi=39 INTER*/
- {
- { 88, -7},{ 92, 352},{ 85, 680},{ 102, 1053},
- { 119, 1434},{ 132, 1797},{ 146, 2151},{ 163, 2498},
- { 185, 2830},{ 211, 3147},{ 243, 3451},{ 285, 3735},
- { 337, 4005},{ 401, 4260},{ 477, 4499},{ 565, 4721},
- { 655, 4937},{ 749, 5148},{ 858, 5344},{ 979, 5529},
- { 1110, 5710},{ 1264, 5871},{ 1460, 5990},{ 1677, 6086}
- }
- }
- },
- {
- {
- /*Y' qi=40 INTRA*/
- {
- { 98, 71},{ 491, 1274},{ 1023, 2103},{ 1641, 2559},
- { 2257, 2877},{ 2898, 3171},{ 3566, 3429},{ 4233, 3629},
- { 4881, 3784},{ 5499, 3906},{ 6088, 3997},{ 6631, 4040},
- { 7145, 4060},{ 7640, 4107},{ 8128, 4178},{ 8618, 4233},
- { 9077, 4267},{ 9514, 4304},{ 9919, 4324},{10277, 4317},
- {10635, 4312},{10985, 4324},{11338, 4331},{11792, 4334}
- },
- /*Y' qi=40 INTER*/
- {
- { 63, -26},{ 125, 1331},{ 256, 2640},{ 439, 3801},
- { 757, 4782},{ 1391, 5474},{ 2399, 5805},{ 3582, 5870},
- { 4678, 5824},{ 5600, 5763},{ 6386, 5710},{ 7076, 5667},
- { 7693, 5637},{ 8252, 5610},{ 8775, 5586},{ 9255, 5571},
- { 9694, 5556},{10115, 5541},{10530, 5530},{10903, 5522},
- {11242, 5515},{11596, 5501},{11904, 5482},{12205, 5475}
- }
- },
- {
- /*Cb qi=40 INTRA*/
- {
- { 8, 3},{ 108, 371},{ 189, 743},{ 265, 1128},
- { 371, 1475},{ 499, 1767},{ 628, 2022},{ 746, 2256},
- { 864, 2467},{ 991, 2647},{ 1124, 2801},{ 1270, 2933},
- { 1412, 3054},{ 1547, 3165},{ 1677, 3277},{ 1804, 3393},
- { 1946, 3483},{ 2078, 3569},{ 2201, 3651},{ 2352, 3711},
- { 2513, 3766},{ 2643, 3826},{ 2775, 3880},{ 3025, 3919}
- },
- /*Cb qi=40 INTER*/
- {
- { 114, 35},{ 104, 349},{ 96, 667},{ 106, 1040},
- { 121, 1423},{ 138, 1789},{ 158, 2132},{ 184, 2464},
- { 212, 2787},{ 242, 3095},{ 279, 3389},{ 321, 3671},
- { 374, 3941},{ 438, 4199},{ 517, 4446},{ 617, 4673},
- { 740, 4881},{ 891, 5064},{ 1058, 5225},{ 1239, 5372},
- { 1441, 5499},{ 1638, 5610},{ 1840, 5719},{ 2076, 5814}
- }
- },
- {
- /*Cr qi=40 INTRA*/
- {
- { 14, 7},{ 114, 389},{ 193, 771},{ 283, 1156},
- { 399, 1488},{ 523, 1768},{ 643, 2018},{ 752, 2245},
- { 865, 2450},{ 984, 2626},{ 1139, 2763},{ 1290, 2887},
- { 1413, 3014},{ 1550, 3128},{ 1711, 3211},{ 1865, 3268},
- { 1981, 3334},{ 2103, 3415},{ 2237, 3486},{ 2365, 3543},
- { 2529, 3610},{ 2666, 3700},{ 2775, 3779},{ 2929, 3803}
- },
- /*Cr qi=40 INTER*/
- {
- { 89, -8},{ 95, 353},{ 90, 681},{ 107, 1053},
- { 124, 1430},{ 139, 1787},{ 156, 2136},{ 177, 2477},
- { 203, 2803},{ 237, 3112},{ 276, 3406},{ 329, 3683},
- { 395, 3942},{ 475, 4182},{ 567, 4407},{ 665, 4624},
- { 767, 4834},{ 879, 5032},{ 1011, 5213},{ 1169, 5375},
- { 1348, 5525},{ 1547, 5654},{ 1785, 5743},{ 2066, 5787}
- }
- }
- },
- {
- {
- /*Y' qi=41 INTRA*/
- {
- { 98, 71},{ 495, 1272},{ 1040, 2090},{ 1675, 2533},
- { 2302, 2842},{ 2953, 3132},{ 3631, 3381},{ 4309, 3574},
- { 4966, 3726},{ 5593, 3846},{ 6189, 3934},{ 6738, 3972},
- { 7256, 3991},{ 7754, 4036},{ 8250, 4099},{ 8747, 4150},
- { 9207, 4185},{ 9650, 4222},{10057, 4242},{10411, 4237},
- {10771, 4230},{11127, 4244},{11486, 4254},{11933, 4252}
- },
- /*Y' qi=41 INTER*/
- {
- { 65, -25},{ 125, 1331},{ 260, 2633},{ 457, 3782},
- { 807, 4740},{ 1499, 5397},{ 2562, 5693},{ 3766, 5743},
- { 4859, 5695},{ 5776, 5638},{ 6556, 5590},{ 7243, 5554},
- { 7859, 5529},{ 8417, 5506},{ 8935, 5486},{ 9419, 5473},
- { 9869, 5460},{10296, 5446},{10711, 5436},{11089, 5430},
- {11445, 5421},{11802, 5412},{12129, 5404},{12465, 5393}
- }
- },
- {
- /*Cb qi=41 INTRA*/
- {
- { 8, 3},{ 108, 371},{ 189, 743},{ 267, 1126},
- { 374, 1471},{ 504, 1760},{ 635, 2011},{ 758, 2241},
- { 881, 2447},{ 1013, 2621},{ 1147, 2773},{ 1293, 2906},
- { 1441, 3023},{ 1580, 3131},{ 1712, 3243},{ 1844, 3360},
- { 1985, 3451},{ 2114, 3532},{ 2240, 3613},{ 2390, 3680},
- { 2550, 3740},{ 2687, 3800},{ 2825, 3862},{ 3052, 3944}
- },
- /*Cb qi=41 INTER*/
- {
- { 104, 39},{ 100, 350},{ 95, 667},{ 105, 1040},
- { 121, 1422},{ 137, 1787},{ 159, 2129},{ 185, 2459},
- { 216, 2778},{ 249, 3083},{ 287, 3374},{ 335, 3653},
- { 393, 3920},{ 462, 4175},{ 549, 4414},{ 660, 4636},
- { 791, 4839},{ 952, 5014},{ 1135, 5166},{ 1337, 5297},
- { 1552, 5411},{ 1752, 5530},{ 1972, 5634},{ 2224, 5724}
- }
- },
- {
- /*Cr qi=41 INTRA*/
- {
- { 15, 7},{ 115, 389},{ 193, 770},{ 284, 1154},
- { 401, 1484},{ 528, 1761},{ 652, 2005},{ 764, 2228},
- { 882, 2427},{ 1008, 2599},{ 1167, 2734},{ 1320, 2859},
- { 1443, 2990},{ 1580, 3103},{ 1743, 3181},{ 1894, 3241},
- { 2012, 3309},{ 2141, 3385},{ 2272, 3459},{ 2398, 3519},
- { 2566, 3584},{ 2707, 3680},{ 2816, 3762},{ 2991, 3770}
- },
- /*Cr qi=41 INTER*/
- {
- { 92, -9},{ 98, 354},{ 90, 682},{ 107, 1052},
- { 124, 1429},{ 139, 1786},{ 156, 2132},{ 178, 2471},
- { 207, 2794},{ 241, 3100},{ 285, 3391},{ 345, 3662},
- { 417, 3915},{ 503, 4151},{ 600, 4375},{ 703, 4589},
- { 815, 4791},{ 942, 4981},{ 1088, 5155},{ 1250, 5316},
- { 1432, 5462},{ 1653, 5575},{ 1930, 5639},{ 2250, 5655}
- }
- }
- },
- {
- {
- /*Y' qi=42 INTRA*/
- {
- { 109, 75},{ 534, 1257},{ 1114, 2047},{ 1793, 2456},
- { 2461, 2735},{ 3157, 2994},{ 3879, 3221},{ 4595, 3396},
- { 5282, 3531},{ 5931, 3638},{ 6546, 3714},{ 7105, 3749},
- { 7633, 3766},{ 8147, 3803},{ 8652, 3865},{ 9148, 3915},
- { 9613, 3946},{10075, 3976},{10489, 3997},{10835, 3994},
- {11195, 3985},{11553, 3997},{11909, 4004},{12369, 3990}
- },
- /*Y' qi=42 INTER*/
- {
- { 69, -23},{ 134, 1332},{ 287, 2611},{ 521, 3730},
- { 970, 4624},{ 1827, 5176},{ 3028, 5382},{ 4262, 5389},
- { 5325, 5338},{ 6214, 5291},{ 6976, 5255},{ 7651, 5228},
- { 8260, 5206},{ 8821, 5190},{ 9343, 5177},{ 9823, 5165},
- {10273, 5152},{10709, 5143},{11121, 5136},{11502, 5129},
- {11857, 5125},{12193, 5115},{12520, 5107},{12802, 5097}
- }
- },
- {
- /*Cb qi=42 INTRA*/
- {
- { 9, 3},{ 113, 371},{ 199, 743},{ 279, 1123},
- { 390, 1462},{ 525, 1743},{ 662, 1986},{ 789, 2208},
- { 916, 2406},{ 1057, 2571},{ 1204, 2712},{ 1362, 2835},
- { 1524, 2943},{ 1676, 3040},{ 1815, 3145},{ 1959, 3249},
- { 2117, 3325},{ 2249, 3406},{ 2377, 3488},{ 2537, 3547},
- { 2706, 3597},{ 2854, 3646},{ 2999, 3705},{ 3236, 3759}
- },
- /*Cb qi=42 INTER*/
- {
- { 114, 44},{ 107, 353},{ 101, 670},{ 111, 1041},
- { 129, 1418},{ 148, 1775},{ 174, 2110},{ 208, 2432},
- { 244, 2746},{ 283, 3046},{ 330, 3330},{ 388, 3602},
- { 460, 3858},{ 546, 4101},{ 655, 4326},{ 793, 4530},
- { 966, 4703},{ 1165, 4851},{ 1388, 4980},{ 1630, 5088},
- { 1869, 5189},{ 2122, 5268},{ 2403, 5328},{ 2667, 5417}
- }
- },
- {
- /*Cr qi=42 INTRA*/
- {
- { 15, 7},{ 120, 390},{ 202, 771},{ 298, 1150},
- { 421, 1473},{ 553, 1743},{ 681, 1982},{ 796, 2199},
- { 923, 2388},{ 1062, 2547},{ 1225, 2678},{ 1392, 2792},
- { 1531, 2907},{ 1682, 3007},{ 1856, 3074},{ 2009, 3134},
- { 2138, 3192},{ 2274, 3257},{ 2407, 3333},{ 2536, 3393},
- { 2711, 3455},{ 2875, 3531},{ 3000, 3598},{ 3186, 3599}
- },
- /*Cr qi=42 INTER*/
- {
- { 87, -4},{ 95, 358},{ 97, 683},{ 113, 1052},
- { 131, 1423},{ 148, 1774},{ 170, 2116},{ 198, 2448},
- { 234, 2762},{ 276, 3062},{ 331, 3343},{ 404, 3603},
- { 494, 3844},{ 598, 4067},{ 715, 4276},{ 842, 4471},
- { 977, 4661},{ 1128, 4840},{ 1311, 4991},{ 1516, 5127},
- { 1759, 5233},{ 2050, 5300},{ 2377, 5323},{ 2710, 5304}
- }
- }
- },
- {
- {
- /*Y' qi=43 INTRA*/
- {
- { 99, 79},{ 557, 1244},{ 1175, 2016},{ 1882, 2408},
- { 2570, 2677},{ 3288, 2926},{ 4030, 3141},{ 4760, 3307},
- { 5458, 3435},{ 6115, 3537},{ 6743, 3608},{ 7312, 3636},
- { 7841, 3652},{ 8357, 3687},{ 8870, 3742},{ 9376, 3788},
- { 9850, 3821},{10315, 3853},{10734, 3873},{11084, 3870},
- {11442, 3862},{11800, 3874},{12160, 3879},{12618, 3876}
- },
- /*Y' qi=43 INTER*/
- {
- { 69, -22},{ 134, 1331},{ 294, 2601},{ 551, 3703},
- { 1056, 4563},{ 2003, 5061},{ 3276, 5215},{ 4534, 5194},
- { 5599, 5133},{ 6488, 5083},{ 7257, 5044},{ 7938, 5014},
- { 8556, 4992},{ 9124, 4975},{ 9648, 4960},{10138, 4948},
- {10594, 4939},{11039, 4926},{11462, 4919},{11847, 4912},
- {12216, 4904},{12570, 4896},{12883, 4889},{13189, 4879}
- }
- },
- {
- /*Cb qi=43 INTRA*/
- {
- { 9, 3},{ 114, 371},{ 202, 740},{ 294, 1110},
- { 417, 1440},{ 558, 1716},{ 700, 1956},{ 833, 2172},
- { 966, 2365},{ 1116, 2524},{ 1269, 2661},{ 1431, 2781},
- { 1599, 2885},{ 1756, 2980},{ 1902, 3082},{ 2051, 3185},
- { 2209, 3261},{ 2337, 3342},{ 2464, 3420},{ 2633, 3475},
- { 2809, 3525},{ 2948, 3579},{ 3094, 3633},{ 3347, 3678}
- },
- /*Cb qi=43 INTER*/
- {
- { 111, 44},{ 106, 353},{ 102, 670},{ 112, 1040},
- { 128, 1416},{ 148, 1771},{ 176, 2104},{ 211, 2424},
- { 250, 2734},{ 293, 3030},{ 347, 3309},{ 411, 3575},
- { 490, 3828},{ 589, 4064},{ 716, 4278},{ 869, 4472},
- { 1050, 4640},{ 1264, 4781},{ 1512, 4895},{ 1775, 4991},
- { 2042, 5069},{ 2310, 5141},{ 2593, 5207},{ 2912, 5239}
- }
- },
- {
- /*Cr qi=43 INTRA*/
- {
- { 15, 7},{ 121, 390},{ 208, 767},{ 315, 1135},
- { 449, 1449},{ 586, 1715},{ 718, 1950},{ 843, 2158},
- { 977, 2342},{ 1120, 2501},{ 1290, 2632},{ 1466, 2739},
- { 1613, 2845},{ 1763, 2945},{ 1937, 3015},{ 2093, 3070},
- { 2225, 3126},{ 2366, 3194},{ 2501, 3267},{ 2634, 3324},
- { 2815, 3385},{ 2964, 3466},{ 3087, 3538},{ 3263, 3555}
- },
- /*Cr qi=43 INTER*/
- {
- { 84, -4},{ 93, 358},{ 95, 683},{ 113, 1052},
- { 131, 1421},{ 148, 1770},{ 171, 2110},{ 201, 2439},
- { 240, 2750},{ 287, 3046},{ 348, 3322},{ 429, 3576},
- { 527, 3811},{ 641, 4029},{ 767, 4230},{ 904, 4422},
- { 1053, 4603},{ 1225, 4765},{ 1433, 4903},{ 1661, 5030},
- { 1928, 5121},{ 2252, 5160},{ 2604, 5164},{ 2979, 5125}
- }
- }
- },
- {
- {
- /*Y' qi=44 INTRA*/
- {
- { 103, 80},{ 560, 1244},{ 1183, 2009},{ 1891, 2391},
- { 2586, 2649},{ 3324, 2884},{ 4093, 3089},{ 4850, 3243},
- { 5575, 3358},{ 6252, 3452},{ 6886, 3518},{ 7459, 3546},
- { 7993, 3562},{ 8515, 3594},{ 9030, 3645},{ 9534, 3691},
- {10004, 3723},{10469, 3750},{10887, 3765},{11236, 3766},
- {11596, 3762},{11960, 3775},{12317, 3784},{12766, 3789}
- },
- /*Y' qi=44 INTER*/
- {
- { 77, -24},{ 145, 1332},{ 332, 2580},{ 642, 3649},
- { 1270, 4438},{ 2360, 4860},{ 3685, 4982},{ 4910, 4966},
- { 5929, 4928},{ 6785, 4900},{ 7529, 4880},{ 8198, 4863},
- { 8804, 4850},{ 9361, 4842},{ 9882, 4836},{10371, 4830},
- {10827, 4822},{11262, 4816},{11672, 4811},{12052, 4807},
- {12431, 4806},{12780, 4798},{13095, 4792},{13401, 4791}
- }
- },
- {
- /*Cb qi=44 INTRA*/
- {
- { 9, 2},{ 122, 371},{ 214, 741},{ 307, 1109},
- { 433, 1432},{ 576, 1704},{ 718, 1939},{ 855, 2152},
- { 991, 2340},{ 1141, 2497},{ 1298, 2632},{ 1463, 2749},
- { 1636, 2851},{ 1796, 2944},{ 1947, 3041},{ 2101, 3140},
- { 2260, 3219},{ 2392, 3297},{ 2527, 3366},{ 2693, 3424},
- { 2872, 3477},{ 3025, 3525},{ 3175, 3584},{ 3451, 3626}
- },
- /*Cb qi=44 INTER*/
- {
- { 111, 14},{ 110, 339},{ 109, 671},{ 120, 1040},
- { 139, 1410},{ 162, 1758},{ 197, 2084},{ 243, 2397},
- { 291, 2702},{ 342, 2992},{ 405, 3265},{ 484, 3521},
- { 584, 3760},{ 705, 3983},{ 855, 4185},{ 1048, 4356},
- { 1274, 4500},{ 1531, 4617},{ 1816, 4707},{ 2111, 4783},
- { 2409, 4846},{ 2720, 4901},{ 3044, 4957},{ 3391, 4985}
- }
- },
- {
- /*Cr qi=44 INTRA*/
- {
- { 17, 7},{ 128, 392},{ 219, 770},{ 329, 1135},
- { 465, 1442},{ 601, 1703},{ 734, 1935},{ 862, 2142},
- { 998, 2325},{ 1147, 2482},{ 1321, 2606},{ 1496, 2710},
- { 1649, 2813},{ 1809, 2908},{ 1984, 2977},{ 2143, 3032},
- { 2279, 3087},{ 2423, 3152},{ 2559, 3225},{ 2684, 3288},
- { 2866, 3351},{ 3025, 3426},{ 3161, 3492},{ 3372, 3500}
- },
- /*Cr qi=44 INTER*/
- {
- { 89, 0},{ 101, 352},{ 104, 683},{ 121, 1051},
- { 141, 1414},{ 163, 1757},{ 192, 2092},{ 231, 2415},
- { 278, 2720},{ 336, 3007},{ 412, 3273},{ 510, 3516},
- { 633, 3733},{ 769, 3936},{ 914, 4130},{ 1076, 4307},
- { 1256, 4472},{ 1469, 4617},{ 1723, 4732},{ 2012, 4822},
- { 2347, 4871},{ 2716, 4875},{ 3082, 4866},{ 3422, 4826}
+ { 53, 45},{ 50, 467},{ 45, 789},{ 76, 1150},
+ { 92, 1531},{ 107, 1877},{ 125, 2219},{ 147, 2561},
+ { 176, 2893},{ 206, 3209},{ 231, 3514},{ 260, 3808},
+ { 298, 4085},{ 350, 4344},{ 411, 4587},{ 475, 4814},
+ { 532, 5037},{ 587, 5261},{ 647, 5480},{ 707, 5694},
+ { 793, 5900},{ 891, 6093},{ 1017, 6292},{ 1205, 6307}
}
}
},
@@ -2848,557 +341,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=45 INTRA*/
{
- { 119, 78},{ 610, 1226},{ 1271, 1965},{ 2026, 2319},
- { 2768, 2550},{ 3556, 2757},{ 4369, 2938},{ 5157, 3076},
- { 5901, 3182},{ 6598, 3268},{ 7253, 3326},{ 7844, 3343},
- { 8392, 3356},{ 8922, 3386},{ 9453, 3433},{ 9973, 3474},
- {10457, 3503},{10929, 3530},{11351, 3543},{11709, 3541},
- {12068, 3537},{12434, 3547},{12805, 3555},{13268, 3563}
+ { 47, 170},{ 955, 1217},{ 1713, 2014},{ 3050, 2094},
+ { 3954, 2179},{ 4801, 2357},{ 5629, 2494},{ 6313, 2614},
+ { 6962, 2716},{ 7566, 2820},{ 8138, 2886},{ 8613, 2949},
+ { 9097, 3031},{ 9574, 3044},{10053, 3142},{10514, 3134},
+ {10897, 3241},{11397, 3275},{11775, 3297},{12200, 3350},
+ {12527, 3350},{12959, 3393},{13246, 3401},{13573, 3397}
},
/*Y' qi=45 INTER*/
{
- { 77, -20},{ 146, 1330},{ 342, 2566},{ 699, 3604},
- { 1439, 4332},{ 2669, 4672},{ 4075, 4727},{ 5318, 4679},
- { 6345, 4630},{ 7209, 4595},{ 7963, 4570},{ 8644, 4551},
- { 9262, 4535},{ 9831, 4525},{10370, 4515},{10872, 4506},
- {11334, 4500},{11783, 4492},{12219, 4489},{12617, 4483},
- {12995, 4477},{13350, 4472},{13674, 4466},{13968, 4468}
+ { 53, 73},{ 175, 1343},{ 649, 2439},{ 1339, 3250},
+ { 2297, 3837},{ 3395, 4203},{ 4438, 4400},{ 5401, 4529},
+ { 6222, 4588},{ 7018, 4564},{ 7713, 4532},{ 8378, 4464},
+ { 8959, 4414},{ 9464, 4364},{ 9980, 4315},{10401, 4291},
+ {10805, 4260},{11172, 4260},{11501, 4231},{11798, 4248},
+ {12082, 4254},{12381, 4262},{12572, 4285},{12877, 4289}
}
},
{
/*Cb qi=45 INTRA*/
{
- { 9, 2},{ 122, 370},{ 219, 735},{ 324, 1096},
- { 465, 1414},{ 619, 1679},{ 771, 1905},{ 920, 2103},
- { 1070, 2276},{ 1236, 2419},{ 1410, 2539},{ 1595, 2644},
- { 1784, 2736},{ 1949, 2831},{ 2104, 2931},{ 2275, 3021},
- { 2443, 3092},{ 2586, 3166},{ 2735, 3234},{ 2904, 3288},
- { 3093, 3338},{ 3262, 3382},{ 3419, 3427},{ 3708, 3456}
+ { 112, -14},{ 173, 495},{ 260, 827},{ 355, 1122},
+ { 451, 1420},{ 579, 1695},{ 697, 1934},{ 917, 2101},
+ { 1104, 2244},{ 1266, 2381},{ 1417, 2520},{ 1609, 2611},
+ { 1801, 2689},{ 1973, 2764},{ 2108, 2864},{ 2298, 2948},
+ { 2452, 3008},{ 2588, 3080},{ 2732, 3161},{ 2888, 3203},
+ { 3052, 3266},{ 3240, 3294},{ 3342, 3351},{ 3467, 3373}
},
/*Cb qi=45 INTER*/
{
- { 103, 0},{ 109, 339},{ 109, 670},{ 119, 1039},
- { 137, 1408},{ 162, 1754},{ 199, 2076},{ 248, 2386},
- { 301, 2684},{ 360, 2967},{ 433, 3234},{ 525, 3481},
- { 640, 3713},{ 780, 3924},{ 956, 4110},{ 1176, 4266},
- { 1438, 4390},{ 1736, 4481},{ 2057, 4553},{ 2385, 4613},
- { 2718, 4656},{ 3056, 4698},{ 3416, 4733},{ 3799, 4755}
+ { 41, -49},{ 52, 385},{ 87, 743},{ 110, 1102},
+ { 135, 1453},{ 162, 1788},{ 207, 2096},{ 272, 2391},
+ { 330, 2677},{ 392, 2950},{ 464, 3205},{ 556, 3442},
+ { 674, 3656},{ 827, 3847},{ 1030, 4006},{ 1275, 4132},
+ { 1544, 4234},{ 1809, 4317},{ 2089, 4408},{ 2377, 4456},
+ { 2647, 4532},{ 2919, 4595},{ 3256, 4659},{ 3465, 4657}
}
},
{
/*Cr qi=45 INTRA*/
{
- { 16, 7},{ 128, 391},{ 225, 763},{ 350, 1120},
- { 500, 1420},{ 649, 1673},{ 792, 1893},{ 929, 2089},
- { 1084, 2257},{ 1250, 2401},{ 1440, 2518},{ 1633, 2614},
- { 1799, 2708},{ 1968, 2798},{ 2151, 2863},{ 2314, 2914},
- { 2453, 2968},{ 2611, 3025},{ 2759, 3095},{ 2887, 3160},
- { 3082, 3210},{ 3259, 3278},{ 3403, 3342},{ 3593, 3354}
+ { 99, -14},{ 164, 493},{ 247, 832},{ 358, 1123},
+ { 468, 1416},{ 599, 1680},{ 795, 1886},{ 958, 2063},
+ { 1133, 2211},{ 1300, 2345},{ 1480, 2461},{ 1664, 2554},
+ { 1807, 2656},{ 1995, 2742},{ 2146, 2799},{ 2331, 2856},
+ { 2440, 2894},{ 2592, 2996},{ 2751, 3033},{ 2865, 3112},
+ { 3073, 3162},{ 3210, 3208},{ 3330, 3306},{ 3454, 3332}
},
/*Cr qi=45 INTER*/
{
- { 92, 0},{ 101, 352},{ 103, 682},{ 120, 1049},
- { 140, 1412},{ 163, 1752},{ 193, 2083},{ 234, 2402},
- { 287, 2702},{ 353, 2983},{ 442, 3240},{ 557, 3471},
- { 694, 3680},{ 846, 3873},{ 1014, 4056},{ 1200, 4224},
- { 1414, 4369},{ 1664, 4495},{ 1946, 4595},{ 2278, 4654},
- { 2654, 4673},{ 3047, 4658},{ 3438, 4627},{ 3825, 4585}
- }
- }
- },
- {
- {
- /*Y' qi=46 INTRA*/
- {
- { 119, 78},{ 610, 1227},{ 1277, 1960},{ 2043, 2309},
- { 2805, 2529},{ 3618, 2719},{ 4452, 2887},{ 5257, 3016},
- { 6017, 3115},{ 6727, 3195},{ 7392, 3248},{ 7984, 3267},
- { 8528, 3281},{ 9059, 3310},{ 9593, 3354},{10119, 3395},
- {10599, 3425},{11064, 3450},{11493, 3464},{11850, 3466},
- {12207, 3462},{12578, 3471},{12948, 3480},{13407, 3487}
- },
- /*Y' qi=46 INTER*/
- {
- { 74, -14},{ 149, 1326},{ 382, 2538},{ 807, 3541},
- { 1670, 4211},{ 3000, 4499},{ 4416, 4533},{ 5628, 4490},
- { 6628, 4453},{ 7479, 4425},{ 8228, 4406},{ 8902, 4393},
- { 9521, 4380},{10090, 4371},{10623, 4364},{11124, 4356},
- {11586, 4351},{12043, 4344},{12476, 4341},{12863, 4340},
- {13244, 4337},{13610, 4329},{13936, 4324},{14246, 4329}
- }
- },
- {
- /*Cb qi=46 INTRA*/
- {
- { 11, 2},{ 132, 371},{ 234, 737},{ 340, 1094},
- { 481, 1405},{ 637, 1667},{ 791, 1891},{ 944, 2084},
- { 1099, 2253},{ 1268, 2392},{ 1444, 2507},{ 1633, 2610},
- { 1825, 2700},{ 1990, 2794},{ 2147, 2895},{ 2321, 2984},
- { 2493, 3053},{ 2640, 3126},{ 2787, 3198},{ 2954, 3253},
- { 3146, 3297},{ 3313, 3344},{ 3473, 3393},{ 3757, 3434}
- },
- /*Cb qi=46 INTER*/
- {
- { 97, 0},{ 109, 339},{ 108, 669},{ 120, 1035},
- { 142, 1398},{ 173, 1737},{ 221, 2052},{ 281, 2353},
- { 345, 2646},{ 415, 2924},{ 504, 3183},{ 616, 3421},
- { 749, 3643},{ 914, 3842},{ 1123, 4012},{ 1379, 4150},
- { 1685, 4250},{ 2014, 4327},{ 2366, 4382},{ 2731, 4426},
- { 3083, 4470},{ 3445, 4490},{ 3805, 4511},{ 4146, 4539}
- }
- },
- {
- /*Cr qi=46 INTRA*/
- {
- { 19, 7},{ 137, 393},{ 237, 765},{ 364, 1116},
- { 516, 1411},{ 665, 1662},{ 809, 1880},{ 951, 2072},
- { 1109, 2236},{ 1278, 2378},{ 1474, 2491},{ 1669, 2584},
- { 1835, 2678},{ 2014, 2766},{ 2203, 2828},{ 2366, 2880},
- { 2506, 2933},{ 2661, 2988},{ 2810, 3053},{ 2941, 3116},
- { 3131, 3175},{ 3310, 3243},{ 3461, 3303},{ 3656, 3321}
- },
- /*Cr qi=46 INTER*/
- {
- { 91, 1},{ 103, 351},{ 104, 681},{ 121, 1046},
- { 144, 1401},{ 173, 1736},{ 213, 2060},{ 265, 2373},
- { 330, 2666},{ 410, 2938},{ 517, 3185},{ 655, 3404},
- { 815, 3601},{ 989, 3784},{ 1183, 3951},{ 1400, 4104},
- { 1649, 4241},{ 1933, 4352},{ 2261, 4427},{ 2646, 4458},
- { 3057, 4446},{ 3453, 4418},{ 3820, 4385},{ 4171, 4352}
- }
- }
- },
- {
- {
- /*Y' qi=47 INTRA*/
- {
- { 117, 83},{ 670, 1205},{ 1408, 1904},{ 2239, 2219},
- { 3049, 2414},{ 3905, 2584},{ 4775, 2734},{ 5610, 2852},
- { 6393, 2944},{ 7121, 3017},{ 7804, 3066},{ 8407, 3081},
- { 8957, 3093},{ 9498, 3119},{10043, 3160},{10582, 3199},
- {11083, 3226},{11561, 3250},{11993, 3263},{12352, 3264},
- {12711, 3259},{13092, 3266},{13463, 3271},{13918, 3275}
- },
- /*Y' qi=47 INTER*/
- {
- { 74, -11},{ 148, 1325},{ 404, 2518},{ 910, 3478},
- { 1916, 4080},{ 3369, 4298},{ 4823, 4292},{ 6035, 4238},
- { 7037, 4197},{ 7894, 4168},{ 8650, 4146},{ 9337, 4129},
- { 9968, 4116},{10549, 4105},{11096, 4096},{11605, 4089},
- {12081, 4083},{12547, 4076},{12990, 4070},{13399, 4070},
- {13776, 4065},{14133, 4059},{14486, 4057},{14842, 4053}
- }
- },
- {
- /*Cb qi=47 INTRA*/
- {
- { 11, 2},{ 133, 370},{ 242, 731},{ 367, 1077},
- { 524, 1378},{ 692, 1630},{ 860, 1844},{ 1028, 2024},
- { 1203, 2178},{ 1393, 2305},{ 1582, 2413},{ 1787, 2507},
- { 1992, 2590},{ 2175, 2676},{ 2351, 2767},{ 2534, 2851},
- { 2707, 2923},{ 2862, 2994},{ 3021, 3060},{ 3193, 3111},
- { 3396, 3147},{ 3573, 3184},{ 3752, 3220},{ 4038, 3255}
- },
- /*Cb qi=47 INTER*/
- {
- { 101, 0},{ 107, 339},{ 108, 667},{ 120, 1033},
- { 142, 1394},{ 175, 1729},{ 227, 2040},{ 295, 2335},
- { 369, 2619},{ 452, 2888},{ 556, 3138},{ 686, 3368},
- { 850, 3574},{ 1050, 3758},{ 1299, 3910},{ 1605, 4024},
- { 1950, 4104},{ 2317, 4163},{ 2689, 4210},{ 3077, 4239},
- { 3466, 4258},{ 3840, 4278},{ 4205, 4298},{ 4515, 4340}
- }
- },
- {
- /*Cr qi=47 INTRA*/
- {
- { 19, 7},{ 138, 392},{ 248, 758},{ 396, 1094},
- { 563, 1378},{ 723, 1621},{ 881, 1829},{ 1037, 2011},
- { 1214, 2165},{ 1410, 2290},{ 1623, 2393},{ 1834, 2480},
- { 2016, 2564},{ 2203, 2647},{ 2405, 2707},{ 2569, 2757},
- { 2709, 2810},{ 2871, 2860},{ 3027, 2924},{ 3178, 2980},
- { 3375, 3034},{ 3563, 3097},{ 3724, 3151},{ 3952, 3153}
- },
- /*Cr qi=47 INTER*/
- {
- { 91, 1},{ 100, 351},{ 102, 681},{ 120, 1043},
- { 144, 1397},{ 175, 1729},{ 219, 2049},{ 277, 2356},
- { 353, 2640},{ 451, 2902},{ 579, 3136},{ 739, 3342},
- { 926, 3525},{ 1125, 3698},{ 1343, 3859},{ 1595, 3998},
- { 1881, 4113},{ 2208, 4205},{ 2589, 4253},{ 3014, 4250},
- { 3444, 4220},{ 3838, 4183},{ 4196, 4147},{ 4521, 4116}
- }
- }
- },
- {
- {
- /*Y' qi=48 INTRA*/
- {
- { 107, 87},{ 681, 1200},{ 1456, 1883},{ 2306, 2193},
- { 3122, 2386},{ 3984, 2548},{ 4862, 2693},{ 5704, 2808},
- { 6495, 2899},{ 7232, 2970},{ 7915, 3018},{ 8524, 3034},
- { 9085, 3043},{ 9635, 3068},{10192, 3108},{10735, 3145},
- {11237, 3171},{11719, 3194},{12153, 3207},{12516, 3206},
- {12888, 3202},{13266, 3210},{13637, 3218},{14101, 3219}
- },
- /*Y' qi=48 INTER*/
- {
- { 83, -18},{ 147, 1328},{ 398, 2519},{ 923, 3468},
- { 1979, 4047},{ 3472, 4246},{ 4936, 4232},{ 6148, 4178},
- { 7150, 4139},{ 8007, 4111},{ 8765, 4091},{ 9458, 4076},
- {10090, 4063},{10676, 4054},{11226, 4045},{11742, 4038},
- {12223, 4033},{12686, 4029},{13127, 4022},{13527, 4015},
- {13915, 4012},{14277, 4007},{14619, 4004},{14966, 4001}
- }
- },
- {
- /*Cb qi=48 INTRA*/
- {
- { 11, 2},{ 134, 369},{ 245, 730},{ 373, 1075},
- { 531, 1374},{ 698, 1625},{ 865, 1839},{ 1033, 2019},
- { 1207, 2173},{ 1397, 2300},{ 1588, 2408},{ 1795, 2501},
- { 2003, 2581},{ 2187, 2666},{ 2362, 2757},{ 2548, 2841},
- { 2719, 2912},{ 2876, 2983},{ 3034, 3047},{ 3209, 3097},
- { 3409, 3137},{ 3589, 3178},{ 3762, 3216},{ 4004, 3252}
- },
- /*Cb qi=48 INTER*/
- {
- { 113, 26},{ 112, 344},{ 111, 668},{ 120, 1032},
- { 141, 1392},{ 173, 1727},{ 224, 2036},{ 290, 2330},
- { 363, 2612},{ 447, 2880},{ 551, 3130},{ 685, 3358},
- { 852, 3563},{ 1061, 3742},{ 1332, 3884},{ 1654, 3993},
- { 2011, 4068},{ 2394, 4120},{ 2782, 4160},{ 3172, 4186},
- { 3557, 4209},{ 3932, 4228},{ 4306, 4237},{ 4675, 4236}
- }
- },
- {
- /*Cr qi=48 INTRA*/
- {
- { 18, 7},{ 139, 389},{ 252, 755},{ 404, 1090},
- { 573, 1372},{ 732, 1615},{ 889, 1823},{ 1045, 2005},
- { 1222, 2159},{ 1417, 2285},{ 1631, 2387},{ 1843, 2474},
- { 2027, 2558},{ 2212, 2639},{ 2413, 2697},{ 2578, 2746},
- { 2720, 2798},{ 2887, 2852},{ 3040, 2913},{ 3181, 2970},
- { 3381, 3024},{ 3581, 3081},{ 3743, 3130},{ 3948, 3133}
- },
- /*Cr qi=48 INTER*/
- {
- { 89, 0},{ 106, 352},{ 105, 682},{ 120, 1044},
- { 144, 1395},{ 174, 1724},{ 215, 2044},{ 270, 2350},
- { 343, 2635},{ 441, 2895},{ 571, 3129},{ 735, 3334},
- { 926, 3518},{ 1139, 3684},{ 1371, 3836},{ 1628, 3977},
- { 1933, 4089},{ 2279, 4164},{ 2672, 4204},{ 3105, 4205},
- { 3533, 4176},{ 3931, 4135},{ 4290, 4089},{ 4624, 4057}
- }
- }
- },
- {
- {
- /*Y' qi=49 INTRA*/
- {
- { 120, 85},{ 706, 1194},{ 1485, 1875},{ 2348, 2187},
- { 3190, 2372},{ 4076, 2521},{ 4967, 2658},{ 5819, 2771},
- { 6611, 2861},{ 7345, 2936},{ 8026, 2990},{ 8626, 3013},
- { 9182, 3030},{ 9723, 3059},{10266, 3100},{10802, 3143},
- {11293, 3179},{11768, 3206},{12201, 3221},{12556, 3225},
- {12914, 3226},{13281, 3237},{13639, 3247},{14089, 3257}
- },
- /*Y' qi=49 INTER*/
- {
- { 72, -11},{ 155, 1320},{ 458, 2485},{ 1090, 3386},
- { 2284, 3907},{ 3835, 4075},{ 5272, 4064},{ 6449, 4026},
- { 7426, 4003},{ 8267, 3987},{ 9017, 3976},{ 9698, 3967},
- {10328, 3962},{10913, 3959},{11452, 3954},{11961, 3950},
- {12442, 3947},{12904, 3946},{13347, 3945},{13749, 3943},
- {14123, 3941},{14490, 3941},{14826, 3939},{15153, 3937}
- }
- },
- {
- /*Cb qi=49 INTRA*/
- {
- { 11, 2},{ 145, 369},{ 262, 729},{ 393, 1070},
- { 557, 1363},{ 731, 1607},{ 907, 1811},{ 1085, 1983},
- { 1268, 2130},{ 1465, 2251},{ 1658, 2359},{ 1868, 2454},
- { 2079, 2534},{ 2264, 2621},{ 2440, 2717},{ 2625, 2802},
- { 2792, 2878},{ 2945, 2954},{ 3106, 3021},{ 3277, 3075},
- { 3466, 3119},{ 3638, 3170},{ 3824, 3213},{ 4100, 3243}
- },
- /*Cb qi=49 INTER*/
- {
- { 98, -6},{ 113, 343},{ 110, 669},{ 122, 1029},
- { 149, 1380},{ 192, 1706},{ 258, 2007},{ 340, 2293},
- { 426, 2569},{ 525, 2831},{ 653, 3071},{ 814, 3287},
- { 1013, 3478},{ 1262, 3637},{ 1575, 3761},{ 1936, 3851},
- { 2328, 3910},{ 2741, 3949},{ 3163, 3970},{ 3559, 3994},
- { 3936, 4025},{ 4300, 4050},{ 4655, 4060},{ 4962, 4062}
- }
- },
- {
- /*Cr qi=49 INTRA*/
- {
- { 19, 7},{ 151, 389},{ 270, 753},{ 427, 1084},
- { 602, 1360},{ 767, 1595},{ 933, 1794},{ 1098, 1968},
- { 1285, 2115},{ 1489, 2237},{ 1699, 2342},{ 1912, 2435},
- { 2101, 2519},{ 2288, 2601},{ 2486, 2663},{ 2651, 2715},
- { 2799, 2769},{ 2958, 2825},{ 3106, 2890},{ 3257, 2948},
- { 3452, 3007},{ 3634, 3075},{ 3786, 3136},{ 3959, 3164}
- },
- /*Cr qi=49 INTER*/
- {
- { 85, 1},{ 103, 352},{ 104, 681},{ 121, 1039},
- { 152, 1382},{ 195, 1702},{ 248, 2015},{ 316, 2316},
- { 403, 2595},{ 520, 2847},{ 676, 3068},{ 870, 3258},
- { 1091, 3429},{ 1329, 3585},{ 1597, 3725},{ 1894, 3849},
- { 2242, 3940},{ 2656, 3984},{ 3098, 3992},{ 3531, 3981},
- { 3936, 3950},{ 4304, 3915},{ 4646, 3879},{ 4915, 3861}
- }
- }
- },
- {
- {
- /*Y' qi=50 INTRA*/
- {
- { 122, 89},{ 798, 1170},{ 1682, 1812},{ 2613, 2096},
- { 3501, 2260},{ 4430, 2388},{ 5352, 2510},{ 6228, 2613},
- { 7043, 2698},{ 7793, 2770},{ 8486, 2823},{ 9092, 2846},
- { 9652, 2865},{10210, 2895},{10773, 2936},{11315, 2979},
- {11817, 3014},{12297, 3041},{12734, 3057},{13097, 3064},
- {13443, 3067},{13813, 3078},{14190, 3088},{14646, 3103}
- },
- /*Y' qi=50 INTER*/
- {
- { 73, -11},{ 154, 1318},{ 501, 2457},{ 1281, 3291},
- { 2685, 3719},{ 4356, 3810},{ 5811, 3769},{ 6988, 3726},
- { 7976, 3700},{ 8835, 3682},{ 9606, 3669},{10307, 3659},
- {10953, 3652},{11556, 3645},{12115, 3643},{12641, 3640},
- {13138, 3636},{13613, 3634},{14068, 3629},{14488, 3627},
- {14876, 3625},{15237, 3621},{15585, 3623},{15922, 3629}
- }
- },
- {
- /*Cb qi=50 INTRA*/
- {
- { 11, 2},{ 148, 368},{ 278, 724},{ 431, 1052},
- { 613, 1334},{ 806, 1567},{ 1004, 1756},{ 1203, 1915},
- { 1405, 2051},{ 1621, 2163},{ 1833, 2262},{ 2059, 2347},
- { 2280, 2424},{ 2476, 2512},{ 2670, 2598},{ 2864, 2679},
- { 3037, 2754},{ 3201, 2826},{ 3376, 2887},{ 3562, 2936},
- { 3756, 2976},{ 3932, 3022},{ 4117, 3065},{ 4385, 3094}
- },
- /*Cb qi=50 INTER*/
- {
- { 92, -3},{ 112, 343},{ 109, 669},{ 121, 1027},
- { 149, 1375},{ 196, 1697},{ 270, 1992},{ 366, 2267},
- { 471, 2532},{ 594, 2782},{ 747, 3011},{ 942, 3212},
- { 1189, 3384},{ 1497, 3521},{ 1875, 3613},{ 2297, 3673},
- { 2739, 3710},{ 3195, 3725},{ 3644, 3737},{ 4057, 3751},
- { 4445, 3763},{ 4841, 3769},{ 5211, 3779},{ 5568, 3769}
- }
- },
- {
- /*Cr qi=50 INTRA*/
- {
- { 19, 7},{ 155, 388},{ 290, 744},{ 474, 1060},
- { 666, 1324},{ 847, 1549},{ 1033, 1737},{ 1219, 1898},
- { 1428, 2034},{ 1653, 2147},{ 1885, 2245},{ 2115, 2329},
- { 2316, 2410},{ 2517, 2486},{ 2730, 2539},{ 2901, 2586},
- { 3042, 2638},{ 3199, 2693},{ 3366, 2755},{ 3534, 2805},
- { 3738, 2858},{ 3934, 2916},{ 4079, 2975},{ 4257, 2992}
- },
- /*Cr qi=50 INTER*/
- {
- { 87, 1},{ 102, 353},{ 103, 680},{ 121, 1036},
- { 153, 1377},{ 199, 1694},{ 260, 1999},{ 339, 2291},
- { 446, 2559},{ 590, 2797},{ 780, 3003},{ 1010, 3176},
- { 1267, 3331},{ 1547, 3474},{ 1874, 3594},{ 2245, 3688},
- { 2666, 3742},{ 3130, 3758},{ 3594, 3748},{ 4028, 3711},
- { 4415, 3674},{ 4771, 3641},{ 5122, 3605},{ 5482, 3569}
- }
- }
- },
- {
- {
- /*Y' qi=51 INTRA*/
- {
- { 115, 93},{ 819, 1164},{ 1739, 1806},{ 2695, 2101},
- { 3612, 2257},{ 4552, 2374},{ 5479, 2490},{ 6352, 2593},
- { 7158, 2683},{ 7898, 2761},{ 8580, 2823},{ 9177, 2854},
- { 9728, 2880},{10268, 2917},{10816, 2966},{11350, 3016},
- {11834, 3058},{12311, 3089},{12741, 3109},{13092, 3119},
- {13434, 3126},{13791, 3142},{14156, 3155},{14590, 3171}
- },
- /*Y' qi=51 INTER*/
- {
- { 58, 0},{ 171, 1307},{ 610, 2407},{ 1563, 3175},
- { 3116, 3545},{ 4789, 3624},{ 6185, 3602},{ 7320, 3583},
- { 8282, 3574},{ 9124, 3569},{ 9878, 3567},{10569, 3565},
- {11207, 3563},{11801, 3564},{12359, 3566},{12884, 3567},
- {13373, 3568},{13841, 3567},{14289, 3566},{14699, 3568},
- {15086, 3568},{15446, 3566},{15788, 3564},{16103, 3568}
- }
- },
- {
- /*Cb qi=51 INTRA*/
- {
- { 14, 3},{ 161, 369},{ 297, 722},{ 454, 1047},
- { 639, 1325},{ 833, 1554},{ 1033, 1742},{ 1236, 1897},
- { 1440, 2032},{ 1653, 2148},{ 1860, 2253},{ 2077, 2347},
- { 2288, 2432},{ 2476, 2525},{ 2661, 2621},{ 2841, 2714},
- { 3010, 2797},{ 3170, 2876},{ 3333, 2945},{ 3510, 3000},
- { 3696, 3054},{ 3865, 3114},{ 4046, 3164},{ 4317, 3200}
- },
- /*Cb qi=51 INTER*/
- {
- { 88, -11},{ 109, 341},{ 109, 668},{ 126, 1019},
- { 168, 1358},{ 233, 1670},{ 329, 1955},{ 451, 2219},
- { 584, 2472},{ 736, 2711},{ 931, 2923},{ 1179, 3104},
- { 1480, 3254},{ 1846, 3368},{ 2265, 3448},{ 2714, 3501},
- { 3180, 3524},{ 3638, 3529},{ 4074, 3543},{ 4485, 3560},
- { 4868, 3571},{ 5238, 3581},{ 5597, 3594},{ 5953, 3591}
- }
- },
- {
- /*Cr qi=51 INTRA*/
- {
- { 24, 7},{ 168, 388},{ 309, 742},{ 496, 1054},
- { 688, 1316},{ 873, 1538},{ 1063, 1723},{ 1252, 1882},
- { 1460, 2018},{ 1682, 2134},{ 1907, 2238},{ 2125, 2332},
- { 2317, 2422},{ 2507, 2510},{ 2705, 2575},{ 2869, 2630},
- { 3015, 2684},{ 3178, 2744},{ 3329, 2815},{ 3477, 2878},
- { 3667, 2945},{ 3848, 3016},{ 3997, 3082},{ 4174, 3121}
- },
- /*Cr qi=51 INTER*/
- {
- { 83, -2},{ 102, 351},{ 102, 680},{ 126, 1029},
- { 172, 1359},{ 238, 1665},{ 321, 1962},{ 422, 2246},
- { 552, 2505},{ 733, 2728},{ 970, 2912},{ 1247, 3069},
- { 1552, 3209},{ 1876, 3338},{ 2251, 3440},{ 2692, 3502},
- { 3161, 3529},{ 3637, 3525},{ 4084, 3509},{ 4487, 3479},
- { 4850, 3444},{ 5181, 3419},{ 5507, 3406},{ 5786, 3398}
- }
- }
- },
- {
- {
- /*Y' qi=52 INTRA*/
- {
- { 117, 93},{ 814, 1168},{ 1729, 1822},{ 2706, 2119},
- { 3655, 2262},{ 4604, 2374},{ 5528, 2490},{ 6394, 2596},
- { 7189, 2691},{ 7921, 2777},{ 8596, 2846},{ 9184, 2885},
- { 9728, 2918},{10260, 2961},{10796, 3014},{11316, 3069},
- {11793, 3115},{12267, 3150},{12692, 3172},{13037, 3185},
- {13367, 3196},{13717, 3214},{14087, 3227},{14521, 3249}
- },
- /*Y' qi=52 INTER*/
- {
- { 52, 0},{ 169, 1308},{ 668, 2382},{ 1735, 3112},
- { 3384, 3451},{ 5077, 3519},{ 6461, 3506},{ 7587, 3496},
- { 8545, 3494},{ 9384, 3494},{10142, 3498},{10838, 3501},
- {11475, 3503},{12078, 3508},{12640, 3511},{13162, 3513},
- {13654, 3517},{14130, 3521},{14576, 3522},{14980, 3523},
- {15369, 3523},{15737, 3522},{16071, 3521},{16382, 3516}
- }
- },
- {
- /*Cb qi=52 INTRA*/
- {
- { 14, 3},{ 163, 369},{ 299, 722},{ 457, 1044},
- { 645, 1319},{ 843, 1545},{ 1050, 1728},{ 1261, 1879},
- { 1468, 2013},{ 1678, 2132},{ 1883, 2240},{ 2093, 2338},
- { 2301, 2428},{ 2488, 2523},{ 2667, 2619},{ 2843, 2718},
- { 3010, 2805},{ 3163, 2887},{ 3323, 2963},{ 3490, 3028},
- { 3665, 3087},{ 3841, 3145},{ 4011, 3197},{ 4289, 3230}
- },
- /*Cb qi=52 INTER*/
- {
- { 98, -7},{ 109, 342},{ 109, 668},{ 126, 1018},
- { 170, 1355},{ 242, 1663},{ 352, 1941},{ 490, 2195},
- { 642, 2439},{ 823, 2666},{ 1052, 2868},{ 1333, 3039},
- { 1670, 3178},{ 2074, 3280},{ 2524, 3348},{ 2996, 3390},
- { 3469, 3410},{ 3923, 3420},{ 4355, 3434},{ 4771, 3451},
- { 5166, 3468},{ 5532, 3483},{ 5885, 3499},{ 6263, 3501}
- }
- },
- {
- /*Cr qi=52 INTRA*/
- {
- { 25, 7},{ 170, 388},{ 312, 741},{ 500, 1051},
- { 694, 1310},{ 883, 1529},{ 1082, 1709},{ 1280, 1864},
- { 1491, 1998},{ 1710, 2117},{ 1932, 2225},{ 2143, 2324},
- { 2328, 2418},{ 2516, 2506},{ 2708, 2578},{ 2870, 2637},
- { 3017, 2693},{ 3170, 2758},{ 3312, 2835},{ 3455, 2901},
- { 3644, 2972},{ 3827, 3049},{ 3968, 3121},{ 4115, 3166}
- },
- /*Cr qi=52 INTER*/
- {
- { 86, -2},{ 101, 352},{ 100, 680},{ 126, 1028},
- { 175, 1356},{ 247, 1657},{ 341, 1948},{ 458, 2224},
- { 615, 2471},{ 828, 2681},{ 1091, 2857},{ 1395, 3008},
- { 1732, 3140},{ 2095, 3257},{ 2502, 3348},{ 2968, 3402},
- { 3457, 3420},{ 3926, 3413},{ 4360, 3388},{ 4759, 3357},
- { 5128, 3329},{ 5449, 3306},{ 5741, 3295},{ 6071, 3296}
- }
- }
- },
- {
- {
- /*Y' qi=53 INTRA*/
- {
- { 138, 93},{ 850, 1161},{ 1773, 1810},{ 2763, 2103},
- { 3722, 2245},{ 4675, 2360},{ 5600, 2483},{ 6464, 2597},
- { 7255, 2700},{ 7982, 2792},{ 8652, 2867},{ 9237, 2913},
- { 9775, 2950},{10302, 2998},{10834, 3058},{11347, 3121},
- {11826, 3169},{12299, 3207},{12713, 3235},{13054, 3250},
- {13387, 3265},{13744, 3286},{14110, 3302},{14515, 3323}
- },
- /*Y' qi=53 INTER*/
- {
- { 52, 2},{ 169, 1308},{ 680, 2377},{ 1763, 3103},
- { 3410, 3450},{ 5094, 3531},{ 6469, 3526},{ 7590, 3525},
- { 8547, 3530},{ 9385, 3534},{10139, 3540},{10835, 3548},
- {11479, 3553},{12075, 3559},{12634, 3565},{13159, 3570},
- {13650, 3573},{14124, 3576},{14575, 3580},{14993, 3583},
- {15375, 3584},{15744, 3584},{16091, 3583},{16421, 3586}
- }
- },
- {
- /*Cb qi=53 INTRA*/
- {
- { 14, 3},{ 167, 367},{ 317, 717},{ 492, 1033},
- { 687, 1306},{ 887, 1531},{ 1095, 1715},{ 1309, 1866},
- { 1517, 2000},{ 1729, 2119},{ 1932, 2227},{ 2146, 2325},
- { 2358, 2414},{ 2544, 2511},{ 2724, 2611},{ 2902, 2711},
- { 3070, 2800},{ 3227, 2878},{ 3381, 2954},{ 3548, 3021},
- { 3724, 3077},{ 3888, 3140},{ 4065, 3196},{ 4359, 3225}
- },
- /*Cb qi=53 INTER*/
- {
- { 93, -8},{ 110, 342},{ 108, 668},{ 125, 1018},
- { 170, 1355},{ 242, 1663},{ 353, 1939},{ 494, 2192},
- { 651, 2433},{ 838, 2658},{ 1076, 2856},{ 1368, 3022},
- { 1716, 3158},{ 2123, 3260},{ 2575, 3330},{ 3042, 3373},
- { 3507, 3396},{ 3962, 3413},{ 4394, 3430},{ 4797, 3452},
- { 5169, 3476},{ 5547, 3496},{ 5914, 3510},{ 6235, 3525}
- }
- },
- {
- /*Cr qi=53 INTRA*/
- {
- { 25, 7},{ 175, 386},{ 335, 734},{ 541, 1037},
- { 737, 1296},{ 926, 1516},{ 1125, 1696},{ 1324, 1851},
- { 1540, 1984},{ 1763, 2102},{ 1989, 2210},{ 2202, 2310},
- { 2386, 2404},{ 2572, 2495},{ 2768, 2569},{ 2929, 2627},
- { 3071, 2684},{ 3231, 2749},{ 3374, 2825},{ 3514, 2894},
- { 3703, 2963},{ 3882, 3040},{ 4024, 3111},{ 4190, 3150}
- },
- /*Cr qi=53 INTER*/
- {
- { 87, -1},{ 99, 352},{ 100, 680},{ 125, 1027},
- { 175, 1355},{ 249, 1657},{ 343, 1946},{ 462, 2220},
- { 624, 2465},{ 844, 2671},{ 1122, 2841},{ 1435, 2989},
- { 1768, 3125},{ 2134, 3243},{ 2545, 3334},{ 3002, 3393},
- { 3490, 3412},{ 3965, 3405},{ 4401, 3384},{ 4797, 3359},
- { 5156, 3328},{ 5482, 3297},{ 5800, 3292},{ 6135, 3293}
+ { 39, -33},{ 48, 403},{ 86, 744},{ 110, 1101},
+ { 134, 1461},{ 165, 1779},{ 205, 2095},{ 259, 2401},
+ { 318, 2686},{ 386, 2958},{ 481, 3204},{ 610, 3415},
+ { 753, 3603},{ 908, 3780},{ 1055, 3959},{ 1220, 4132},
+ { 1422, 4281},{ 1656, 4419},{ 1939, 4512},{ 2259, 4574},
+ { 2593, 4593},{ 2950, 4569},{ 3339, 4505},{ 3542, 4497}
}
}
},
@@ -3406,557 +403,563 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=54 INTRA*/
{
- { 184, 94},{ 902, 1151},{ 1876, 1776},{ 2881, 2057},
- { 3832, 2200},{ 4785, 2315},{ 5709, 2442},{ 6570, 2562},
- { 7362, 2672},{ 8092, 2771},{ 8760, 2852},{ 9337, 2901},
- { 9874, 2943},{10402, 2995},{10928, 3059},{11443, 3126},
- {11926, 3178},{12396, 3220},{12805, 3251},{13139, 3266},
- {13466, 3280},{13822, 3304},{14184, 3322},{14585, 3342}
+ { 339, 30},{ 785, 1251},{ 2395, 1971},{ 4075, 2063},
+ { 4924, 2135},{ 5806, 2270},{ 6604, 2372},{ 7224, 2497},
+ { 7879, 2608},{ 8400, 2729},{ 8951, 2829},{ 9379, 2864},
+ { 9782, 2955},{10230, 3020},{10704, 3132},{11264, 3272},
+ {11618, 3284},{12034, 3394},{12500, 3482},{12767, 3484},
+ {13162, 3580},{13552, 3565},{13997, 3732},{14320, 3715}
},
/*Y' qi=54 INTER*/
{
- { 60, 5},{ 169, 1308},{ 683, 2375},{ 1791, 3090},
- { 3478, 3412},{ 5184, 3470},{ 6568, 3455},{ 7697, 3446},
- { 8659, 3446},{ 9503, 3447},{10266, 3450},{10971, 3454},
- {11619, 3458},{12223, 3462},{12789, 3467},{13315, 3471},
- {13811, 3475},{14291, 3479},{14743, 3479},{15148, 3481},
- {15535, 3483},{15913, 3481},{16252, 3479},{16569, 3472}
+ { 65, 95},{ 269, 1312},{ 1152, 2242},{ 2336, 2863},
+ { 3728, 3239},{ 4944, 3439},{ 6034, 3543},{ 7064, 3580},
+ { 7991, 3586},{ 8849, 3568},{ 9605, 3561},{10306, 3550},
+ {10919, 3544},{11466, 3530},{11972, 3528},{12401, 3536},
+ {12818, 3511},{13185, 3522},{13523, 3505},{13827, 3505},
+ {14114, 3522},{14395, 3521},{14625, 3533},{14909, 3532}
}
},
{
/*Cb qi=54 INTRA*/
{
- { 13, 2},{ 165, 367},{ 318, 715},{ 498, 1030},
- { 698, 1301},{ 906, 1523},{ 1121, 1703},{ 1336, 1853},
- { 1549, 1984},{ 1765, 2100},{ 1974, 2207},{ 2192, 2306},
- { 2402, 2396},{ 2587, 2493},{ 2773, 2591},{ 2953, 2691},
- { 3119, 2778},{ 3277, 2858},{ 3430, 2940},{ 3603, 3004},
- { 3788, 3059},{ 3950, 3121},{ 4128, 3173},{ 4398, 3215}
+ { 148, -3},{ 218, 480},{ 351, 787},{ 437, 1069},
+ { 550, 1350},{ 730, 1592},{ 931, 1784},{ 1243, 1884},
+ { 1499, 1984},{ 1680, 2115},{ 1864, 2244},{ 2062, 2334},
+ { 2278, 2407},{ 2442, 2496},{ 2602, 2603},{ 2783, 2686},
+ { 2928, 2771},{ 3073, 2856},{ 3207, 2938},{ 3368, 2998},
+ { 3516, 3077},{ 3699, 3122},{ 3818, 3202},{ 3939, 3230}
},
/*Cb qi=54 INTER*/
{
- { 100, -3},{ 109, 343},{ 107, 668},{ 125, 1018},
- { 169, 1354},{ 241, 1662},{ 353, 1938},{ 496, 2190},
- { 655, 2431},{ 843, 2655},{ 1082, 2851},{ 1381, 3015},
- { 1739, 3146},{ 2154, 3243},{ 2610, 3310},{ 3094, 3344},
- { 3581, 3358},{ 4034, 3371},{ 4457, 3384},{ 4867, 3399},
- { 5255, 3413},{ 5630, 3425},{ 6003, 3440},{ 6346, 3440}
+ { 48, -11},{ 54, 407},{ 86, 743},{ 122, 1083},
+ { 176, 1400},{ 241, 1699},{ 347, 1968},{ 496, 2208},
+ { 664, 2431},{ 863, 2637},{ 1120, 2816},{ 1442, 2961},
+ { 1835, 3066},{ 2261, 3140},{ 2676, 3203},{ 3092, 3245},
+ { 3480, 3266},{ 3862, 3286},{ 4254, 3305},{ 4604, 3316},
+ { 4989, 3335},{ 5306, 3351},{ 5654, 3339},{ 5855, 3345}
}
},
{
/*Cr qi=54 INTRA*/
{
- { 23, 7},{ 174, 386},{ 338, 732},{ 549, 1034},
- { 751, 1289},{ 947, 1506},{ 1150, 1685},{ 1353, 1837},
- { 1572, 1969},{ 1800, 2087},{ 2031, 2192},{ 2248, 2291},
- { 2434, 2387},{ 2622, 2477},{ 2815, 2549},{ 2976, 2607},
- { 3126, 2663},{ 3286, 2727},{ 3427, 2807},{ 3569, 2877},
- { 3761, 2941},{ 3942, 3016},{ 4084, 3093},{ 4226, 3131}
+ { 137, 10},{ 212, 492},{ 315, 795},{ 470, 1061},
+ { 612, 1333},{ 821, 1539},{ 1105, 1680},{ 1335, 1811},
+ { 1566, 1927},{ 1773, 2038},{ 1973, 2153},{ 2148, 2259},
+ { 2311, 2352},{ 2474, 2460},{ 2647, 2516},{ 2810, 2607},
+ { 2928, 2638},{ 3085, 2742},{ 3232, 2815},{ 3348, 2899},
+ { 3533, 2993},{ 3679, 3029},{ 3803, 3138},{ 3925, 3170}
},
/*Cr qi=54 INTER*/
{
- { 88, -2},{ 99, 351},{ 100, 680},{ 125, 1027},
- { 175, 1354},{ 248, 1656},{ 343, 1945},{ 463, 2219},
- { 626, 2463},{ 850, 2668},{ 1128, 2837},{ 1445, 2983},
- { 1791, 3111},{ 2168, 3224},{ 2597, 3309},{ 3075, 3351},
- { 3560, 3364},{ 4029, 3356},{ 4464, 3335},{ 4858, 3307},
- { 5218, 3275},{ 5547, 3256},{ 5850, 3247},{ 6171, 3214}
+ { 46, 2},{ 47, 419},{ 87, 746},{ 125, 1083},
+ { 177, 1401},{ 249, 1687},{ 342, 1964},{ 453, 2226},
+ { 627, 2454},{ 869, 2641},{ 1152, 2800},{ 1455, 2942},
+ { 1776, 3077},{ 2135, 3187},{ 2524, 3287},{ 2984, 3325},
+ { 3425, 3344},{ 3881, 3328},{ 4313, 3274},{ 4701, 3218},
+ { 5027, 3171},{ 5299, 3130},{ 5597, 3107},{ 5791, 3120}
}
}
},
{
{
- /*Y' qi=55 INTRA*/
- {
- { 178, 95},{ 968, 1137},{ 2000, 1747},{ 3013, 2027},
- { 3966, 2173},{ 4920, 2294},{ 5842, 2427},{ 6702, 2553},
- { 7489, 2668},{ 8213, 2773},{ 8875, 2858},{ 9452, 2913},
- { 9986, 2959},{10504, 3016},{11023, 3085},{11530, 3157},
- {12011, 3213},{12480, 3257},{12882, 3291},{13214, 3310},
- {13542, 3325},{13890, 3350},{14248, 3371},{14671, 3398}
+ /*Y' qi=63 INTRA*/
+ {
+ { -86, 167},{ 2070, 1104},{ 5138, 1428},{ 7014, 1535},
+ { 8430, 1629},{ 9663, 1690},{10576, 1745},{11277, 1809},
+ {12003, 1869},{12663, 1925},{13258, 1983},{13701, 2016},
+ {14228, 2073},{14756, 2088},{15203, 2164},{15993, 2175},
+ {16378, 2256},{16917, 2240},{17361, 2332},{17782, 2312},
+ {18376, 2381},{18728, 2362},{19224, 2408},{19705, 2392}
},
- /*Y' qi=55 INTER*/
- {
- { 59, 5},{ 170, 1307},{ 725, 2358},{ 1886, 3058},
- { 3589, 3385},{ 5284, 3459},{ 6654, 3458},{ 7771, 3461},
- { 8727, 3470},{ 9564, 3478},{10322, 3488},{11019, 3497},
- {11658, 3505},{12258, 3513},{12819, 3520},{13344, 3527},
- {13840, 3533},{14314, 3537},{14755, 3541},{15161, 3544},
- {15552, 3548},{15916, 3548},{16257, 3548},{16576, 3540}
+ /*Y' qi=63 INTER*/
+ {
+ { -529, 154},{ 967, 1233},{ 4201, 1610},{ 6285, 1800},
+ { 8058, 1908},{ 9439, 1968},{10737, 1987},{11999, 1979},
+ {13003, 1972},{13854, 1963},{14584, 1965},{15217, 1955},
+ {15773, 1956},{16229, 1949},{16735, 1952},{17085, 1956},
+ {17508, 1956},{17821, 1961},{18191, 1961},{18465, 1982},
+ {18792, 1975},{19158, 1995},{19378, 2010},{19817, 2021}
}
},
{
- /*Cb qi=55 INTRA*/
- {
- { 13, 2},{ 167, 366},{ 322, 714},{ 508, 1026},
- { 716, 1292},{ 930, 1511},{ 1148, 1690},{ 1366, 1839},
- { 1578, 1972},{ 1793, 2090},{ 2001, 2199},{ 2217, 2300},
- { 2427, 2393},{ 2609, 2495},{ 2784, 2600},{ 2961, 2704},
- { 3121, 2797},{ 3268, 2884},{ 3423, 2965},{ 3590, 3032},
- { 3764, 3096},{ 3926, 3165},{ 4101, 3223},{ 4405, 3258}
+ /*Cb qi=63 INTRA*/
+ {
+ { 136, 4},{ 338, 438},{ 593, 730},{ 835, 974},
+ { 1168, 1188},{ 1602, 1345},{ 2004, 1467},{ 2465, 1505},
+ { 2799, 1574},{ 3091, 1669},{ 3384, 1758},{ 3673, 1817},
+ { 3950, 1861},{ 4190, 1924},{ 4444, 1993},{ 4701, 2051},
+ { 4915, 2123},{ 5119, 2166},{ 5329, 2231},{ 5576, 2259},
+ { 5793, 2310},{ 6001, 2334},{ 6198, 2384},{ 6344, 2401}
},
- /*Cb qi=55 INTER*/
- {
- { 90, -4},{ 109, 344},{ 107, 668},{ 126, 1017},
- { 172, 1351},{ 249, 1657},{ 370, 1928},{ 527, 2174},
- { 702, 2407},{ 909, 2624},{ 1170, 2814},{ 1493, 2970},
- { 1869, 3097},{ 2292, 3192},{ 2752, 3258},{ 3232, 3295},
- { 3709, 3314},{ 4156, 3335},{ 4592, 3355},{ 5004, 3373},
- { 5377, 3389},{ 5737, 3411},{ 6092, 3432},{ 6473, 3423}
+ /*Cb qi=63 INTER*/
+ {
+ { 49, 4},{ 51, 403},{ 98, 729},{ 185, 1034},
+ { 352, 1304},{ 622, 1533},{ 1068, 1696},{ 1604, 1821},
+ { 2203, 1924},{ 2890, 1988},{ 3622, 2017},{ 4359, 2019},
+ { 5025, 2005},{ 5586, 2002},{ 6090, 1989},{ 6519, 1977},
+ { 6927, 1977},{ 7305, 1968},{ 7730, 1984},{ 8087, 1981},
+ { 8435, 1991},{ 8822, 1987},{ 9155, 2008},{ 9392, 2011}
}
},
{
- /*Cr qi=55 INTRA*/
- {
- { 23, 7},{ 175, 385},{ 342, 730},{ 561, 1028},
- { 771, 1279},{ 973, 1493},{ 1181, 1669},{ 1384, 1822},
- { 1602, 1956},{ 1830, 2076},{ 2057, 2184},{ 2270, 2288},
- { 2452, 2389},{ 2637, 2484},{ 2823, 2559},{ 2983, 2621},
- { 3129, 2682},{ 3280, 2753},{ 3417, 2833},{ 3554, 2904},
- { 3743, 2977},{ 3921, 3060},{ 4055, 3137},{ 4185, 3186}
+ /*Cr qi=63 INTRA*/
+ {
+ { 131, 11},{ 334, 448},{ 569, 739},{ 929, 946},
+ { 1285, 1145},{ 1718, 1274},{ 2176, 1343},{ 2531, 1424},
+ { 2866, 1504},{ 3176, 1580},{ 3475, 1657},{ 3736, 1728},
+ { 3962, 1807},{ 4232, 1872},{ 4425, 1921},{ 4657, 1976},
+ { 4817, 2009},{ 5063, 2082},{ 5281, 2129},{ 5480, 2199},
+ { 5743, 2258},{ 5887, 2283},{ 6124, 2358},{ 6273, 2378}
},
- /*Cr qi=55 INTER*/
- {
- { 85, 0},{ 99, 352},{ 100, 679},{ 126, 1025},
- { 178, 1351},{ 256, 1650},{ 359, 1935},{ 493, 2202},
- { 675, 2439},{ 921, 2636},{ 1220, 2799},{ 1552, 2941},
- { 1910, 3068},{ 2303, 3177},{ 2735, 3262},{ 3206, 3311},
- { 3689, 3333},{ 4152, 3327},{ 4588, 3299},{ 4978, 3272},
- { 5325, 3243},{ 5651, 3221},{ 5969, 3210},{ 6218, 3185}
+ /*Cr qi=63 INTER*/
+ {
+ { 47, 15},{ 40, 405},{ 100, 730},{ 189, 1037},
+ { 351, 1303},{ 625, 1526},{ 984, 1719},{ 1512, 1862},
+ { 2189, 1947},{ 2895, 2003},{ 3576, 2046},{ 4249, 2072},
+ { 4901, 2068},{ 5514, 2043},{ 6079, 2009},{ 6528, 1977},
+ { 6927, 1940},{ 7274, 1915},{ 7580, 1894},{ 7910, 1910},
+ { 8211, 1902},{ 8472, 1920},{ 8742, 1926},{ 8981, 1930}
}
}
- },
+ }
+};
+
+# if !defined(OC_COLLECT_METRICS)
+static const
+# endif
+oc_mode_rd OC_MODE_RD_SAD[OC_LOGQ_BINS][3][2][OC_COMP_BINS]={
{
{
- /*Y' qi=56 INTRA*/
- {
- { 137, 104},{ 1048, 1128},{ 2147, 1760},{ 3261, 2029},
- { 4319, 2131},{ 5310, 2234},{ 6245, 2351},{ 7101, 2464},
- { 7886, 2572},{ 8610, 2675},{ 9270, 2762},{ 9840, 2818},
- {10365, 2869},{10875, 2928},{11393, 2997},{11900, 3071},
- {12371, 3128},{12834, 3172},{13233, 3208},{13562, 3228},
- {13878, 3245},{14221, 3271},{14584, 3292},{15008, 3320}
+ /*Y' qi=0 INTRA*/
+ {
+ { 33, 122},{ 57, 1297},{ 13, 2226},{ 157, 3890},
+ { 227, 3682},{ 169, 3084},{ 197, 2700},{ 227, 3238},
+ { 290, 4294},{ 354, 5230},{ 406, 5615},{ 417, 5322},
+ { 452, 5462},{ 455, 5683},{ 493, 5938},{ 553, 6374},
+ { 558, 6464},{ 606, 6493},{ 616, 6417},{ 643, 6557},
+ { 641, 6664},{ 716, 7285},{ 748, 7518},{ 747, 7502}
},
- /*Y' qi=56 INTER*/
- {
- { 19, 21},{ 207, 1292},{ 1031, 2252},{ 2553, 2846},
- { 4463, 3085},{ 6137, 3131},{ 7441, 3151},{ 8526, 3172},
- { 9468, 3193},{10301, 3209},{11059, 3224},{11760, 3237},
- {12405, 3249},{13008, 3261},{13570, 3270},{14100, 3278},
- {14597, 3284},{15074, 3289},{15524, 3297},{15929, 3302},
- {16314, 3306},{16675, 3307},{17004, 3305},{17288, 3301}
+ /*Y' qi=0 INTER*/
+ {
+ { 16, 205},{ 5, 1338},{ 16, 2554},{ 6, 3809},
+ { 9, 5188},{ 58, 6446},{ 76, 7561},{ 95, 8648},
+ { 124, 9713},{ 158,10787},{ 193,11887},{ 233,12991},
+ { 270,14116},{ 307,15236},{ 341,16346},{ 372,17426},
+ { 398,18499},{ 422,19594},{ 448,20669},{ 479,21732},
+ { 526,22720},{ 583,23572},{ 655,24516},{ 758,24647}
}
},
{
- /*Cb qi=56 INTRA*/
- {
- { 16, 3},{ 188, 367},{ 353, 712},{ 546, 1017},
- { 765, 1275},{ 989, 1484},{ 1221, 1653},{ 1459, 1791},
- { 1681, 1920},{ 1893, 2046},{ 2102, 2160},{ 2323, 2257},
- { 2534, 2347},{ 2720, 2447},{ 2902, 2549},{ 3075, 2654},
- { 3239, 2749},{ 3392, 2835},{ 3544, 2920},{ 3712, 2988},
- { 3882, 3052},{ 4052, 3123},{ 4227, 3181},{ 4483, 3213}
+ /*Cb qi=0 INTRA*/
+ {
+ { 26, 40},{ 23, 589},{ 27, 784},{ 27, 1079},
+ { 24, 1186},{ 25, 1641},{ 25, 1915},{ 29, 2207},
+ { 39, 2361},{ 39, 2746},{ 32, 3020},{ 16, 3387},
+ { 31, 3604},{ 36, 4076},{ 69, 4426},{ 102, 4724},
+ { 139, 4923},{ 196, 5061},{ 211, 5103},{ 214, 5063},
+ { 161, 4466},{ 208, 4793},{ 218, 4537},{ 219, 4539}
},
- /*Cb qi=56 INTER*/
- {
- { 92, -1},{ 111, 343},{ 114, 665},{ 148, 1003},
- { 224, 1321},{ 345, 1609},{ 526, 1858},{ 754, 2077},
- { 1009, 2281},{ 1319, 2464},{ 1702, 2614},{ 2145, 2732},
- { 2625, 2824},{ 3123, 2890},{ 3634, 2933},{ 4137, 2954},
- { 4614, 2965},{ 5052, 2988},{ 5468, 3015},{ 5852, 3035},
- { 6213, 3060},{ 6557, 3081},{ 6906, 3094},{ 7243, 3112}
+ /*Cb qi=0 INTER*/
+ {
+ { 3, 164},{ 1, 535},{ 1, 779},{ 2, 1048},
+ { 3, 1267},{ 1, 1625},{ 2, 1921},{ 5, 2224},
+ { 8, 2481},{ 8, 2813},{ 4, 3089},{ -2, 3386},
+ { -9, 3642},{ -14, 3993},{ -11, 4300},{ -6, 4628},
+ { 4, 4929},{ 25, 5299},{ 44, 5623},{ 83, 5915},
+ { 93, 6186},{ 91, 6483},{ 90, 6775},{ 95, 6952}
}
},
{
- /*Cr qi=56 INTRA*/
- {
- { 28, 8},{ 195, 385},{ 373, 727},{ 598, 1019},
- { 816, 1263},{ 1033, 1465},{ 1260, 1630},{ 1482, 1773},
- { 1717, 1900},{ 1949, 2018},{ 2178, 2128},{ 2393, 2233},
- { 2570, 2338},{ 2749, 2435},{ 2937, 2514},{ 3097, 2577},
- { 3240, 2638},{ 3398, 2709},{ 3540, 2791},{ 3673, 2865},
- { 3869, 2938},{ 4049, 3019},{ 4179, 3095},{ 4330, 3137}
+ /*Cr qi=0 INTRA*/
+ {
+ { 22, 49},{ 26, 579},{ 23, 762},{ 15, 1050},
+ { 20, 1191},{ 24, 1608},{ 26, 1875},{ 35, 2173},
+ { 39, 2359},{ 30, 2736},{ 16, 2987},{ 0, 3334},
+ { 14, 3625},{ 11, 4095},{ 57, 4512},{ 95, 4793},
+ { 141, 4949},{ 206, 5242},{ 230, 5191},{ 242, 5177},
+ { 178, 4775},{ 237, 5010},{ 223, 4656},{ 224, 4657}
},
- /*Cr qi=56 INTER*/
- {
- { 83, 0},{ 99, 353},{ 103, 676},{ 146, 1010},
- { 232, 1320},{ 355, 1601},{ 512, 1866},{ 713, 2109},
- { 988, 2312},{ 1344, 2471},{ 1750, 2602},{ 2180, 2719},
- { 2642, 2819},{ 3141, 2892},{ 3653, 2939},{ 4159, 2961},
- { 4636, 2961},{ 5072, 2945},{ 5464, 2917},{ 5813, 2895},
- { 6134, 2890},{ 6458, 2883},{ 6735, 2881},{ 6953, 2902}
+ /*Cr qi=0 INTER*/
+ {
+ { 3, 163},{ 1, 536},{ 1, 773},{ 3, 1023},
+ { 2, 1225},{ 1, 1607},{ 1, 1900},{ 5, 2204},
+ { 9, 2453},{ 8, 2781},{ 3, 3049},{ -5, 3338},
+ { -13, 3570},{ -17, 3950},{ -13, 4255},{ -6, 4596},
+ { 7, 4893},{ 33, 5300},{ 53, 5632},{ 97, 5942},
+ { 103, 6216},{ 96, 6522},{ 91, 6849},{ 98, 6995}
}
}
},
{
{
- /*Y' qi=57 INTRA*/
- {
- { 170, 106},{ 1106, 1120},{ 2246, 1740},{ 3399, 1993},
- { 4482, 2077},{ 5492, 2167},{ 6446, 2273},{ 7324, 2379},
- { 8130, 2482},{ 8866, 2578},{ 9537, 2661},{10119, 2715},
- {10646, 2762},{11161, 2820},{11694, 2886},{12214, 2957},
- {12693, 3013},{13166, 3053},{13569, 3087},{13897, 3106},
- {14224, 3122},{14568, 3148},{14931, 3167},{15390, 3192}
+ /*Y' qi=9 INTRA*/
+ {
+ { 47, 152},{ 50, 1213},{ 144, 2543},{ 242, 2332},
+ { 210, 1894},{ 250, 2386},{ 328, 3094},{ 407, 3419},
+ { 464, 3507},{ 522, 3770},{ 613, 4194},{ 657, 4618},
+ { 753, 5137},{ 796, 5248},{ 842, 5110},{ 927, 5330},
+ { 994, 5487},{ 1008, 5463},{ 1101, 5794},{ 1169, 5966},
+ { 1208, 6121},{ 1331, 6447},{ 1445, 6618},{ 1449, 6616}
},
- /*Y' qi=57 INTER*/
- {
- { 19, 20},{ 205, 1292},{ 1096, 2229},{ 2775, 2766},
- { 4811, 2943},{ 6512, 2964},{ 7832, 2976},{ 8940, 2990},
- { 9903, 3004},{10755, 3017},{11532, 3029},{12243, 3039},
- {12891, 3047},{13502, 3058},{14073, 3065},{14603, 3071},
- {15097, 3078},{15581, 3083},{16036, 3086},{16452, 3090},
- {16855, 3093},{17222, 3094},{17552, 3092},{17851, 3098}
+ /*Y' qi=9 INTER*/
+ {
+ { 4, 218},{ 16, 1314},{ 4, 2563},{ 37, 3882},
+ { 83, 5058},{ 109, 6184},{ 161, 7292},{ 224, 8389},
+ { 287, 9485},{ 349,10565},{ 411,11608},{ 464,12648},
+ { 518,13664},{ 575,14650},{ 649,15585},{ 742,16451},
+ { 862,17214},{ 1003,17860},{ 1179,18325},{ 1372,18648},
+ { 1576,18878},{ 1795,18903},{ 2040,18880},{ 2116,18759}
}
},
{
- /*Cb qi=57 INTRA*/
- {
- { 16, 3},{ 197, 365},{ 384, 704},{ 603, 1001},
- { 837, 1252},{ 1077, 1455},{ 1326, 1618},{ 1581, 1748},
- { 1819, 1871},{ 2042, 1993},{ 2264, 2104},{ 2500, 2196},
- { 2722, 2280},{ 2916, 2375},{ 3103, 2473},{ 3290, 2575},
- { 3456, 2667},{ 3612, 2748},{ 3775, 2829},{ 3958, 2896},
- { 4145, 2947},{ 4307, 3012},{ 4476, 3070},{ 4733, 3110}
+ /*Cb qi=9 INTRA*/
+ {
+ { 27, 42},{ 23, 587},{ 34, 782},{ 37, 1079},
+ { 34, 1204},{ 42, 1630},{ 37, 1887},{ 25, 2210},
+ { 40, 2455},{ 71, 2880},{ 112, 3193},{ 156, 3427},
+ { 168, 3403},{ 217, 3488},{ 203, 3335},{ 224, 3200},
+ { 191, 2742},{ 195, 2810},{ 207, 2665},{ 201, 2661},
+ { 169, 2078},{ 211, 2720},{ 226, 2813},{ 228, 2824}
},
- /*Cb qi=57 INTER*/
- {
- { 94, -1},{ 111, 344},{ 112, 665},{ 147, 1002},
- { 227, 1319},{ 353, 1604},{ 543, 1849},{ 785, 2062},
- { 1066, 2257},{ 1408, 2430},{ 1827, 2568},{ 2320, 2670},
- { 2848, 2743},{ 3386, 2791},{ 3934, 2812},{ 4453, 2820},
- { 4929, 2830},{ 5368, 2842},{ 5787, 2856},{ 6190, 2875},
- { 6554, 2896},{ 6895, 2913},{ 7229, 2927},{ 7572, 2932}
+ /*Cb qi=9 INTER*/
+ {
+ { 4, 158},{ 2, 537},{ 3, 779},{ 2, 1045},
+ { 3, 1284},{ 7, 1629},{ 7, 1917},{ 1, 2218},
+ { -4, 2497},{ -3, 2845},{ 6, 3162},{ 23, 3482},
+ { 42, 3788},{ 62, 4116},{ 76, 4416},{ 84, 4700},
+ { 91, 4975},{ 95, 5259},{ 97, 5518},{ 94, 5790},
+ { 99, 6052},{ 111, 6311},{ 126, 6601},{ 136, 6719}
}
},
{
- /*Cr qi=57 INTRA*/
- {
- { 28, 8},{ 207, 383},{ 413, 716},{ 661, 999},
- { 889, 1237},{ 1123, 1433},{ 1365, 1592},{ 1603, 1731},
- { 1853, 1852},{ 2103, 1965},{ 2345, 2072},{ 2571, 2173},
- { 2763, 2271},{ 2949, 2364},{ 3146, 2438},{ 3315, 2497},
- { 3459, 2552},{ 3618, 2616},{ 3767, 2697},{ 3906, 2773},
- { 4099, 2841},{ 4281, 2916},{ 4429, 2987},{ 4569, 3030}
+ /*Cr qi=9 INTRA*/
+ {
+ { 25, 50},{ 32, 576},{ 32, 762},{ 21, 1049},
+ { 28, 1207},{ 41, 1603},{ 36, 1839},{ 26, 2170},
+ { 34, 2462},{ 59, 2872},{ 109, 3176},{ 157, 3364},
+ { 188, 3397},{ 231, 3418},{ 250, 3341},{ 261, 3228},
+ { 222, 2814},{ 258, 3091},{ 234, 2915},{ 228, 3042},
+ { 210, 2610},{ 273, 3210},{ 274, 3231},{ 276, 3239}
},
- /*Cr qi=57 INTER*/
- {
- { 85, 0},{ 99, 352},{ 102, 675},{ 147, 1008},
- { 235, 1317},{ 363, 1597},{ 529, 1858},{ 748, 2094},
- { 1050, 2287},{ 1439, 2436},{ 1877, 2557},{ 2352, 2660},
- { 2869, 2740},{ 3413, 2791},{ 3962, 2815},{ 4485, 2819},
- { 4955, 2816},{ 5382, 2800},{ 5769, 2772},{ 6107, 2748},
- { 6443, 2740},{ 6754, 2739},{ 7029, 2737},{ 7284, 2745}
+ /*Cr qi=9 INTER*/
+ {
+ { 4, 156},{ 2, 538},{ 3, 772},{ 2, 1028},
+ { 3, 1254},{ 7, 1613},{ 7, 1893},{ 0, 2191},
+ { -8, 2454},{ -4, 2811},{ 7, 3121},{ 27, 3442},
+ { 48, 3749},{ 72, 4101},{ 88, 4410},{ 91, 4698},
+ { 99, 4988},{ 99, 5279},{ 101, 5542},{ 95, 5813},
+ { 99, 6088},{ 114, 6367},{ 125, 6683},{ 137, 6761}
}
}
},
{
{
- /*Y' qi=58 INTRA*/
- {
- { 164, 109},{ 1198, 1111},{ 2396, 1737},{ 3606, 1978},
- { 4727, 2048},{ 5749, 2138},{ 6708, 2243},{ 7584, 2347},
- { 8388, 2449},{ 9122, 2549},{ 9784, 2635},{10354, 2691},
- {10876, 2740},{11385, 2800},{11912, 2869},{12429, 2941},
- {12902, 2997},{13375, 3040},{13779, 3075},{14103, 3096},
- {14435, 3112},{14783, 3140},{15141, 3160},{15599, 3186}
+ /*Y' qi=18 INTRA*/
+ {
+ { 51, 88},{ 88, 1344},{ 258, 1643},{ 228, 1325},
+ { 372, 2208},{ 443, 2371},{ 520, 2382},{ 584, 2477},
+ { 739, 2906},{ 859, 3348},{ 1008, 3697},{ 1131, 3884},
+ { 1278, 4110},{ 1349, 4229},{ 1431, 4329},{ 1544, 4395},
+ { 1602, 4439},{ 1669, 4535},{ 1814, 4656},{ 1883, 4716},
+ { 1957, 4940},{ 2101, 5019},{ 2259, 5249},{ 2265, 5246}
},
- /*Y' qi=58 INTER*/
- {
- { 14, 23},{ 210, 1290},{ 1277, 2178},{ 3118, 2677},
- { 5207, 2834},{ 6902, 2857},{ 8218, 2878},{ 9323, 2900},
- {10285, 2919},{11132, 2934},{11899, 2949},{12599, 2961},
- {13235, 2971},{13835, 2982},{14394, 2991},{14917, 2997},
- {15412, 3005},{15882, 3009},{16325, 3013},{16735, 3016},
- {17131, 3018},{17501, 3021},{17824, 3021},{18125, 3016}
+ /*Y' qi=18 INTER*/
+ {
+ { 26, 195},{ 1, 1317},{ 45, 2595},{ 103, 3750},
+ { 168, 4903},{ 281, 6007},{ 397, 7062},{ 513, 8064},
+ { 630, 9010},{ 758, 9902},{ 906,10732},{ 1095,11463},
+ { 1338,12060},{ 1629,12490},{ 1969,12724},{ 2313,12842},
+ { 2666,12828},{ 2993,12747},{ 3294,12670},{ 3558,12553},
+ { 3813,12440},{ 3990,12379},{ 4177,12291},{ 4226,12265}
}
},
{
- /*Cb qi=58 INTRA*/
- {
- { 17, 3},{ 200, 365},{ 389, 703},{ 613, 996},
- { 853, 1243},{ 1095, 1445},{ 1349, 1604},{ 1613, 1731},
- { 1853, 1853},{ 2074, 1978},{ 2292, 2091},{ 2526, 2184},
- { 2750, 2266},{ 2945, 2360},{ 3134, 2458},{ 3320, 2561},
- { 3482, 2654},{ 3641, 2737},{ 3804, 2818},{ 3985, 2881},
- { 4168, 2935},{ 4331, 3003},{ 4499, 3060},{ 4751, 3100}
+ /*Cb qi=18 INTRA*/
+ {
+ { 31, 43},{ 33, 585},{ 40, 781},{ 58, 1077},
+ { 45, 1189},{ 58, 1655},{ 66, 1983},{ 123, 2221},
+ { 168, 2193},{ 227, 2321},{ 241, 2246},{ 250, 2208},
+ { 221, 1786},{ 250, 2087},{ 247, 2036},{ 250, 2164},
+ { 241, 2054},{ 287, 2453},{ 302, 2551},{ 335, 2758},
+ { 279, 2511},{ 379, 2973},{ 404, 3028},{ 406, 3029}
},
- /*Cb qi=58 INTER*/
- {
- { 94, -1},{ 112, 345},{ 112, 665},{ 152, 998},
- { 247, 1307},{ 406, 1580},{ 644, 1810},{ 938, 2007},
- { 1271, 2189},{ 1668, 2348},{ 2151, 2470},{ 2691, 2558},
- { 3249, 2619},{ 3798, 2659},{ 4334, 2682},{ 4849, 2692},
- { 5314, 2700},{ 5747, 2721},{ 6167, 2742},{ 6547, 2765},
- { 6902, 2790},{ 7251, 2804},{ 7583, 2819},{ 7924, 2833}
+ /*Cb qi=18 INTER*/
+ {
+ { 7, 153},{ 4, 537},{ 3, 777},{ 9, 1034},
+ { 6, 1282},{ 0, 1630},{ 0, 1943},{ 21, 2252},
+ { 48, 2567},{ 67, 2881},{ 83, 3178},{ 89, 3463},
+ { 92, 3738},{ 99, 4024},{ 114, 4289},{ 131, 4552},
+ { 153, 4814},{ 179, 5081},{ 207, 5333},{ 241, 5581},
+ { 273, 5822},{ 303, 6068},{ 335, 6368},{ 353, 6432}
}
},
{
- /*Cr qi=58 INTRA*/
- {
- { 29, 8},{ 210, 382},{ 419, 714},{ 671, 993},
- { 903, 1229},{ 1141, 1422},{ 1390, 1578},{ 1635, 1713},
- { 1889, 1833},{ 2140, 1946},{ 2379, 2055},{ 2604, 2157},
- { 2794, 2256},{ 2977, 2349},{ 3174, 2422},{ 3339, 2482},
- { 3483, 2537},{ 3643, 2604},{ 3790, 2684},{ 3927, 2757},
- { 4112, 2826},{ 4294, 2900},{ 4451, 2975},{ 4600, 3011}
+ /*Cr qi=18 INTRA*/
+ {
+ { 31, 49},{ 42, 575},{ 42, 763},{ 38, 1045},
+ { 41, 1184},{ 56, 1631},{ 87, 1968},{ 163, 2177},
+ { 191, 2188},{ 236, 2264},{ 240, 2101},{ 234, 2047},
+ { 206, 1651},{ 222, 1966},{ 238, 2013},{ 240, 2176},
+ { 229, 2098},{ 321, 2592},{ 341, 2748},{ 378, 3025},
+ { 367, 2849},{ 442, 3283},{ 453, 3315},{ 455, 3313}
},
- /*Cr qi=58 INTER*/
- {
- { 86, 0},{ 99, 352},{ 103, 675},{ 151, 1004},
- { 256, 1306},{ 417, 1573},{ 628, 1819},{ 901, 2040},
- { 1262, 2217},{ 1705, 2353},{ 2191, 2466},{ 2713, 2556},
- { 3268, 2622},{ 3831, 2664},{ 4374, 2682},{ 4881, 2686},
- { 5339, 2685},{ 5747, 2668},{ 6123, 2646},{ 6465, 2630},
- { 6783, 2618},{ 7082, 2623},{ 7366, 2632},{ 7673, 2654}
+ /*Cr qi=18 INTER*/
+ {
+ { 6, 151},{ 3, 539},{ 3, 775},{ 8, 1027},
+ { 6, 1260},{ -3, 1619},{ 0, 1927},{ 24, 2238},
+ { 58, 2558},{ 76, 2871},{ 92, 3173},{ 96, 3461},
+ { 98, 3742},{ 104, 4032},{ 116, 4306},{ 136, 4578},
+ { 158, 4839},{ 185, 5123},{ 217, 5383},{ 250, 5642},
+ { 279, 5910},{ 306, 6169},{ 333, 6502},{ 350, 6522}
}
}
},
{
{
- /*Y' qi=59 INTRA*/
- {
- { 142, 112},{ 1259, 1100},{ 2552, 1711},{ 3815, 1933},
- { 4955, 1987},{ 5983, 2068},{ 6949, 2165},{ 7832, 2263},
- { 8645, 2359},{ 9392, 2454},{10066, 2536},{10643, 2589},
- {11174, 2636},{11696, 2693},{12230, 2758},{12752, 2826},
- {13239, 2883},{13721, 2926},{14139, 2959},{14479, 2978},
- {14811, 2993},{15166, 3020},{15532, 3039},{16000, 3062}
+ /*Y' qi=27 INTRA*/
+ {
+ { 10, 85},{ 280, 1349},{ 278, 815},{ 497, 1699},
+ { 600, 1569},{ 744, 1944},{ 894, 2114},{ 1040, 2292},
+ { 1216, 2484},{ 1485, 2816},{ 1778, 3065},{ 1990, 3243},
+ { 2199, 3381},{ 2326, 3515},{ 2370, 3422},{ 2512, 3581},
+ { 2548, 3526},{ 2656, 3615},{ 2803, 3679},{ 2946, 3766},
+ { 3023, 3824},{ 3179, 3908},{ 3374, 4035},{ 3377, 4030}
},
- /*Y' qi=59 INTER*/
- {
- { 8, 25},{ 211, 1289},{ 1394, 2144},{ 3421, 2580},
- { 5611, 2689},{ 7316, 2701},{ 8643, 2717},{ 9762, 2734},
- {10735, 2750},{11587, 2763},{12353, 2775},{13056, 2785},
- {13693, 2793},{14288, 2805},{14843, 2814},{15361, 2821},
- {15857, 2827},{16328, 2831},{16763, 2834},{17171, 2838},
- {17568, 2840},{17941, 2842},{18285, 2843},{18586, 2839}
+ /*Y' qi=27 INTER*/
+ {
+ { -2, 172},{ 31, 1347},{ 117, 2488},{ 245, 3651},
+ { 448, 4719},{ 668, 5679},{ 918, 6524},{ 1204, 7255},
+ { 1557, 7848},{ 1998, 8281},{ 2511, 8531},{ 3055, 8642},
+ { 3582, 8648},{ 4062, 8611},{ 4482, 8582},{ 4845, 8560},
+ { 5140, 8560},{ 5423, 8581},{ 5645, 8596},{ 5855, 8586},
+ { 6061, 8608},{ 6211, 8558},{ 6402, 8583},{ 6472, 8575}
}
},
{
- /*Cb qi=59 INTRA*/
- {
- { 17, 3},{ 224, 363},{ 441, 696},{ 689, 982},
- { 945, 1222},{ 1204, 1416},{ 1474, 1571},{ 1751, 1695},
- { 2001, 1816},{ 2228, 1941},{ 2453, 2055},{ 2693, 2147},
- { 2924, 2227},{ 3125, 2321},{ 3321, 2416},{ 3510, 2520},
- { 3676, 2616},{ 3839, 2699},{ 4008, 2778},{ 4193, 2842},
- { 4371, 2898},{ 4535, 2965},{ 4710, 3023},{ 4921, 3068}
+ /*Cb qi=27 INTRA*/
+ {
+ { 47, 49},{ 35, 580},{ 64, 778},{ 69, 1071},
+ { 98, 1289},{ 186, 1556},{ 177, 1654},{ 197, 1736},
+ { 211, 1373},{ 284, 1742},{ 321, 1840},{ 344, 2024},
+ { 321, 1969},{ 386, 2254},{ 397, 2281},{ 425, 2320},
+ { 396, 2088},{ 448, 2284},{ 462, 2213},{ 482, 2274},
+ { 410, 1894},{ 513, 2310},{ 546, 2332},{ 549, 2334}
},
- /*Cb qi=59 INTER*/
- {
- { 95, -5},{ 111, 343},{ 112, 664},{ 157, 995},
- { 258, 1302},{ 429, 1569},{ 691, 1790},{ 1017, 1977},
- { 1387, 2148},{ 1832, 2294},{ 2368, 2401},{ 2961, 2472},
- { 3553, 2518},{ 4133, 2545},{ 4688, 2557},{ 5198, 2563},
- { 5663, 2574},{ 6100, 2590},{ 6511, 2608},{ 6898, 2621},
- { 7274, 2634},{ 7631, 2655},{ 7984, 2669},{ 8361, 2669}
+ /*Cb qi=27 INTER*/
+ {
+ { 11, 145},{ 5, 539},{ 11, 771},{ 0, 1033},
+ { 9, 1334},{ 44, 1644},{ 70, 1934},{ 87, 2227},
+ { 96, 2508},{ 113, 2812},{ 139, 3085},{ 174, 3352},
+ { 216, 3614},{ 261, 3873},{ 305, 4123},{ 349, 4372},
+ { 396, 4611},{ 442, 4853},{ 493, 5088},{ 543, 5313},
+ { 600, 5537},{ 662, 5752},{ 737, 6018},{ 775, 6037}
}
},
{
- /*Cr qi=59 INTRA*/
- {
- { 31, 8},{ 240, 379},{ 480, 706},{ 748, 978},
- { 993, 1208},{ 1250, 1394},{ 1519, 1543},{ 1779, 1674},
- { 2047, 1792},{ 2307, 1904},{ 2552, 2013},{ 2780, 2116},
- { 2973, 2216},{ 3165, 2309},{ 3362, 2383},{ 3528, 2444},
- { 3677, 2499},{ 3841, 2566},{ 3995, 2646},{ 4139, 2720},
- { 4324, 2793},{ 4504, 2867},{ 4658, 2939},{ 4806, 2975}
+ /*Cr qi=27 INTRA*/
+ {
+ { 49, 52},{ 57, 570},{ 61, 762},{ 44, 1048},
+ { 80, 1291},{ 196, 1513},{ 224, 1522},{ 242, 1532},
+ { 213, 1293},{ 260, 1639},{ 253, 1691},{ 291, 1915},
+ { 294, 1897},{ 367, 2178},{ 395, 2258},{ 432, 2310},
+ { 407, 2105},{ 503, 2369},{ 492, 2293},{ 552, 2421},
+ { 496, 2099},{ 598, 2549},{ 624, 2531},{ 627, 2532}
},
- /*Cr qi=59 INTER*/
- {
- { 89, -3},{ 98, 352},{ 103, 674},{ 156, 1002},
- { 268, 1300},{ 441, 1562},{ 673, 1801},{ 980, 2010},
- { 1385, 2175},{ 1868, 2301},{ 2401, 2402},{ 2984, 2474},
- { 3591, 2520},{ 4179, 2545},{ 4729, 2555},{ 5232, 2553},
- { 5679, 2545},{ 6081, 2530},{ 6447, 2510},{ 6791, 2496},
- { 7101, 2487},{ 7393, 2489},{ 7684, 2499},{ 7950, 2501}
+ /*Cr qi=27 INTER*/
+ {
+ { 10, 147},{ 4, 538},{ 11, 769},{ 0, 1022},
+ { 9, 1318},{ 51, 1635},{ 80, 1925},{ 97, 2214},
+ { 101, 2493},{ 115, 2805},{ 143, 3083},{ 182, 3361},
+ { 226, 3625},{ 270, 3898},{ 319, 4157},{ 366, 4405},
+ { 418, 4649},{ 467, 4904},{ 509, 5157},{ 548, 5412},
+ { 589, 5659},{ 636, 5909},{ 683, 6208},{ 710, 6190}
}
}
},
{
{
- /*Y' qi=60 INTRA*/
- {
- { 92, 116},{ 1361, 1085},{ 2746, 1686},{ 4050, 1895},
- { 5209, 1939},{ 6244, 2012},{ 7213, 2103},{ 8105, 2197},
- { 8928, 2290},{ 9685, 2381},{10371, 2460},{10952, 2511},
- {11487, 2556},{12026, 2611},{12574, 2674},{13102, 2739},
- {13597, 2793},{14092, 2831},{14523, 2862},{14862, 2881},
- {15198, 2897},{15568, 2923},{15949, 2941},{16416, 2964}
+ /*Y' qi=36 INTRA*/
+ {
+ { 86, 252},{ 345, 662},{ 476, 1143},{ 698, 1169},
+ { 894, 1457},{ 1218, 1728},{ 1465, 1849},{ 1731, 2019},
+ { 2183, 2298},{ 2666, 2511},{ 3116, 2731},{ 3371, 2813},
+ { 3621, 2923},{ 3675, 2949},{ 3710, 2921},{ 3740, 2896},
+ { 3746, 2895},{ 3886, 2978},{ 4069, 2991},{ 4229, 3016},
+ { 4338, 3102},{ 4530, 3124},{ 4751, 3248},{ 4753, 3244}
},
- /*Y' qi=60 INTER*/
- {
- { 4, 30},{ 215, 1287},{ 1547, 2104},{ 3729, 2491},
- { 5973, 2568},{ 7672, 2577},{ 9001, 2591},{10123, 2606},
- {11094, 2620},{11943, 2632},{12709, 2643},{13409, 2652},
- {14044, 2660},{14641, 2669},{15193, 2677},{15709, 2684},
- {16201, 2689},{16675, 2693},{17118, 2696},{17522, 2701},
- {17920, 2704},{18293, 2706},{18620, 2702},{18923, 2700}
+ /*Y' qi=36 INTER*/
+ {
+ { 0, 208},{ 73, 1293},{ 248, 2449},{ 616, 3461},
+ { 1061, 4329},{ 1601, 4986},{ 2189, 5447},{ 2875, 5723},
+ { 3620, 5844},{ 4328, 5879},{ 4954, 5880},{ 5490, 5890},
+ { 5934, 5901},{ 6353, 5926},{ 6706, 5924},{ 7036, 5930},
+ { 7338, 5938},{ 7600, 5930},{ 7870, 5939},{ 8065, 5921},
+ { 8318, 5914},{ 8451, 5912},{ 8648, 5923},{ 8734, 5926}
}
},
{
- /*Cb qi=60 INTRA*/
- {
- { 18, 3},{ 227, 362},{ 447, 694},{ 708, 974},
- { 981, 1207},{ 1252, 1397},{ 1532, 1547},{ 1822, 1663},
- { 2082, 1780},{ 2316, 1903},{ 2548, 2013},{ 2794, 2101},
- { 3029, 2178},{ 3242, 2266},{ 3445, 2360},{ 3638, 2459},
- { 3816, 2547},{ 3980, 2628},{ 4146, 2708},{ 4344, 2766},
- { 4546, 2812},{ 4725, 2872},{ 4880, 2930},{ 5054, 2966}
+ /*Cb qi=36 INTRA*/
+ {
+ { 52, 54},{ 52, 575},{ 103, 776},{ 185, 1072},
+ { 172, 1069},{ 211, 1302},{ 217, 1413},{ 285, 1586},
+ { 330, 1463},{ 453, 1694},{ 500, 1741},{ 545, 1852},
+ { 501, 1650},{ 584, 1874},{ 587, 1856},{ 638, 1919},
+ { 581, 1742},{ 670, 1953},{ 688, 1934},{ 731, 2030},
+ { 637, 1794},{ 806, 2123},{ 840, 2091},{ 843, 2091}
},
- /*Cb qi=60 INTER*/
- {
- { 97, -4},{ 112, 343},{ 114, 664},{ 162, 993},
- { 273, 1294},{ 472, 1553},{ 774, 1762},{ 1138, 1939},
- { 1543, 2102},{ 2034, 2236},{ 2620, 2329},{ 3244, 2389},
- { 3860, 2423},{ 4443, 2440},{ 4997, 2449},{ 5502, 2455},
- { 5962, 2458},{ 6413, 2466},{ 6836, 2485},{ 7217, 2506},
- { 7592, 2518},{ 7957, 2533},{ 8291, 2543},{ 8574, 2545}
+ /*Cb qi=36 INTER*/
+ {
+ { 19, 142},{ 17, 534},{ 6, 772},{ 44, 1023},
+ { 82, 1296},{ 94, 1614},{ 117, 1903},{ 158, 2187},
+ { 218, 2450},{ 285, 2703},{ 352, 2943},{ 421, 3181},
+ { 489, 3415},{ 564, 3644},{ 647, 3861},{ 748, 4060},
+ { 861, 4246},{ 993, 4419},{ 1132, 4576},{ 1282, 4744},
+ { 1445, 4894},{ 1600, 5034},{ 1782, 5211},{ 1837, 5200}
}
},
{
- /*Cr qi=60 INTRA*/
- {
- { 32, 8},{ 243, 379},{ 488, 702},{ 771, 968},
- { 1030, 1192},{ 1300, 1373},{ 1581, 1517},{ 1854, 1643},
- { 2127, 1757},{ 2393, 1864},{ 2645, 1968},{ 2879, 2068},
- { 3078, 2166},{ 3277, 2256},{ 3484, 2325},{ 3660, 2381},
- { 3808, 2433},{ 3970, 2496},{ 4138, 2571},{ 4288, 2643},
- { 4475, 2710},{ 4655, 2778},{ 4810, 2843},{ 4959, 2879}
+ /*Cr qi=36 INTRA*/
+ {
+ { 62, 55},{ 90, 561},{ 56, 767},{ 148, 1014},
+ { 207, 981},{ 258, 1216},{ 273, 1253},{ 326, 1392},
+ { 338, 1383},{ 417, 1613},{ 443, 1629},{ 497, 1734},
+ { 466, 1525},{ 561, 1778},{ 577, 1787},{ 631, 1892},
+ { 591, 1706},{ 715, 1980},{ 730, 1958},{ 822, 2113},
+ { 755, 1935},{ 928, 2228},{ 935, 2205},{ 938, 2205}
},
- /*Cr qi=60 INTER*/
- {
- { 86, -2},{ 99, 352},{ 103, 673},{ 160, 998},
- { 284, 1292},{ 484, 1546},{ 753, 1774},{ 1100, 1973},
- { 1546, 2129},{ 2072, 2246},{ 2652, 2334},{ 3279, 2392},
- { 3911, 2425},{ 4504, 2440},{ 5044, 2443},{ 5536, 2440},
- { 5979, 2430},{ 6381, 2413},{ 6735, 2397},{ 7062, 2382},
- { 7383, 2376},{ 7680, 2375},{ 7962, 2373},{ 8203, 2379}
+ /*Cr qi=36 INTER*/
+ {
+ { 14, 145},{ 16, 535},{ 5, 772},{ 44, 1017},
+ { 91, 1296},{ 100, 1605},{ 122, 1891},{ 163, 2174},
+ { 225, 2443},{ 294, 2707},{ 362, 2962},{ 436, 3210},
+ { 518, 3437},{ 607, 3664},{ 702, 3876},{ 795, 4094},
+ { 886, 4310},{ 980, 4538},{ 1089, 4749},{ 1216, 4927},
+ { 1357, 5116},{ 1506, 5247},{ 1758, 5338},{ 1787, 5306}
}
}
},
{
{
- /*Y' qi=61 INTRA*/
- {
- { 54, 121},{ 1477, 1069},{ 3061, 1638},{ 4465, 1808},
- { 5649, 1827},{ 6710, 1884},{ 7716, 1958},{ 8648, 2037},
- { 9514, 2116},{10311, 2192},{11033, 2261},{11641, 2305},
- {12202, 2342},{12771, 2387},{13356, 2440},{13924, 2493},
- {14444, 2541},{14951, 2576},{15409, 2600},{15779, 2615},
- {16131, 2626},{16521, 2648},{16921, 2663},{17409, 2694}
+ /*Y' qi=45 INTRA*/
+ {
+ { 185, 246},{ 513, 647},{ 883, 891},{ 1313, 1142},
+ { 1760, 1351},{ 2368, 1595},{ 2828, 1718},{ 3097, 1780},
+ { 3762, 1951},{ 4454, 2121},{ 4986, 2227},{ 5281, 2281},
+ { 5477, 2299},{ 5431, 2288},{ 5425, 2283},{ 5439, 2290},
+ { 5324, 2249},{ 5509, 2279},{ 5703, 2321},{ 5896, 2348},
+ { 6049, 2370},{ 6253, 2425},{ 6415, 2432},{ 6419, 2430}
},
- /*Y' qi=61 INTER*/
- {
- { -1, 32},{ 216, 1286},{ 1806, 2036},{ 4279, 2327},
- { 6629, 2352},{ 8347, 2352},{ 9707, 2357},{10860, 2364},
- {11857, 2372},{12726, 2377},{13508, 2382},{14225, 2387},
- {14877, 2392},{15484, 2398},{16048, 2401},{16581, 2405},
- {17092, 2409},{17573, 2409},{18016, 2410},{18427, 2413},
- {18829, 2415},{19221, 2415},{19578, 2415},{19980, 2413}
+ /*Y' qi=45 INTER*/
+ {
+ { 6, 215},{ 152, 1261},{ 691, 2314},{ 1538, 3095},
+ { 2505, 3632},{ 3475, 3935},{ 4355, 4084},{ 5209, 4139},
+ { 5985, 4162},{ 6644, 4185},{ 7235, 4190},{ 7768, 4196},
+ { 8266, 4200},{ 8736, 4210},{ 9143, 4207},{ 9511, 4215},
+ { 9828, 4209},{10112, 4224},{10374, 4226},{10642, 4232},
+ {10842, 4219},{10971, 4208},{11200, 4211},{11299, 4216}
}
},
{
- /*Cb qi=61 INTRA*/
- {
- { 19, 3},{ 231, 362},{ 456, 693},{ 733, 965},
- { 1032, 1188},{ 1330, 1369},{ 1637, 1508},{ 1956, 1612},
- { 2241, 1718},{ 2496, 1832},{ 2750, 1932},{ 3019, 2007},
- { 3274, 2074},{ 3505, 2154},{ 3725, 2236},{ 3943, 2323},
- { 4138, 2403},{ 4323, 2476},{ 4505, 2543},{ 4706, 2592},
- { 4909, 2630},{ 5109, 2675},{ 5292, 2724},{ 5495, 2768}
+ /*Cb qi=45 INTRA*/
+ {
+ { 58, 71},{ 66, 548},{ 155, 762},{ 213, 944},
+ { 192, 731},{ 324, 1147},{ 401, 1366},{ 481, 1480},
+ { 508, 1238},{ 657, 1522},{ 727, 1563},{ 794, 1611},
+ { 761, 1470},{ 885, 1710},{ 893, 1700},{ 958, 1760},
+ { 893, 1543},{ 985, 1719},{ 1014, 1732},{ 1082, 1784},
+ { 963, 1519},{ 1152, 1800},{ 1221, 1830},{ 1226, 1830}
},
- /*Cb qi=61 INTER*/
- {
- { 91, -2},{ 111, 344},{ 114, 663},{ 166, 989},
- { 291, 1285},{ 522, 1534},{ 875, 1729},{ 1302, 1889},
- { 1786, 2031},{ 2368, 2141},{ 3042, 2207},{ 3734, 2243},
- { 4388, 2259},{ 4982, 2264},{ 5533, 2265},{ 6043, 2262},
- { 6524, 2264},{ 6982, 2274},{ 7422, 2283},{ 7831, 2295},
- { 8198, 2308},{ 8593, 2319},{ 8965, 2329},{ 9258, 2340}
+ /*Cb qi=45 INTER*/
+ {
+ { 35, 135},{ 12, 532},{ 54, 769},{ 106, 1007},
+ { 127, 1258},{ 198, 1565},{ 289, 1832},{ 398, 2082},
+ { 520, 2302},{ 653, 2511},{ 800, 2705},{ 956, 2897},
+ { 1143, 3064},{ 1358, 3220},{ 1623, 3335},{ 1913, 3444},
+ { 2198, 3534},{ 2502, 3626},{ 2787, 3711},{ 3114, 3783},
+ { 3454, 3831},{ 3711, 3871},{ 4163, 3901},{ 4221, 3890}
}
},
{
- /*Cr qi=61 INTRA*/
- {
- { 33, 9},{ 245, 378},{ 497, 699},{ 801, 958},
- { 1087, 1171},{ 1384, 1342},{ 1692, 1474},{ 1992, 1589},
- { 2290, 1692},{ 2576, 1789},{ 2852, 1884},{ 3109, 1973},
- { 3324, 2061},{ 3544, 2142},{ 3763, 2199},{ 3945, 2244},
- { 4103, 2292},{ 4283, 2349},{ 4469, 2413},{ 4635, 2476},
- { 4836, 2534},{ 5038, 2592},{ 5210, 2649},{ 5358, 2682}
+ /*Cr qi=45 INTRA*/
+ {
+ { 93, 68},{ 72, 541},{ 154, 769},{ 239, 848},
+ { 214, 623},{ 377, 1060},{ 437, 1200},{ 514, 1280},
+ { 512, 1160},{ 625, 1453},{ 657, 1470},{ 718, 1516},
+ { 692, 1331},{ 831, 1617},{ 875, 1609},{ 944, 1678},
+ { 886, 1469},{ 1061, 1699},{ 1082, 1714},{ 1226, 1823},
+ { 1113, 1581},{ 1324, 1872},{ 1370, 1925},{ 1374, 1924}
},
- /*Cr qi=61 INTER*/
- {
- { 82, 0},{ 97, 353},{ 104, 672},{ 165, 995},
- { 303, 1284},{ 532, 1529},{ 852, 1742},{ 1273, 1921},
- { 1798, 2057},{ 2409, 2154},{ 3090, 2212},{ 3794, 2240},
- { 4460, 2251},{ 5057, 2249},{ 5596, 2249},{ 6085, 2245},
- { 6519, 2234},{ 6908, 2220},{ 7269, 2203},{ 7618, 2196},
- { 7949, 2198},{ 8269, 2195},{ 8554, 2196},{ 8928, 2217}
+ /*Cr qi=45 INTER*/
+ {
+ { 31, 140},{ 13, 533},{ 52, 770},{ 109, 1000},
+ { 134, 1253},{ 201, 1555},{ 298, 1821},{ 411, 2076},
+ { 525, 2314},{ 659, 2545},{ 828, 2747},{ 1019, 2918},
+ { 1205, 3082},{ 1405, 3266},{ 1609, 3443},{ 1847, 3606},
+ { 2085, 3730},{ 2404, 3835},{ 2709, 3876},{ 3049, 3886},
+ { 3381, 3821},{ 3708, 3780},{ 4026, 3663},{ 4043, 3646}
}
}
},
{
{
- /*Y' qi=62 INTRA*/
- {
- { 29, 124},{ 1527, 1067},{ 3221, 1618},{ 4703, 1751},
- { 5909, 1744},{ 7001, 1779},{ 8057, 1829},{ 9049, 1885},
- { 9968, 1943},{10813, 1999},{11572, 2050},{12206, 2082},
- {12801, 2107},{13402, 2140},{14020, 2180},{14625, 2223},
- {15179, 2260},{15718, 2288},{16196, 2305},{16581, 2313},
- {16963, 2324},{17382, 2341},{17800, 2351},{18318, 2376}
+ /*Y' qi=54 INTRA*/
+ {
+ { 316, 203},{ 720, 585},{ 1596, 1077},{ 2316, 1289},
+ { 2687, 1439},{ 3133, 1593},{ 3495, 1706},{ 3836, 1775},
+ { 4249, 1892},{ 4804, 2031},{ 5320, 2139},{ 5617, 2203},
+ { 5726, 2199},{ 5726, 2176},{ 5682, 2146},{ 5677, 2127},
+ { 5717, 2124},{ 5707, 2129},{ 5853, 2148},{ 6110, 2180},
+ { 6454, 2247},{ 6714, 2287},{ 6845, 2304},{ 6854, 2303}
},
- /*Y' qi=62 INTER*/
- {
- { -8, 36},{ 218, 1284},{ 2073, 1965},{ 4814, 2159},
- { 7237, 2138},{ 8979, 2124},{10378, 2115},{11570, 2109},
- {12601, 2106},{13503, 2103},{14320, 2103},{15064, 2103},
- {15746, 2103},{16384, 2104},{16975, 2105},{17534, 2105},
- {18062, 2106},{18564, 2107},{19035, 2106},{19471, 2107},
- {19890, 2107},{20288, 2107},{20651, 2107},{21012, 2108}
+ /*Y' qi=54 INTER*/
+ {
+ { -48, 217},{ 314, 1261},{ 1450, 2126},{ 2761, 2728},
+ { 4275, 3012},{ 5408, 3167},{ 6305, 3245},{ 7165, 3290},
+ { 7966, 3325},{ 8698, 3359},{ 9352, 3377},{ 9907, 3391},
+ {10389, 3390},{10856, 3395},{11170, 3385},{11530, 3385},
+ {11780, 3362},{12018, 3362},{12266, 3361},{12443, 3339},
+ {12683, 3342},{12713, 3317},{12967, 3325},{13082, 3332}
}
},
{
- /*Cb qi=62 INTRA*/
- {
- { 21, 3},{ 283, 360},{ 565, 683},{ 907, 938},
- { 1269, 1143},{ 1611, 1311},{ 1949, 1441},{ 2290, 1535},
- { 2596, 1632},{ 2877, 1738},{ 3162, 1828},{ 3458, 1893},
- { 3745, 1948},{ 4011, 2016},{ 4253, 2089},{ 4506, 2164},
- { 4734, 2233},{ 4943, 2294},{ 5162, 2353},{ 5381, 2393},
- { 5593, 2420},{ 5807, 2454},{ 6003, 2496},{ 6210, 2543}
+ /*Cb qi=54 INTRA*/
+ {
+ { 94, 73},{ 83, 557},{ 152, 818},{ 304, 919},
+ { 341, 819},{ 506, 1128},{ 593, 1281},{ 700, 1389},
+ { 714, 1225},{ 907, 1502},{ 981, 1549},{ 1062, 1641},
+ { 1032, 1523},{ 1170, 1710},{ 1217, 1727},{ 1258, 1714},
+ { 1216, 1575},{ 1309, 1682},{ 1331, 1656},{ 1393, 1712},
+ { 1247, 1456},{ 1469, 1728},{ 1530, 1711},{ 1532, 1711}
},
- /*Cb qi=62 INTER*/
- {
- { 91, -1},{ 110, 344},{ 113, 663},{ 169, 987},
- { 306, 1279},{ 562, 1519},{ 961, 1701},{ 1450, 1845},
- { 2013, 1967},{ 2686, 2053},{ 3437, 2095},{ 4171, 2109},
- { 4841, 2109},{ 5441, 2105},{ 6002, 2097},{ 6542, 2089},
- { 7028, 2087},{ 7491, 2088},{ 7949, 2090},{ 8377, 2089},
- { 8789, 2095},{ 9195, 2103},{ 9569, 2104},{ 9937, 2102}
+ /*Cb qi=54 INTER*/
+ {
+ { 33, 133},{ 12, 532},{ 70, 770},{ 171, 996},
+ { 279, 1233},{ 427, 1503},{ 600, 1736},{ 824, 1939},
+ { 1101, 2097},{ 1411, 2237},{ 1735, 2374},{ 2097, 2493},
+ { 2486, 2606},{ 2916, 2691},{ 3297, 2771},{ 3715, 2826},
+ { 4088, 2855},{ 4460, 2886},{ 4849, 2911},{ 5198, 2932},
+ { 5489, 2940},{ 5875, 2981},{ 6208, 3017},{ 6270, 3012}
}
},
{
- /*Cr qi=62 INTRA*/
- {
- { 38, 8},{ 308, 374},{ 619, 685},{ 984, 925},
- { 1326, 1126},{ 1662, 1285},{ 1999, 1407},{ 2328, 1512},
- { 2659, 1604},{ 2976, 1691},{ 3285, 1774},{ 3570, 1853},
- { 3815, 1931},{ 4068, 1998},{ 4304, 2044},{ 4491, 2082},
- { 4666, 2124},{ 4870, 2174},{ 5078, 2231},{ 5262, 2285},
- { 5480, 2335},{ 5703, 2378},{ 5905, 2423},{ 6075, 2454}
+ /*Cr qi=54 INTRA*/
+ {
+ { 103, 63},{ 83, 580},{ 258, 796},{ 301, 802},
+ { 361, 675},{ 538, 1001},{ 625, 1097},{ 713, 1171},
+ { 699, 1103},{ 868, 1380},{ 915, 1400},{ 970, 1491},
+ { 923, 1365},{ 1070, 1603},{ 1154, 1655},{ 1206, 1677},
+ { 1157, 1541},{ 1366, 1736},{ 1391, 1723},{ 1506, 1797},
+ { 1388, 1556},{ 1616, 1828},{ 1655, 1797},{ 1658, 1796}
},
- /*Cr qi=62 INTER*/
- {
- { 79, 1},{ 95, 353},{ 102, 671},{ 169, 992},
- { 318, 1277},{ 569, 1515},{ 936, 1716},{ 1428, 1876},
- { 2034, 1993},{ 2738, 2067},{ 3511, 2095},{ 4268, 2094},
- { 4943, 2087},{ 5543, 2079},{ 6074, 2074},{ 6552, 2069},
- { 6985, 2057},{ 7366, 2043},{ 7728, 2030},{ 8086, 2021},
- { 8423, 2017},{ 8752, 2016},{ 9057, 2014},{ 9376, 2008}
+ /*Cr qi=54 INTER*/
+ {
+ { 30, 138},{ 14, 532},{ 63, 771},{ 176, 990},
+ { 299, 1226},{ 438, 1496},{ 606, 1735},{ 814, 1950},
+ { 1089, 2127},{ 1417, 2281},{ 1761, 2421},{ 2104, 2571},
+ { 2467, 2701},{ 2881, 2827},{ 3303, 2900},{ 3735, 2917},
+ { 4183, 2913},{ 4529, 2882},{ 4915, 2844},{ 5168, 2796},
+ { 5410, 2763},{ 5562, 2753},{ 5815, 2764},{ 5832, 2755}
}
}
},
@@ -3964,61 +967,61 @@ oc_mode_rd OC_MODE_RD[64][3][2][OC_SAD_BINS]={
{
/*Y' qi=63 INTRA*/
{
- { -59, 134},{ 1734, 1036},{ 3743, 1521},{ 5309, 1618},
- { 6520, 1597},{ 7664, 1609},{ 8809, 1630},{ 9894, 1657},
- {10907, 1687},{11838, 1717},{12673, 1744},{13379, 1758},
- {14038, 1767},{14698, 1784},{15379, 1806},{16062, 1831},
- {16694, 1852},{17300, 1867},{17827, 1878},{18250, 1881},
- {18702, 1884},{19199, 1892},{19665, 1896},{20273, 1908}
+ { 421, 194},{ 1272, 564},{ 3016, 943},{ 3831, 1079},
+ { 4282, 1174},{ 4799, 1290},{ 5166, 1348},{ 5259, 1350},
+ { 5720, 1426},{ 6501, 1539},{ 7048, 1606},{ 7328, 1642},
+ { 7374, 1622},{ 7349, 1612},{ 7192, 1578},{ 7207, 1571},
+ { 7161, 1555},{ 7259, 1573},{ 7432, 1592},{ 7710, 1613},
+ { 8167, 1672},{ 8425, 1697},{ 8597, 1710},{ 8602, 1710}
},
/*Y' qi=63 INTER*/
{
- { -7, 33},{ 209, 1285},{ 2309, 1904},{ 5274, 2025},
- { 7801, 1966},{ 9637, 1924},{11126, 1892},{12403, 1868},
- {13515, 1849},{14491, 1834},{15380, 1822},{16197, 1814},
- {16944, 1806},{17645, 1799},{18303, 1794},{18916, 1789},
- {19494, 1785},{20056, 1782},{20568, 1779},{21047, 1776},
- {21508, 1775},{21925, 1772},{22327, 1770},{22678, 1771}
+ { -584, 286},{ 1231, 1186},{ 3939, 1663},{ 6096, 1865},
+ { 7849, 1929},{ 8934, 1995},{ 9962, 2039},{11038, 2078},
+ {12016, 2092},{12889, 2100},{13617, 2096},{14221, 2089},
+ {14743, 2083},{15240, 2081},{15619, 2074},{15992, 2065},
+ {16314, 2065},{16529, 2059},{16822, 2056},{17041, 2049},
+ {17321, 2052},{17408, 2043},{17670, 2051},{17801, 2053}
}
},
{
/*Cb qi=63 INTRA*/
{
- { 20, 3},{ 294, 357},{ 608, 673},{ 1047, 908},
- { 1501, 1090},{ 1898, 1240},{ 2275, 1353},{ 2654, 1427},
- { 3014, 1502},{ 3366, 1579},{ 3726, 1637},{ 4084, 1674},
- { 4425, 1703},{ 4752, 1743},{ 5058, 1791},{ 5377, 1838},
- { 5676, 1877},{ 5946, 1912},{ 6213, 1945},{ 6458, 1969},
- { 6704, 1982},{ 6969, 1997},{ 7210, 2017},{ 7439, 2037}
+ { 154, 55},{ 280, 582},{ 507, 731},{ 788, 853},
+ { 763, 738},{ 1141, 1008},{ 1323, 1090},{ 1540, 1220},
+ { 1487, 1089},{ 1861, 1322},{ 1983, 1347},{ 2145, 1425},
+ { 2047, 1317},{ 2334, 1475},{ 2352, 1413},{ 2458, 1467},
+ { 2243, 1270},{ 2464, 1413},{ 2423, 1335},{ 2506, 1385},
+ { 2182, 1180},{ 2565, 1376},{ 2555, 1321},{ 2557, 1321}
},
/*Cb qi=63 INTER*/
{
- { 86, 1},{ 108, 345},{ 111, 663},{ 168, 985},
- { 307, 1276},{ 577, 1513},{ 1007, 1688},{ 1550, 1819},
- { 2189, 1921},{ 2938, 1981},{ 3744, 2002},{ 4512, 2002},
- { 5199, 1996},{ 5824, 1986},{ 6419, 1971},{ 6978, 1954},
- { 7507, 1940},{ 8015, 1932},{ 8502, 1928},{ 8978, 1920},
- { 9410, 1915},{ 9842, 1910},{10262, 1901},{10634, 1896}
+ { 34, 133},{ 6, 531},{ 139, 767},{ 344, 975},
+ { 608, 1180},{ 1048, 1367},{ 1651, 1495},{ 2376, 1572},
+ { 3103, 1609},{ 3752, 1646},{ 4373, 1680},{ 4980, 1718},
+ { 5540, 1744},{ 6023, 1764},{ 6431, 1766},{ 6800, 1769},
+ { 7149, 1775},{ 7529, 1777},{ 7920, 1817},{ 8198, 1808},
+ { 8691, 1848},{ 8965, 1845},{ 9372, 1865},{ 9459, 1863}
}
},
{
/*Cr qi=63 INTRA*/
{
- { 38, 7},{ 324, 367},{ 677, 670},{ 1136, 892},
- { 1562, 1070},{ 1951, 1209},{ 2326, 1313},{ 2694, 1399},
- { 3074, 1471},{ 3460, 1531},{ 3850, 1575},{ 4214, 1622},
- { 4522, 1679},{ 4819, 1723},{ 5089, 1749},{ 5315, 1769},
- { 5530, 1792},{ 5756, 1825},{ 6006, 1860},{ 6244, 1889},
- { 6514, 1924},{ 6792, 1946},{ 7026, 1962},{ 7191, 1971}
+ { 121, 59},{ 392, 570},{ 609, 654},{ 800, 760},
+ { 720, 598},{ 1192, 892},{ 1298, 897},{ 1470, 1027},
+ { 1411, 962},{ 1761, 1184},{ 1826, 1197},{ 1981, 1308},
+ { 1854, 1198},{ 2229, 1427},{ 2269, 1365},{ 2428, 1453},
+ { 2217, 1265},{ 2558, 1435},{ 2541, 1356},{ 2660, 1417},
+ { 2337, 1199},{ 2688, 1382},{ 2603, 1301},{ 2605, 1300}
},
/*Cr qi=63 INTER*/
{
- { 80, 2},{ 95, 354},{ 101, 671},{ 167, 990},
- { 321, 1274},{ 585, 1509},{ 984, 1702},{ 1534, 1849},
- { 2217, 1947},{ 3005, 1995},{ 3839, 1999},{ 4619, 1986},
- { 5310, 1973},{ 5933, 1961},{ 6486, 1952},{ 6988, 1942},
- { 7435, 1927},{ 7817, 1911},{ 8198, 1900},{ 8552, 1895},
- { 8881, 1890},{ 9253, 1883},{ 9598, 1876},{ 9923, 1859}
+ { 31, 137},{ 10, 531},{ 136, 768},{ 360, 971},
+ { 638, 1166},{ 1029, 1373},{ 1604, 1519},{ 2351, 1595},
+ { 3129, 1640},{ 3861, 1691},{ 4491, 1751},{ 5101, 1783},
+ { 5635, 1784},{ 6136, 1779},{ 6550, 1763},{ 6905, 1746},
+ { 7172, 1726},{ 7495, 1732},{ 7738, 1735},{ 7949, 1735},
+ { 8211, 1744},{ 8424, 1740},{ 8779, 1764},{ 8812, 1760}
}
}
}
diff --git a/thirdparty/libtheora/ocintrin.h b/thirdparty/libtheora/ocintrin.h
index d49ebb2159..b200ceafce 100644
--- a/thirdparty/libtheora/ocintrin.h
+++ b/thirdparty/libtheora/ocintrin.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: ocintrin.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch b/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch
deleted file mode 100644
index 1b9c8e20be..0000000000
--- a/thirdparty/libtheora/patches/theora.git-0ae66d565e6bead8604d312bc1a4e9dccf245c88.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 0ae66d565e6bead8604d312bc1a4e9dccf245c88 Mon Sep 17 00:00:00 2001
-From: Tim Terriberry <tterribe@xiph.org>
-Date: Tue, 8 May 2012 02:51:57 +0000
-Subject: [PATCH] Fix pp_sharp_mod calculation.
-
-This was broken when the dequant_tables indexing changed in commit
- r16102, but it only affected post-processing quality, so we never
- noticed.
-With gcc 4.8.0, this can now trigger a segfault during decoder
- initialization.
-
-svn path=/trunk/theora/; revision=18268
----
- decode.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/decode.c b/decode.c
-index b803505..9f2516a 100644
---- a/decode.c
-+++ b/decode.c
-@@ -400,10 +400,10 @@ static int oc_dec_init(oc_dec_ctx *_dec,const th_info *_info,
- int qsum;
- qsum=0;
- for(qti=0;qti<2;qti++)for(pli=0;pli<3;pli++){
-- qsum+=_dec->state.dequant_tables[qti][pli][qi][12]+
-- _dec->state.dequant_tables[qti][pli][qi][17]+
-- _dec->state.dequant_tables[qti][pli][qi][18]+
-- _dec->state.dequant_tables[qti][pli][qi][24]<<(pli==0);
-+ qsum+=_dec->state.dequant_tables[qi][pli][qti][12]+
-+ _dec->state.dequant_tables[qi][pli][qti][17]+
-+ _dec->state.dequant_tables[qi][pli][qti][18]+
-+ _dec->state.dequant_tables[qi][pli][qti][24]<<(pli==0);
- }
- _dec->pp_sharp_mod[qi]=-(qsum>>11);
- }
---
-2.11.0
-
diff --git a/thirdparty/libtheora/quant.c b/thirdparty/libtheora/quant.c
index 8359f5abea..e206202844 100644
--- a/thirdparty/libtheora/quant.c
+++ b/thirdparty/libtheora/quant.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: quant.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -21,6 +21,14 @@
#include "quant.h"
#include "decint.h"
+/*The maximum output of the DCT with +/- 255 inputs is +/- 8157.
+ These minimum quantizers ensure the result after quantization (and after
+ prediction for DC) will be no more than +/- 510.
+ The tokenization system can handle values up to +/- 580, so there is no need
+ to do any coefficient clamping.
+ I would rather have allowed smaller quantizers and had to clamp, but these
+ minimums were required when constructing the original VP3 matrices and have
+ been formalized in the spec.*/
static const unsigned OC_DC_QUANT_MIN[2]={4<<2,8<<2};
static const unsigned OC_AC_QUANT_MIN[2]={2<<2,4<<2};
diff --git a/thirdparty/libtheora/quant.h b/thirdparty/libtheora/quant.h
index 49ce13a65c..247210eaae 100644
--- a/thirdparty/libtheora/quant.h
+++ b/thirdparty/libtheora/quant.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: quant.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
diff --git a/thirdparty/libtheora/rate.c b/thirdparty/libtheora/rate.c
index 4f43bb2e5f..bf2b1396a1 100644
--- a/thirdparty/libtheora/rate.c
+++ b/thirdparty/libtheora/rate.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: rate.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -190,7 +190,8 @@ void oc_enc_calc_lambda(oc_enc_ctx *_enc,int _qti){
This may need to be revised if the R-D cost estimation or qii flag
optimization strategies change.*/
nqis=1;
- if(lq<(OC_Q57(56)>>3)&&!_enc->vp3_compatible){
+ if(lq<(OC_Q57(56)>>3)&&!_enc->vp3_compatible&&
+ _enc->sp_level<OC_SP_LEVEL_FAST_ANALYSIS){
qi1=oc_enc_find_qi_for_target(_enc,_qti,OC_MAXI(qi-1,0),0,
lq+(OC_Q57(7)+5)/10);
if(qi1!=qi)_enc->state.qis[nqis++]=qi1;
@@ -761,6 +762,7 @@ int oc_enc_update_rc_state(oc_enc_ctx *_enc,
_enc->rc.cur_metrics.log_scale=oc_q57_to_q24(log_scale);
_enc->rc.cur_metrics.dup_count=_enc->dup_count;
_enc->rc.cur_metrics.frame_type=_enc->state.frame_type;
+ _enc->rc.cur_metrics.activity_avg=_enc->activity_avg;
_enc->rc.twopass_buffer_bytes=0;
}break;
case 2:{
@@ -863,9 +865,9 @@ int oc_enc_update_rc_state(oc_enc_ctx *_enc,
return dropped;
}
-#define OC_RC_2PASS_VERSION (1)
+#define OC_RC_2PASS_VERSION (2)
#define OC_RC_2PASS_HDR_SZ (38)
-#define OC_RC_2PASS_PACKET_SZ (8)
+#define OC_RC_2PASS_PACKET_SZ (12)
static void oc_rc_buffer_val(oc_rc_state *_rc,ogg_int64_t _val,int _bytes){
while(_bytes-->0){
@@ -900,6 +902,7 @@ int oc_enc_rc_2pass_out(oc_enc_ctx *_enc,unsigned char **_buf){
oc_rc_buffer_val(&_enc->rc,
_enc->rc.cur_metrics.dup_count|_enc->rc.cur_metrics.frame_type<<31,4);
oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.log_scale,4);
+ oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.activity_avg,4);
}
}
else if(_enc->packet_state==OC_PACKET_DONE&&
@@ -1050,16 +1053,19 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_PACKET_SZ){
ogg_uint32_t dup_count;
ogg_int32_t log_scale;
+ unsigned activity;
int qti;
int arg;
/*Read the metrics for the next frame.*/
dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
+ activity=oc_rc_unbuffer_val(&_enc->rc,4);
_enc->rc.cur_metrics.log_scale=log_scale;
qti=(dup_count&0x80000000)>>31;
_enc->rc.cur_metrics.dup_count=dup_count&0x7FFFFFFF;
_enc->rc.cur_metrics.frame_type=qti;
_enc->rc.twopass_force_kf=qti==OC_INTRA_FRAME;
+ _enc->activity_avg=_enc->rc.cur_metrics.activity_avg=activity;
/*"Helpfully" set the dup count back to what it was in pass 1.*/
arg=_enc->rc.cur_metrics.dup_count;
th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));
@@ -1070,8 +1076,8 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
else{
int frames_needed;
/*We're using a finite buffer:*/
- frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay
- -(_enc->rc.scale_window_end-_enc->rc.scale_window0),
+ frames_needed=OC_MINI(_enc->rc.buf_delay-OC_MINI(_enc->rc.buf_delay,
+ _enc->rc.scale_window_end-_enc->rc.scale_window0),
_enc->rc.frames_left[0]+_enc->rc.frames_left[1]
-_enc->rc.nframes[0]-_enc->rc.nframes[1]);
while(frames_needed>0){
@@ -1087,9 +1093,11 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
ogg_uint32_t dup_count;
ogg_int32_t log_scale;
int qti;
+ unsigned activity;
/*Read the metrics for the next frame.*/
dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
+ activity=oc_rc_unbuffer_val(&_enc->rc,4);
/*Add the to the circular buffer.*/
fmi=_enc->rc.frame_metrics_head+_enc->rc.nframe_metrics++;
if(fmi>=_enc->rc.cframe_metrics)fmi-=_enc->rc.cframe_metrics;
@@ -1098,6 +1106,7 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
qti=(dup_count&0x80000000)>>31;
m->dup_count=dup_count&0x7FFFFFFF;
m->frame_type=qti;
+ m->activity_avg=activity;
/*And accumulate the statistics over the window.*/
_enc->rc.nframes[qti]++;
_enc->rc.nframes[2]+=m->dup_count;
@@ -1105,8 +1114,8 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
_enc->rc.scale_window_end+=m->dup_count+1;
/*Compute an upper bound on the number of remaining packets needed
for the current window.*/
- frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay
- -(_enc->rc.scale_window_end-_enc->rc.scale_window0),
+ frames_needed=OC_MINI(_enc->rc.buf_delay-OC_MINI(_enc->rc.buf_delay,
+ _enc->rc.scale_window_end-_enc->rc.scale_window0),
_enc->rc.frames_left[0]+_enc->rc.frames_left[1]
-_enc->rc.nframes[0]-_enc->rc.nframes[1]);
/*Clear the buffer for the next frame.*/
@@ -1124,6 +1133,7 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
*(_enc->rc.frame_metrics+_enc->rc.frame_metrics_head);
_enc->rc.twopass_force_kf=
_enc->rc.cur_metrics.frame_type==OC_INTRA_FRAME;
+ _enc->activity_avg=_enc->rc.cur_metrics.activity_avg;
/*"Helpfully" set the dup count back to what it was in pass 1.*/
arg=_enc->rc.cur_metrics.dup_count;
th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));
diff --git a/thirdparty/libtheora/state.c b/thirdparty/libtheora/state.c
index 42ed33a9a3..f4c6240387 100644
--- a/thirdparty/libtheora/state.c
+++ b/thirdparty/libtheora/state.c
@@ -11,25 +11,93 @@
********************************************************************
function:
- last mod: $Id: state.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
#include <string.h>
-#include "internal.h"
-#if defined(OC_X86_ASM)
-#if defined(_MSC_VER)
-# include "x86_vc/x86int.h"
-#else
-# include "x86/x86int.h"
-#endif
-#endif
+#include "state.h"
#if defined(OC_DUMP_IMAGES)
# include <stdio.h>
# include "png.h"
+# include "zlib.h"
#endif
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with chroma decimated in the X and Y directions
+ (4:2:0).
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs00(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_lbmvs[0])+OC_MV_X(_lbmvs[1])
+ +OC_MV_X(_lbmvs[2])+OC_MV_X(_lbmvs[3]);
+ dy=OC_MV_Y(_lbmvs[0])+OC_MV_Y(_lbmvs[1])
+ +OC_MV_Y(_lbmvs[2])+OC_MV_Y(_lbmvs[3]);
+ _cbmvs[0]=OC_MV(OC_DIV_ROUND_POW2(dx,2,2),OC_DIV_ROUND_POW2(dy,2,2));
+}
+
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with chroma decimated in the Y direction.
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs01(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_lbmvs[0])+OC_MV_X(_lbmvs[2]);
+ dy=OC_MV_Y(_lbmvs[0])+OC_MV_Y(_lbmvs[2]);
+ _cbmvs[0]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+ dx=OC_MV_X(_lbmvs[1])+OC_MV_X(_lbmvs[3]);
+ dy=OC_MV_Y(_lbmvs[1])+OC_MV_Y(_lbmvs[3]);
+ _cbmvs[1]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+}
+
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with chroma decimated in the X direction (4:2:2).
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs10(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ int dx;
+ int dy;
+ dx=OC_MV_X(_lbmvs[0])+OC_MV_X(_lbmvs[1]);
+ dy=OC_MV_Y(_lbmvs[0])+OC_MV_Y(_lbmvs[1]);
+ _cbmvs[0]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+ dx=OC_MV_X(_lbmvs[2])+OC_MV_X(_lbmvs[3]);
+ dy=OC_MV_Y(_lbmvs[2])+OC_MV_Y(_lbmvs[3]);
+ _cbmvs[2]=OC_MV(OC_DIV_ROUND_POW2(dx,1,1),OC_DIV_ROUND_POW2(dy,1,1));
+}
+
+/*The function used to fill in the chroma plane motion vectors for a macro
+ block when 4 different motion vectors are specified in the luma plane.
+ This version is for use with no chroma decimation (4:4:4).
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lmbmv: The luma macro-block level motion vector to fill in for use in
+ prediction.
+ _lbmvs: The luma block-level motion vectors.*/
+static void oc_set_chroma_mvs11(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]){
+ _cbmvs[0]=_lbmvs[0];
+ _cbmvs[1]=_lbmvs[1];
+ _cbmvs[2]=_lbmvs[2];
+ _cbmvs[3]=_lbmvs[3];
+}
+
+/*A table of functions used to fill in the chroma plane motion vectors for a
+ macro block when 4 different motion vectors are specified in the luma
+ plane.*/
+const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS]={
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs00,
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs01,
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs10,
+ (oc_set_chroma_mvs_func)oc_set_chroma_mvs11
+};
+
+
+
/*Returns the fragment index of the top-left block in a macro block.
This can be used to test whether or not the whole macro block is valid.
_sb_map: The super block map.
@@ -92,7 +160,7 @@ static void oc_sb_create_plane_mapping(oc_sb_map _sb_maps[],
if(jmax>4)jmax=4;
else if(jmax<=0)break;
/*By default, set all fragment indices to -1.*/
- memset(_sb_maps[sbi][0],0xFF,sizeof(_sb_maps[sbi]));
+ memset(_sb_maps[sbi],0xFF,sizeof(_sb_maps[sbi]));
/*Fill in the fragment map for this super block.*/
xfrag=yfrag+x;
for(i=0;i<imax;i++){
@@ -186,10 +254,14 @@ static void oc_mb_fill_cmapping10(oc_mb_map_plane _mb_map[3],
This version is for use with no chroma decimation (4:4:4).
This uses the already filled-in luma plane values.
_mb_map: The macro block map to fill.
- _fplanes: The descriptions of the fragment planes.*/
+ _fplanes: The descriptions of the fragment planes.
+ _xfrag0: The X location of the upper-left hand fragment in the luma plane.
+ _yfrag0: The Y location of the upper-left hand fragment in the luma plane.*/
static void oc_mb_fill_cmapping11(oc_mb_map_plane _mb_map[3],
- const oc_fragment_plane _fplanes[3]){
+ const oc_fragment_plane _fplanes[3],int _xfrag0,int _yfrag0){
int k;
+ (void)_xfrag0;
+ (void)_yfrag0;
for(k=0;k<4;k++){
_mb_map[1][k]=_mb_map[0][k]+_fplanes[1].froffset;
_mb_map[2][k]=_mb_map[0][k]+_fplanes[2].froffset;
@@ -211,7 +283,7 @@ static const oc_mb_fill_cmapping_func OC_MB_FILL_CMAPPING_TABLE[4]={
oc_mb_fill_cmapping00,
oc_mb_fill_cmapping01,
oc_mb_fill_cmapping10,
- (oc_mb_fill_cmapping_func)oc_mb_fill_cmapping11
+ oc_mb_fill_cmapping11
};
/*Fills in the mapping from macro blocks to their corresponding fragment
@@ -469,7 +541,7 @@ static void oc_state_frarray_clear(oc_theora_state *_state){
unrestricted motion vectors without special casing the boundary.
If chroma is decimated in either direction, the padding is reduced by a
factor of 2 on the appropriate sides.
- _nrefs: The number of reference buffers to init; must be 3 or 4.*/
+ _nrefs: The number of reference buffers to init; must be in the range 3...6.*/
static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
th_info *info;
unsigned char *ref_frame_data;
@@ -481,6 +553,7 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
int yheight;
int chstride;
int cheight;
+ ptrdiff_t align;
ptrdiff_t yoffset;
ptrdiff_t coffset;
ptrdiff_t *frag_buf_offs;
@@ -489,33 +562,38 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
int vdec;
int rfi;
int pli;
- if(_nrefs<3||_nrefs>4)return TH_EINVAL;
+ if(_nrefs<3||_nrefs>6)return TH_EINVAL;
info=&_state->info;
/*Compute the image buffer parameters for each plane.*/
hdec=!(info->pixel_fmt&1);
vdec=!(info->pixel_fmt&2);
yhstride=info->frame_width+2*OC_UMV_PADDING;
yheight=info->frame_height+2*OC_UMV_PADDING;
- chstride=yhstride>>hdec;
+ /*Require 16-byte aligned rows in the chroma planes.*/
+ chstride=(yhstride>>hdec)+15&~15;
cheight=yheight>>vdec;
yplane_sz=yhstride*(size_t)yheight;
cplane_sz=chstride*(size_t)cheight;
yoffset=OC_UMV_PADDING+OC_UMV_PADDING*(ptrdiff_t)yhstride;
coffset=(OC_UMV_PADDING>>hdec)+(OC_UMV_PADDING>>vdec)*(ptrdiff_t)chstride;
- ref_frame_sz=yplane_sz+2*cplane_sz;
+ /*Although we guarantee the rows of the chroma planes are a multiple of 16
+ bytes, the initial padding on the first row may only be 8 bytes.
+ Compute the offset needed to the actual image data to a multiple of 16.*/
+ align=-coffset&15;
+ ref_frame_sz=yplane_sz+2*cplane_sz+16;
ref_frame_data_sz=_nrefs*ref_frame_sz;
/*Check for overflow.
The same caveats apply as for oc_state_frarray_init().*/
- if(yplane_sz/yhstride!=yheight||2*cplane_sz<cplane_sz||
+ if(yplane_sz/yhstride!=(size_t)yheight||2*cplane_sz+16<cplane_sz||
ref_frame_sz<yplane_sz||ref_frame_data_sz/_nrefs!=ref_frame_sz){
return TH_EIMPL;
}
- ref_frame_data=_ogg_malloc(ref_frame_data_sz);
+ ref_frame_data=oc_aligned_malloc(ref_frame_data_sz,16);
frag_buf_offs=_state->frag_buf_offs=
_ogg_malloc(_state->nfrags*sizeof(*frag_buf_offs));
if(ref_frame_data==NULL||frag_buf_offs==NULL){
_ogg_free(frag_buf_offs);
- _ogg_free(ref_frame_data);
+ oc_aligned_free(ref_frame_data);
return TH_EFAULT;
}
/*Set up the width, height and stride for the image buffers.*/
@@ -532,15 +610,15 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
memcpy(_state->ref_frame_bufs[rfi],_state->ref_frame_bufs[0],
sizeof(_state->ref_frame_bufs[0]));
}
+ _state->ref_frame_handle=ref_frame_data;
/*Set up the data pointers for the image buffers.*/
for(rfi=0;rfi<_nrefs;rfi++){
- _state->ref_frame_data[rfi]=ref_frame_data;
_state->ref_frame_bufs[rfi][0].data=ref_frame_data+yoffset;
- ref_frame_data+=yplane_sz;
+ ref_frame_data+=yplane_sz+align;
_state->ref_frame_bufs[rfi][1].data=ref_frame_data+coffset;
ref_frame_data+=cplane_sz;
_state->ref_frame_bufs[rfi][2].data=ref_frame_data+coffset;
- ref_frame_data+=cplane_sz;
+ ref_frame_data+=cplane_sz+(16-align);
/*Flip the buffer upside down.
This allows us to decode Theora's bottom-up frames in their natural
order, yet return a top-down buffer with a positive stride to the user.*/
@@ -550,7 +628,7 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
_state->ref_ystride[0]=-yhstride;
_state->ref_ystride[1]=_state->ref_ystride[2]=-chstride;
/*Initialize the fragment buffer offsets.*/
- ref_frame_data=_state->ref_frame_data[0];
+ ref_frame_data=_state->ref_frame_bufs[0][0].data;
fragi=0;
for(pli=0;pli<3;pli++){
th_img_plane *iplane;
@@ -576,41 +654,44 @@ static int oc_state_ref_bufs_init(oc_theora_state *_state,int _nrefs){
vpix+=stride<<3;
}
}
- /*Initialize the reference frame indices.*/
+ /*Initialize the reference frame pointers and indices.*/
_state->ref_frame_idx[OC_FRAME_GOLD]=
_state->ref_frame_idx[OC_FRAME_PREV]=
- _state->ref_frame_idx[OC_FRAME_SELF]=-1;
- _state->ref_frame_idx[OC_FRAME_IO]=_nrefs>3?3:-1;
+ _state->ref_frame_idx[OC_FRAME_GOLD_ORIG]=
+ _state->ref_frame_idx[OC_FRAME_PREV_ORIG]=
+ _state->ref_frame_idx[OC_FRAME_SELF]=
+ _state->ref_frame_idx[OC_FRAME_IO]=-1;
+ _state->ref_frame_data[OC_FRAME_GOLD]=
+ _state->ref_frame_data[OC_FRAME_PREV]=
+ _state->ref_frame_data[OC_FRAME_GOLD_ORIG]=
+ _state->ref_frame_data[OC_FRAME_PREV_ORIG]=
+ _state->ref_frame_data[OC_FRAME_SELF]=
+ _state->ref_frame_data[OC_FRAME_IO]=NULL;
return 0;
}
static void oc_state_ref_bufs_clear(oc_theora_state *_state){
_ogg_free(_state->frag_buf_offs);
- _ogg_free(_state->ref_frame_data[0]);
+ oc_aligned_free(_state->ref_frame_handle);
}
-void oc_state_vtable_init_c(oc_theora_state *_state){
+void oc_state_accel_init_c(oc_theora_state *_state){
+ _state->cpu_flags=0;
+#if defined(OC_STATE_USE_VTABLE)
_state->opt_vtable.frag_copy=oc_frag_copy_c;
+ _state->opt_vtable.frag_copy_list=oc_frag_copy_list_c;
_state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c;
_state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c;
_state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_c;
_state->opt_vtable.idct8x8=oc_idct8x8_c;
_state->opt_vtable.state_frag_recon=oc_state_frag_recon_c;
- _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_c;
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_c;
_state->opt_vtable.state_loop_filter_frag_rows=
oc_state_loop_filter_frag_rows_c;
_state->opt_vtable.restore_fpu=oc_restore_fpu_c;
- _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG;
-}
-
-/*Initialize the accelerated function pointers.*/
-void oc_state_vtable_init(oc_theora_state *_state){
-#if defined(OC_X86_ASM)
- oc_state_vtable_init_x86(_state);
-#else
- oc_state_vtable_init_c(_state);
#endif
+ _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG;
}
@@ -626,7 +707,8 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs){
how it is specified in the bitstream, because the Y axis is flipped in
the bitstream.
The displayable frame must fit inside the encoded frame.
- The color space must be one known by the encoder.*/
+ The color space must be one known by the encoder.
+ The framerate ratio must not contain a zero value.*/
if((_info->frame_width&0xF)||(_info->frame_height&0xF)||
_info->frame_width<=0||_info->frame_width>=0x100000||
_info->frame_height<=0||_info->frame_height>=0x100000||
@@ -639,7 +721,8 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs){
but there are a number of compilers which will mis-optimize this.
It's better to live with the spurious warnings.*/
_info->colorspace<0||_info->colorspace>=TH_CS_NSPACES||
- _info->pixel_fmt<0||_info->pixel_fmt>=TH_PF_NFORMATS){
+ _info->pixel_fmt<0||_info->pixel_fmt>=TH_PF_NFORMATS||
+ _info->fps_numerator<1||_info->fps_denominator<1){
return TH_EINVAL;
}
memset(_state,0,sizeof(*_state));
@@ -648,7 +731,7 @@ int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs){
system.*/
_state->info.pic_y=_info->frame_height-_info->pic_height-_info->pic_y;
_state->frame_type=OC_UNKWN_FRAME;
- oc_state_vtable_init(_state);
+ oc_state_accel_init(_state);
ret=oc_state_frarray_init(_state);
if(ret>=0)ret=oc_state_ref_bufs_init(_state,_nrefs);
if(ret<0){
@@ -758,11 +841,10 @@ void oc_state_borders_fill(oc_theora_state *_state,int _refi){
_offsets[1] is set if the motion vector has non-zero fractional
components.
_pli: The color plane index.
- _dx: The X component of the motion vector.
- _dy: The Y component of the motion vector.
+ _mv: The motion vector.
Return: The number of offsets returned: 1 or 2.*/
int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
- int _pli,int _dx,int _dy){
+ int _pli,oc_mv _mv){
/*Here is a brief description of how Theora handles motion vectors:
Motion vector components are specified to half-pixel accuracy in
undecimated directions of each plane, and quarter-pixel accuracy in
@@ -785,21 +867,25 @@ int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
int xfrac;
int yfrac;
int offs;
+ int dx;
+ int dy;
ystride=_state->ref_ystride[_pli];
/*These two variables decide whether we are in half- or quarter-pixel
precision in each component.*/
xprec=1+(_pli!=0&&!(_state->info.pixel_fmt&1));
yprec=1+(_pli!=0&&!(_state->info.pixel_fmt&2));
+ dx=OC_MV_X(_mv);
+ dy=OC_MV_Y(_mv);
/*These two variables are either 0 if all the fractional bits are zero or -1
if any of them are non-zero.*/
- xfrac=OC_SIGNMASK(-(_dx&(xprec|1)));
- yfrac=OC_SIGNMASK(-(_dy&(yprec|1)));
- offs=(_dx>>xprec)+(_dy>>yprec)*ystride;
+ xfrac=OC_SIGNMASK(-(dx&(xprec|1)));
+ yfrac=OC_SIGNMASK(-(dy&(yprec|1)));
+ offs=(dx>>xprec)+(dy>>yprec)*ystride;
if(xfrac||yfrac){
int xmask;
int ymask;
- xmask=OC_SIGNMASK(_dx);
- ymask=OC_SIGNMASK(_dy);
+ xmask=OC_SIGNMASK(dx);
+ ymask=OC_SIGNMASK(dy);
yfrac&=ystride;
_offsets[0]=offs-(xfrac&xmask)+(yfrac&ymask);
_offsets[1]=offs-(xfrac&~xmask)+(yfrac&~ymask);
@@ -848,13 +934,17 @@ int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
int mx2;
int my2;
int offs;
+ int dx;
+ int dy;
ystride=_state->ref_ystride[_pli];
qpy=_pli!=0&&!(_state->info.pixel_fmt&2);
- my=OC_MVMAP[qpy][_dy+31];
- my2=OC_MVMAP2[qpy][_dy+31];
+ dx=OC_MV_X(_mv);
+ dy=OC_MV_Y(_mv);
+ my=OC_MVMAP[qpy][dy+31];
+ my2=OC_MVMAP2[qpy][dy+31];
qpx=_pli!=0&&!(_state->info.pixel_fmt&1);
- mx=OC_MVMAP[qpx][_dx+31];
- mx2=OC_MVMAP2[qpx][_dx+31];
+ mx=OC_MVMAP[qpx][dx+31];
+ mx2=OC_MVMAP2[qpx][dx+31];
offs=my*ystride+mx;
if(mx2||my2){
_offsets[1]=offs+my2*ystride+mx2;
@@ -866,18 +956,12 @@ int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
#endif
}
-void oc_state_frag_recon(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
- _state->opt_vtable.state_frag_recon(_state,_fragi,_pli,_dct_coeffs,
- _last_zzi,_dc_quant);
-}
-
void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){
unsigned char *dst;
ptrdiff_t frag_buf_off;
int ystride;
- int mb_mode;
+ int refi;
/*Apply the inverse transform.*/
/*Special case only having a DC component.*/
if(_last_zzi<2){
@@ -887,69 +971,35 @@ void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
no iDCT rounding.*/
p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5);
/*LOOP VECTORIZES.*/
- for(ci=0;ci<64;ci++)_dct_coeffs[ci]=p;
+ for(ci=0;ci<64;ci++)_dct_coeffs[64+ci]=p;
}
else{
/*First, dequantize the DC coefficient.*/
_dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
- oc_idct8x8(_state,_dct_coeffs,_last_zzi);
+ oc_idct8x8(_state,_dct_coeffs+64,_dct_coeffs,_last_zzi);
}
/*Fill in the target buffer.*/
frag_buf_off=_state->frag_buf_offs[_fragi];
- mb_mode=_state->frags[_fragi].mb_mode;
+ refi=_state->frags[_fragi].refi;
ystride=_state->ref_ystride[_pli];
- dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off;
- if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra(_state,dst,ystride,_dct_coeffs);
+ dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off;
+ if(refi==OC_FRAME_SELF)oc_frag_recon_intra(_state,dst,ystride,_dct_coeffs+64);
else{
const unsigned char *ref;
int mvoffsets[2];
- ref=
- _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]
- +frag_buf_off;
+ ref=_state->ref_frame_data[refi]+frag_buf_off;
if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
- _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){
+ _state->frag_mvs[_fragi])>1){
oc_frag_recon_inter2(_state,
- dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,_dct_coeffs);
+ dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,_dct_coeffs+64);
+ }
+ else{
+ oc_frag_recon_inter(_state,dst,ref+mvoffsets[0],ystride,_dct_coeffs+64);
}
- else oc_frag_recon_inter(_state,dst,ref+mvoffsets[0],ystride,_dct_coeffs);
- }
-}
-
-/*Copies the fragments specified by the lists of fragment indices from one
- frame to another.
- _fragis: A pointer to a list of fragment indices.
- _nfragis: The number of fragment indices to copy.
- _dst_frame: The reference frame to copy to.
- _src_frame: The reference frame to copy from.
- _pli: The color plane the fragments lie in.*/
-void oc_state_frag_copy_list(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- _state->opt_vtable.state_frag_copy_list(_state,_fragis,_nfragis,_dst_frame,
- _src_frame,_pli);
-}
-
-void oc_state_frag_copy_list_c(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- const ptrdiff_t *frag_buf_offs;
- const unsigned char *src_frame_data;
- unsigned char *dst_frame_data;
- ptrdiff_t fragii;
- int ystride;
- dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
- src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
- ystride=_state->ref_ystride[_pli];
- frag_buf_offs=_state->frag_buf_offs;
- for(fragii=0;fragii<_nfragis;fragii++){
- ptrdiff_t frag_buf_off;
- frag_buf_off=frag_buf_offs[_fragis[fragii]];
- oc_frag_copy(_state,dst_frame_data+frag_buf_off,
- src_frame_data+frag_buf_off,ystride);
}
}
-static void loop_filter_h(unsigned char *_pix,int _ystride,int *_bv){
+static void loop_filter_h(unsigned char *_pix,int _ystride,signed char *_bv){
int y;
_pix-=2;
for(y=0;y<8;y++){
@@ -965,7 +1015,7 @@ static void loop_filter_h(unsigned char *_pix,int _ystride,int *_bv){
}
}
-static void loop_filter_v(unsigned char *_pix,int _ystride,int *_bv){
+static void loop_filter_v(unsigned char *_pix,int _ystride,signed char *_bv){
int x;
_pix-=_ystride*2;
for(x=0;x<8;x++){
@@ -982,20 +1032,16 @@ static void loop_filter_v(unsigned char *_pix,int _ystride,int *_bv){
/*Initialize the bounding values array used by the loop filter.
_bv: Storage for the array.
- Return: 0 on success, or a non-zero value if no filtering need be applied.*/
-int oc_state_loop_filter_init(oc_theora_state *_state,int _bv[256]){
- int flimit;
+ _flimit: The filter limit as defined in Section 7.10 of the spec.*/
+void oc_loop_filter_init_c(signed char _bv[256],int _flimit){
int i;
- flimit=_state->loop_filter_limits[_state->qis[0]];
- if(flimit==0)return 1;
memset(_bv,0,sizeof(_bv[0])*256);
- for(i=0;i<flimit;i++){
- if(127-i-flimit>=0)_bv[127-i-flimit]=i-flimit;
- _bv[127-i]=-i;
- _bv[127+i]=i;
- if(127+i+flimit<256)_bv[127+i+flimit]=flimit-i;
+ for(i=0;i<_flimit;i++){
+ if(127-i-_flimit>=0)_bv[127-i-_flimit]=(signed char)(i-_flimit);
+ _bv[127-i]=(signed char)(-i);
+ _bv[127+i]=(signed char)(i);
+ if(127+i+_flimit<256)_bv[127+i+_flimit]=(signed char)(_flimit-i);
}
- return 0;
}
/*Apply the loop filter to a given set of fragment rows in the given plane.
@@ -1006,14 +1052,8 @@ int oc_state_loop_filter_init(oc_theora_state *_state,int _bv[256]){
_pli: The color plane to filter.
_fragy0: The Y coordinate of the first fragment row to filter.
_fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
-void oc_state_loop_filter_frag_rows(const oc_theora_state *_state,int _bv[256],
- int _refi,int _pli,int _fragy0,int _fragy_end){
- _state->opt_vtable.state_loop_filter_frag_rows(_state,_bv,_refi,_pli,
- _fragy0,_fragy_end);
-}
-
-void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,int *_bv,
- int _refi,int _pli,int _fragy0,int _fragy_end){
+void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,
+ signed char *_bv,int _refi,int _pli,int _fragy0,int _fragy_end){
const oc_fragment_plane *fplane;
const oc_fragment *frags;
const ptrdiff_t *frag_buf_offs;
@@ -1030,7 +1070,7 @@ void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,int *_bv,
fragi_top=fplane->froffset;
fragi_bot=fragi_top+fplane->nfrags;
fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
- fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags;
+ fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags;
ystride=_state->ref_ystride[_pli];
frags=_state->frags;
frag_buf_offs=_state->frag_buf_offs;
diff --git a/thirdparty/libtheora/state.h b/thirdparty/libtheora/state.h
new file mode 100644
index 0000000000..f176a53ce9
--- /dev/null
+++ b/thirdparty/libtheora/state.h
@@ -0,0 +1,552 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: internal.h 17337 2010-07-19 16:08:54Z tterribe $
+
+ ********************************************************************/
+#if !defined(_state_H)
+# define _state_H (1)
+# include "internal.h"
+# include "huffman.h"
+# include "quant.h"
+
+
+
+/*A single quadrant of the map from a super block to fragment numbers.*/
+typedef ptrdiff_t oc_sb_map_quad[4];
+/*A map from a super block to fragment numbers.*/
+typedef oc_sb_map_quad oc_sb_map[4];
+/*A single plane of the map from a macro block to fragment numbers.*/
+typedef ptrdiff_t oc_mb_map_plane[4];
+/*A map from a macro block to fragment numbers.*/
+typedef oc_mb_map_plane oc_mb_map[3];
+/*A motion vector.*/
+typedef ogg_int16_t oc_mv;
+
+typedef struct oc_sb_flags oc_sb_flags;
+typedef struct oc_border_info oc_border_info;
+typedef struct oc_fragment oc_fragment;
+typedef struct oc_fragment_plane oc_fragment_plane;
+typedef struct oc_base_opt_vtable oc_base_opt_vtable;
+typedef struct oc_base_opt_data oc_base_opt_data;
+typedef struct oc_state_dispatch_vtable oc_state_dispatch_vtable;
+typedef struct oc_theora_state oc_theora_state;
+
+
+
+/*Shared accelerated functions.*/
+# if defined(OC_X86_ASM)
+# if defined(_MSC_VER)
+# include "x86_vc/x86int.h"
+# else
+# include "x86/x86int.h"
+# endif
+# endif
+# if defined(OC_ARM_ASM)
+# include "arm/armint.h"
+# endif
+# if defined(OC_C64X_ASM)
+# include "c64x/c64xint.h"
+# endif
+
+# if !defined(oc_state_accel_init)
+# define oc_state_accel_init oc_state_accel_init_c
+# endif
+# if defined(OC_STATE_USE_VTABLE)
+# if !defined(oc_frag_copy)
+# define oc_frag_copy(_state,_dst,_src,_ystride) \
+ ((*(_state)->opt_vtable.frag_copy)(_dst,_src,_ystride))
+# endif
+# if !defined(oc_frag_copy_list)
+# define oc_frag_copy_list(_state,_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs) \
+ ((*(_state)->opt_vtable.frag_copy_list)(_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs))
+# endif
+# if !defined(oc_frag_recon_intra)
+# define oc_frag_recon_intra(_state,_dst,_dst_ystride,_residue) \
+ ((*(_state)->opt_vtable.frag_recon_intra)(_dst,_dst_ystride,_residue))
+# endif
+# if !defined(oc_frag_recon_inter)
+# define oc_frag_recon_inter(_state,_dst,_src,_ystride,_residue) \
+ ((*(_state)->opt_vtable.frag_recon_inter)(_dst,_src,_ystride,_residue))
+# endif
+# if !defined(oc_frag_recon_inter2)
+# define oc_frag_recon_inter2(_state,_dst,_src1,_src2,_ystride,_residue) \
+ ((*(_state)->opt_vtable.frag_recon_inter2)(_dst, \
+ _src1,_src2,_ystride,_residue))
+# endif
+# if !defined(oc_idct8x8)
+# define oc_idct8x8(_state,_y,_x,_last_zzi) \
+ ((*(_state)->opt_vtable.idct8x8)(_y,_x,_last_zzi))
+# endif
+# if !defined(oc_state_frag_recon)
+# define oc_state_frag_recon(_state,_fragi, \
+ _pli,_dct_coeffs,_last_zzi,_dc_quant) \
+ ((*(_state)->opt_vtable.state_frag_recon)(_state,_fragi, \
+ _pli,_dct_coeffs,_last_zzi,_dc_quant))
+# endif
+# if !defined(oc_loop_filter_init)
+# define oc_loop_filter_init(_state,_bv,_flimit) \
+ ((*(_state)->opt_vtable.loop_filter_init)(_bv,_flimit))
+# endif
+# if !defined(oc_state_loop_filter_frag_rows)
+# define oc_state_loop_filter_frag_rows(_state, \
+ _bv,_refi,_pli,_fragy0,_fragy_end) \
+ ((*(_state)->opt_vtable.state_loop_filter_frag_rows)(_state, \
+ _bv,_refi,_pli,_fragy0,_fragy_end))
+# endif
+# if !defined(oc_restore_fpu)
+# define oc_restore_fpu(_state) \
+ ((*(_state)->opt_vtable.restore_fpu)())
+# endif
+# else
+# if !defined(oc_frag_copy)
+# define oc_frag_copy(_state,_dst,_src,_ystride) \
+ oc_frag_copy_c(_dst,_src,_ystride)
+# endif
+# if !defined(oc_frag_copy_list)
+# define oc_frag_copy_list(_state,_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs) \
+ oc_frag_copy_list_c(_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs)
+# endif
+# if !defined(oc_frag_recon_intra)
+# define oc_frag_recon_intra(_state,_dst,_dst_ystride,_residue) \
+ oc_frag_recon_intra_c(_dst,_dst_ystride,_residue)
+# endif
+# if !defined(oc_frag_recon_inter)
+# define oc_frag_recon_inter(_state,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_c(_dst,_src,_ystride,_residue)
+# endif
+# if !defined(oc_frag_recon_inter2)
+# define oc_frag_recon_inter2(_state,_dst,_src1,_src2,_ystride,_residue) \
+ oc_frag_recon_inter2_c(_dst,_src1,_src2,_ystride,_residue)
+# endif
+# if !defined(oc_idct8x8)
+# define oc_idct8x8(_state,_y,_x,_last_zzi) oc_idct8x8_c(_y,_x,_last_zzi)
+# endif
+# if !defined(oc_state_frag_recon)
+# define oc_state_frag_recon oc_state_frag_recon_c
+# endif
+# if !defined(oc_loop_filter_init)
+# define oc_loop_filter_init(_state,_bv,_flimit) \
+ oc_loop_filter_init_c(_bv,_flimit)
+# endif
+# if !defined(oc_state_loop_filter_frag_rows)
+# define oc_state_loop_filter_frag_rows oc_state_loop_filter_frag_rows_c
+# endif
+# if !defined(oc_restore_fpu)
+# define oc_restore_fpu(_state) do{}while(0)
+# endif
+# endif
+
+
+
+/*A keyframe.*/
+# define OC_INTRA_FRAME (0)
+/*A predicted frame.*/
+# define OC_INTER_FRAME (1)
+/*A frame of unknown type (frame type decision has not yet been made).*/
+# define OC_UNKWN_FRAME (-1)
+
+/*The amount of padding to add to the reconstructed frame buffers on all
+ sides.
+ This is used to allow unrestricted motion vectors without special casing.
+ This must be a multiple of 2.*/
+# define OC_UMV_PADDING (16)
+
+/*Frame classification indices.*/
+/*The previous golden frame.*/
+# define OC_FRAME_GOLD (0)
+/*The previous frame.*/
+# define OC_FRAME_PREV (1)
+/*The current frame.*/
+# define OC_FRAME_SELF (2)
+/*Used to mark uncoded fragments (for DC prediction).*/
+# define OC_FRAME_NONE (3)
+
+/*The input or output buffer.*/
+# define OC_FRAME_IO (3)
+/*Uncompressed prev golden frame.*/
+# define OC_FRAME_GOLD_ORIG (4)
+/*Uncompressed previous frame. */
+# define OC_FRAME_PREV_ORIG (5)
+
+/*Macroblock modes.*/
+/*Macro block is invalid: It is never coded.*/
+# define OC_MODE_INVALID (-1)
+/*Encoded difference from the same macro block in the previous frame.*/
+# define OC_MODE_INTER_NOMV (0)
+/*Encoded with no motion compensated prediction.*/
+# define OC_MODE_INTRA (1)
+/*Encoded difference from the previous frame offset by the given motion
+ vector.*/
+# define OC_MODE_INTER_MV (2)
+/*Encoded difference from the previous frame offset by the last coded motion
+ vector.*/
+# define OC_MODE_INTER_MV_LAST (3)
+/*Encoded difference from the previous frame offset by the second to last
+ coded motion vector.*/
+# define OC_MODE_INTER_MV_LAST2 (4)
+/*Encoded difference from the same macro block in the previous golden
+ frame.*/
+# define OC_MODE_GOLDEN_NOMV (5)
+/*Encoded difference from the previous golden frame offset by the given motion
+ vector.*/
+# define OC_MODE_GOLDEN_MV (6)
+/*Encoded difference from the previous frame offset by the individual motion
+ vectors given for each block.*/
+# define OC_MODE_INTER_MV_FOUR (7)
+/*The number of (coded) modes.*/
+# define OC_NMODES (8)
+
+/*Determines the reference frame used for a given MB mode.*/
+# define OC_FRAME_FOR_MODE(_x) \
+ OC_UNIBBLE_TABLE32(OC_FRAME_PREV,OC_FRAME_SELF,OC_FRAME_PREV,OC_FRAME_PREV, \
+ OC_FRAME_PREV,OC_FRAME_GOLD,OC_FRAME_GOLD,OC_FRAME_PREV,(_x))
+
+/*Constants for the packet state machine common between encoder and decoder.*/
+
+/*Next packet to emit/read: Codec info header.*/
+# define OC_PACKET_INFO_HDR (-3)
+/*Next packet to emit/read: Comment header.*/
+# define OC_PACKET_COMMENT_HDR (-2)
+/*Next packet to emit/read: Codec setup header.*/
+# define OC_PACKET_SETUP_HDR (-1)
+/*No more packets to emit/read.*/
+# define OC_PACKET_DONE (INT_MAX)
+
+
+
+#define OC_MV(_x,_y) ((oc_mv)((_x)&0xFF|(_y)<<8))
+#define OC_MV_X(_mv) ((signed char)(_mv))
+#define OC_MV_Y(_mv) ((_mv)>>8)
+#define OC_MV_ADD(_mv1,_mv2) \
+ OC_MV(OC_MV_X(_mv1)+OC_MV_X(_mv2), \
+ OC_MV_Y(_mv1)+OC_MV_Y(_mv2))
+#define OC_MV_SUB(_mv1,_mv2) \
+ OC_MV(OC_MV_X(_mv1)-OC_MV_X(_mv2), \
+ OC_MV_Y(_mv1)-OC_MV_Y(_mv2))
+
+
+
+/*Super blocks are 32x32 segments of pixels in a single color plane indexed
+ in image order.
+ Internally, super blocks are broken up into four quadrants, each of which
+ contains a 2x2 pattern of blocks, each of which is an 8x8 block of pixels.
+ Quadrants, and the blocks within them, are indexed in a special order called
+ a "Hilbert curve" within the super block.
+
+ In order to differentiate between the Hilbert-curve indexing strategy and
+ the regular image order indexing strategy, blocks indexed in image order
+ are called "fragments".
+ Fragments are indexed in image order, left to right, then bottom to top,
+ from Y' plane to Cb plane to Cr plane.
+
+ The co-located fragments in all image planes corresponding to the location
+ of a single quadrant of a luma plane super block form a macro block.
+ Thus there is only a single set of macro blocks for all planes, each of which
+ contains between 6 and 12 fragments, depending on the pixel format.
+ Therefore macro block information is kept in a separate set of arrays from
+ super blocks to avoid unused space in the other planes.
+ The lists are indexed in super block order.
+ That is, the macro block corresponding to the macro block mbi in (luma plane)
+ super block sbi is at index (sbi<<2|mbi).
+ Thus the number of macro blocks in each dimension is always twice the number
+ of super blocks, even when only an odd number fall inside the coded frame.
+ These "extra" macro blocks are just an artifact of our internal data layout,
+ and not part of the coded stream; they are flagged with a negative MB mode.*/
+
+
+
+/*Super block information.*/
+struct oc_sb_flags{
+ unsigned char coded_fully:1;
+ unsigned char coded_partially:1;
+ unsigned char quad_valid:4;
+};
+
+
+
+/*Information about a fragment which intersects the border of the displayable
+ region.
+ This marks which pixels belong to the displayable region.*/
+struct oc_border_info{
+ /*A bit mask marking which pixels are in the displayable region.
+ Pixel (x,y) corresponds to bit (y<<3|x).*/
+ ogg_int64_t mask;
+ /*The number of pixels in the displayable region.
+ This is always positive, and always less than 64.*/
+ int npixels;
+};
+
+
+
+/*Fragment information.*/
+struct oc_fragment{
+ /*A flag indicating whether or not this fragment is coded.*/
+ unsigned coded:1;
+ /*A flag indicating that this entire fragment lies outside the displayable
+ region of the frame.
+ Note the contrast with an invalid macro block, which is outside the coded
+ frame, not just the displayable one.
+ There are no fragments outside the coded frame by construction.*/
+ unsigned invalid:1;
+ /*The index of the quality index used for this fragment's AC coefficients.*/
+ unsigned qii:4;
+ /*The index of the reference frame this fragment is predicted from.*/
+ unsigned refi:2;
+ /*The mode of the macroblock this fragment belongs to.*/
+ unsigned mb_mode:3;
+ /*The index of the associated border information for fragments which lie
+ partially outside the displayable region.
+ For fragments completely inside or outside this region, this is -1.
+ Note that the C standard requires an explicit signed keyword for bitfield
+ types, since some compilers may treat them as unsigned without it.*/
+ signed int borderi:5;
+ /*The prediction-corrected DC component.
+ Note that the C standard requires an explicit signed keyword for bitfield
+ types, since some compilers may treat them as unsigned without it.*/
+ signed int dc:16;
+};
+
+
+
+/*A description of each fragment plane.*/
+struct oc_fragment_plane{
+ /*The number of fragments in the horizontal direction.*/
+ int nhfrags;
+ /*The number of fragments in the vertical direction.*/
+ int nvfrags;
+ /*The offset of the first fragment in the plane.*/
+ ptrdiff_t froffset;
+ /*The total number of fragments in the plane.*/
+ ptrdiff_t nfrags;
+ /*The number of super blocks in the horizontal direction.*/
+ unsigned nhsbs;
+ /*The number of super blocks in the vertical direction.*/
+ unsigned nvsbs;
+ /*The offset of the first super block in the plane.*/
+ unsigned sboffset;
+ /*The total number of super blocks in the plane.*/
+ unsigned nsbs;
+};
+
+
+typedef void (*oc_state_loop_filter_frag_rows_func)(
+ const oc_theora_state *_state,signed char _bv[256],int _refi,int _pli,
+ int _fragy0,int _fragy_end);
+
+/*The shared (encoder and decoder) functions that have accelerated variants.*/
+struct oc_base_opt_vtable{
+ void (*frag_copy)(unsigned char *_dst,
+ const unsigned char *_src,int _ystride);
+ void (*frag_copy_list)(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
+ void (*frag_recon_intra)(unsigned char *_dst,int _ystride,
+ const ogg_int16_t _residue[64]);
+ void (*frag_recon_inter)(unsigned char *_dst,
+ const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
+ void (*frag_recon_inter2)(unsigned char *_dst,const unsigned char *_src1,
+ const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
+ void (*idct8x8)(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
+ void (*state_frag_recon)(const oc_theora_state *_state,ptrdiff_t _fragi,
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+ void (*loop_filter_init)(signed char _bv[256],int _flimit);
+ oc_state_loop_filter_frag_rows_func state_loop_filter_frag_rows;
+ void (*restore_fpu)(void);
+};
+
+/*The shared (encoder and decoder) tables that vary according to which variants
+ of the above functions are used.*/
+struct oc_base_opt_data{
+ const unsigned char *dct_fzig_zag;
+};
+
+
+/*State information common to both the encoder and decoder.*/
+struct oc_theora_state{
+ /*The stream information.*/
+ th_info info;
+# if defined(OC_STATE_USE_VTABLE)
+ /*Table for shared accelerated functions.*/
+ oc_base_opt_vtable opt_vtable;
+# endif
+ /*Table for shared data used by accelerated functions.*/
+ oc_base_opt_data opt_data;
+ /*CPU flags to detect the presence of extended instruction sets.*/
+ ogg_uint32_t cpu_flags;
+ /*The fragment plane descriptions.*/
+ oc_fragment_plane fplanes[3];
+ /*The list of fragments, indexed in image order.*/
+ oc_fragment *frags;
+ /*The the offset into the reference frame buffer to the upper-left pixel of
+ each fragment.*/
+ ptrdiff_t *frag_buf_offs;
+ /*The motion vector for each fragment.*/
+ oc_mv *frag_mvs;
+ /*The total number of fragments in a single frame.*/
+ ptrdiff_t nfrags;
+ /*The list of super block maps, indexed in image order.*/
+ oc_sb_map *sb_maps;
+ /*The list of super block flags, indexed in image order.*/
+ oc_sb_flags *sb_flags;
+ /*The total number of super blocks in a single frame.*/
+ unsigned nsbs;
+ /*The fragments from each color plane that belong to each macro block.
+ Fragments are stored in image order (left to right then top to bottom).
+ When chroma components are decimated, the extra fragments have an index of
+ -1.*/
+ oc_mb_map *mb_maps;
+ /*The list of macro block modes.
+ A negative number indicates the macro block lies entirely outside the
+ coded frame.*/
+ signed char *mb_modes;
+ /*The number of macro blocks in the X direction.*/
+ unsigned nhmbs;
+ /*The number of macro blocks in the Y direction.*/
+ unsigned nvmbs;
+ /*The total number of macro blocks.*/
+ size_t nmbs;
+ /*The list of coded fragments, in coded order.
+ Uncoded fragments are stored in reverse order from the end of the list.*/
+ ptrdiff_t *coded_fragis;
+ /*The number of coded fragments in each plane.*/
+ ptrdiff_t ncoded_fragis[3];
+ /*The total number of coded fragments.*/
+ ptrdiff_t ntotal_coded_fragis;
+ /*The actual buffers used for the reference frames.*/
+ th_ycbcr_buffer ref_frame_bufs[6];
+ /*The index of the buffers being used for each OC_FRAME_* reference frame.*/
+ int ref_frame_idx[6];
+ /*The storage for the reference frame buffers.
+ This is just ref_frame_bufs[ref_frame_idx[i]][0].data, but is cached here
+ for faster look-up.*/
+ unsigned char *ref_frame_data[6];
+ /*The handle used to allocate the reference frame buffers.*/
+ unsigned char *ref_frame_handle;
+ /*The strides for each plane in the reference frames.*/
+ int ref_ystride[3];
+ /*The number of unique border patterns.*/
+ int nborders;
+ /*The unique border patterns for all border fragments.
+ The borderi field of fragments which straddle the border indexes this
+ list.*/
+ oc_border_info borders[16];
+ /*The frame number of the last keyframe.*/
+ ogg_int64_t keyframe_num;
+ /*The frame number of the current frame.*/
+ ogg_int64_t curframe_num;
+ /*The granpos of the current frame.*/
+ ogg_int64_t granpos;
+ /*The type of the current frame.*/
+ signed char frame_type;
+ /*The bias to add to the frame count when computing granule positions.*/
+ unsigned char granpos_bias;
+ /*The number of quality indices used in the current frame.*/
+ unsigned char nqis;
+ /*The quality indices of the current frame.*/
+ unsigned char qis[3];
+ /*The dequantization tables, stored in zig-zag order, and indexed by
+ qi, pli, qti, and zzi.*/
+ ogg_uint16_t *dequant_tables[64][3][2];
+ OC_ALIGN16(oc_quant_table dequant_table_data[64][3][2]);
+ /*Loop filter strength parameters.*/
+ unsigned char loop_filter_limits[64];
+};
+
+
+
+/*The function type used to fill in the chroma plane motion vectors for a
+ macro block when 4 different motion vectors are specified in the luma
+ plane.
+ _cbmvs: The chroma block-level motion vectors to fill in.
+ _lmbmv: The luma macro-block level motion vector to fill in for use in
+ prediction.
+ _lbmvs: The luma block-level motion vectors.*/
+typedef void (*oc_set_chroma_mvs_func)(oc_mv _cbmvs[4],const oc_mv _lbmvs[4]);
+
+
+
+/*A table of functions used to fill in the Cb,Cr plane motion vectors for a
+ macro block when 4 different motion vectors are specified in the luma
+ plane.*/
+extern const oc_set_chroma_mvs_func OC_SET_CHROMA_MVS_TABLE[TH_PF_NFORMATS];
+
+
+
+int oc_state_init(oc_theora_state *_state,const th_info *_info,int _nrefs);
+void oc_state_clear(oc_theora_state *_state);
+void oc_state_accel_init_c(oc_theora_state *_state);
+void oc_state_borders_fill_rows(oc_theora_state *_state,int _refi,int _pli,
+ int _y0,int _yend);
+void oc_state_borders_fill_caps(oc_theora_state *_state,int _refi,int _pli);
+void oc_state_borders_fill(oc_theora_state *_state,int _refi);
+void oc_state_fill_buffer_ptrs(oc_theora_state *_state,int _buf_idx,
+ th_ycbcr_buffer _img);
+int oc_state_mbi_for_pos(oc_theora_state *_state,int _mbx,int _mby);
+int oc_state_get_mv_offsets(const oc_theora_state *_state,int _offsets[2],
+ int _pli,oc_mv _mv);
+
+void oc_loop_filter_init_c(signed char _bv[256],int _flimit);
+void oc_state_loop_filter(oc_theora_state *_state,int _frame);
+# if defined(OC_DUMP_IMAGES)
+int oc_state_dump_frame(const oc_theora_state *_state,int _frame,
+ const char *_suf);
+# endif
+
+/*Default pure-C implementations of shared accelerated functions.*/
+void oc_frag_copy_c(unsigned char *_dst,
+ const unsigned char *_src,int _src_ystride);
+void oc_frag_copy_list_c(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
+void oc_frag_recon_intra_c(unsigned char *_dst,int _dst_ystride,
+ const ogg_int16_t _residue[64]);
+void oc_frag_recon_inter_c(unsigned char *_dst,
+ const unsigned char *_src,int _ystride,const ogg_int16_t _residue[64]);
+void oc_frag_recon_inter2_c(unsigned char *_dst,const unsigned char *_src1,
+ const unsigned char *_src2,int _ystride,const ogg_int16_t _residue[64]);
+void oc_idct8x8_c(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
+void oc_state_frag_recon_c(const oc_theora_state *_state,ptrdiff_t _fragi,
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+void oc_state_loop_filter_frag_rows_c(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+void oc_restore_fpu_c(void);
+
+/*We need a way to call a few encoder functions without introducing a link-time
+ dependency into the decoder, while still allowing the old alpha API which
+ does not distinguish between encoder and decoder objects to be used.
+ We do this by placing a function table at the start of the encoder object
+ which can dispatch into the encoder library.
+ We do a similar thing for the decoder in case we ever decide to split off a
+ common base library.*/
+typedef void (*oc_state_clear_func)(theora_state *_th);
+typedef int (*oc_state_control_func)(theora_state *th,int _req,
+ void *_buf,size_t _buf_sz);
+typedef ogg_int64_t (*oc_state_granule_frame_func)(theora_state *_th,
+ ogg_int64_t _granulepos);
+typedef double (*oc_state_granule_time_func)(theora_state *_th,
+ ogg_int64_t _granulepos);
+
+
+struct oc_state_dispatch_vtable{
+ oc_state_clear_func clear;
+ oc_state_control_func control;
+ oc_state_granule_frame_func granule_frame;
+ oc_state_granule_time_func granule_time;
+};
+
+#endif
diff --git a/thirdparty/libtheora/theora/codec.h b/thirdparty/libtheora/theora/codec.h
index 5c2669630c..29b8602325 100644
--- a/thirdparty/libtheora/theora/codec.h
+++ b/thirdparty/libtheora/theora/codec.h
@@ -16,11 +16,12 @@
********************************************************************/
/**\mainpage
- *
+ *
* \section intro Introduction
*
- * This is the documentation for <tt>libtheora</tt> C API.
- * The current reference
+ * This is the documentation for the <tt>libtheora</tt> C API.
+ *
+ * The \c libtheora package is the current reference
* implementation for <a href="http://www.theora.org/">Theora</a>, a free,
* patent-unencumbered video codec.
* Theora is derived from On2's VP3 codec with additional features and
@@ -30,29 +31,31 @@
* <a href="http://www.theora.org/doc/Theora.pdf">the Theora
* specification</a>.
*
- * \subsection Organization
+ * \section Organization
*
- * The functions documented here are actually subdivided into three
+ * The functions documented here are divided between two
* separate libraries:
- * - <tt>libtheoraenc</tt> contains the encoder interface,
+ * - \c libtheoraenc contains the encoder interface,
* described in \ref encfuncs.
- * - <tt>libtheoradec</tt> contains the decoder interface and
- * routines shared with the encoder.
- * You must also link to this if you link to <tt>libtheoraenc</tt>.
- * The routines in this library are described in \ref decfuncs and
- * \ref basefuncs.
- * - <tt>libtheora</tt> contains the \ref oldfuncs.
+ * - \c libtheoradec contains the decoder interface,
+ * described in \ref decfuncs, \n
+ * and additional \ref basefuncs.
+ *
+ * New code should link to \c libtheoradec. If using encoder
+ * features, it must also link to \c libtheoraenc.
*
- * New code should link to <tt>libtheoradec</tt> and, if using encoder
- * features, <tt>libtheoraenc</tt>. Together these two export both
- * the standard and the legacy API, so this is all that is needed by
- * any code. The older <tt>libtheora</tt> library is provided just for
- * compatibility with older build configurations.
+ * During initial development, prior to the 1.0 release,
+ * \c libtheora exported a different \ref oldfuncs which
+ * combined both encode and decode functions.
+ * In general, legacy API symbols can be indentified
+ * by their \c theora_ or \c OC_ namespace prefixes.
+ * The current API uses \c th_ or \c TH_ instead.
*
- * In general the recommended 1.x API symbols can be distinguished
- * by their <tt>th_</tt> or <tt>TH_</tt> namespace prefix.
- * The older, legacy API uses <tt>theora_</tt> or <tt>OC_</tt>
- * prefixes instead.
+ * While deprecated, \c libtheoraenc and \c libtheoradec
+ * together export the legacy api as well at the one documented above.
+ * Likewise, the legacy \c libtheora included with this package
+ * exports the new 1.x API. Older code and build scripts can therefore
+ * but updated independently to the current scheme.
*/
/**\file
@@ -168,7 +171,7 @@ typedef struct{
typedef th_img_plane th_ycbcr_buffer[3];
/**Theora bitstream information.
- * This contains the basic playback parameters for a stream, and corresponds to
+ * This contains the basic playback parameters for a stream, and corresponds to
* the initial 'info' header packet.
* To initialize an encoder, the application fills in this structure and
* passes it to th_encode_alloc().
@@ -317,7 +320,7 @@ typedef struct{
* In filling in this structure, th_decode_headerin() will null-terminate
* the user_comment strings for safety.
* However, the bitstream format itself treats them as 8-bit clean vectors,
- * possibly containing null characters, and so the length array should be
+ * possibly containing null characters, so the length array should be
* treated as their authoritative length.
*/
typedef struct th_comment{
@@ -448,7 +451,13 @@ typedef struct{
/**\defgroup basefuncs Functions Shared by Encode and Decode*/
/*@{*/
-/**\name Basic shared functions*/
+/**\name Basic shared functions
+ * These functions return information about the library itself,
+ * or provide high-level information about codec state
+ * and packet type.
+ *
+ * You must link to \c libtheoradec if you use any of the
+ * functions in this section.*/
/*@{*/
/**Retrieves a human-readable string to identify the library vendor and
* version.
@@ -510,7 +519,12 @@ extern int th_packet_iskeyframe(ogg_packet *_op);
/*@}*/
-/**\name Functions for manipulating header data*/
+/**\name Functions for manipulating header data
+ * These functions manipulate the #th_info and #th_comment structures
+ * which describe video parameters and key-value metadata, respectively.
+ *
+ * You must link to \c libtheoradec if you use any of the
+ * functions in this section.*/
/*@{*/
/**Initializes a th_info structure.
* This should be called on a freshly allocated #th_info structure before
@@ -537,7 +551,7 @@ extern void th_comment_init(th_comment *_tc);
* \param _tc The #th_comment struct to add the comment to.
* \param _comment Must be a null-terminated UTF-8 string containing the
* comment in "TAG=the value" form.*/
-extern void th_comment_add(th_comment *_tc, char *_comment);
+extern void th_comment_add(th_comment *_tc,const char *_comment);
/**Add a comment to an initialized #th_comment structure.
* \note Neither th_comment_add() nor th_comment_add_tag() support
* comments containing null values, although the bitstream format does
@@ -545,10 +559,11 @@ extern void th_comment_add(th_comment *_tc, char *_comment);
* To add such comments you will need to manipulate the #th_comment
* structure directly.
* \param _tc The #th_comment struct to add the comment to.
- * \param _tag A null-terminated string containing the tag associated with
+ * \param _tag A null-terminated string containing the tag associated with
* the comment.
* \param _val The corresponding value as a null-terminated string.*/
-extern void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val);
+extern void th_comment_add_tag(th_comment *_tc,const char *_tag,
+ const char *_val);
/**Look up a comment value by its tag.
* \param _tc An initialized #th_comment structure.
* \param _tag The tag to look up.
@@ -564,15 +579,15 @@ extern void th_comment_add_tag(th_comment *_tc,char *_tag,char *_val);
* It should not be modified or freed by the application, and
* modifications to the structure may invalidate the pointer.
* \retval NULL If no matching tag is found.*/
-extern char *th_comment_query(th_comment *_tc,char *_tag,int _count);
+extern char *th_comment_query(th_comment *_tc,const char *_tag,int _count);
/**Look up the number of instances of a tag.
* Call this first when querying for a specific tag and then iterate over the
* number of instances with separate calls to th_comment_query() to
* retrieve all the values for that tag in order.
* \param _tc An initialized #th_comment structure.
* \param _tag The tag to look up.
- * \return The number on instances of this particular tag.*/
-extern int th_comment_query_count(th_comment *_tc,char *_tag);
+ * \return The number of instances of this particular tag.*/
+extern int th_comment_query_count(th_comment *_tc,const char *_tag);
/**Clears a #th_comment structure.
* This should be called on a #th_comment structure after it is no longer
* needed.
diff --git a/thirdparty/libtheora/theora/theora.h b/thirdparty/libtheora/theora/theora.h
index af6eb6f380..a729a76890 100644
--- a/thirdparty/libtheora/theora/theora.h
+++ b/thirdparty/libtheora/theora/theora.h
@@ -34,41 +34,41 @@ extern "C"
*
* \section intro Introduction
*
- * This is the documentation for the libtheora legacy C API, declared in
+ * This is the documentation for the libtheora legacy C API, declared in
* the theora.h header, which describes the old interface used before
* the 1.0 release. This API was widely deployed for several years and
- * remains supported, but for new code we recommend the cleaner API
+ * remains supported, but for new code we recommend the cleaner API
* declared in theoradec.h and theoraenc.h.
*
* libtheora is the reference implementation for
* <a href="http://www.theora.org/">Theora</a>, a free video codec.
* Theora is derived from On2's VP3 codec with improved integration with
* Ogg multimedia formats by <a href="http://www.xiph.org/">Xiph.Org</a>.
- *
+ *
* \section overview Overview
*
- * This library will both decode and encode theora packets to/from raw YUV
+ * This library will both decode and encode theora packets to/from raw YUV
* frames. In either case, the packets will most likely either come from or
- * need to be embedded in an Ogg stream. Use
- * <a href="http://xiph.org/ogg/">libogg</a> or
+ * need to be embedded in an Ogg stream. Use
+ * <a href="http://xiph.org/ogg/">libogg</a> or
* <a href="http://www.annodex.net/software/liboggz/index.html">liboggz</a>
* to extract/package these packets.
*
* \section decoding Decoding Process
*
* Decoding can be separated into the following steps:
- * -# initialise theora_info and theora_comment structures using
+ * -# initialise theora_info and theora_comment structures using
* theora_info_init() and theora_comment_init():
\verbatim
theora_info info;
theora_comment comment;
-
+
theora_info_init(&info);
theora_comment_init(&comment);
\endverbatim
- * -# retrieve header packets from Ogg stream (there should be 3) and decode
- * into theora_info and theora_comment structures using
- * theora_decode_header(). See \ref identification for more information on
+ * -# retrieve header packets from Ogg stream (there should be 3) and decode
+ * into theora_info and theora_comment structures using
+ * theora_decode_header(). See \ref identification for more information on
* identifying which packets are theora packets.
\verbatim
int i;
@@ -79,14 +79,14 @@ extern "C"
}
\endverbatim
* -# initialise the decoder based on the information retrieved into the
- * theora_info struct by theora_decode_header(). You will need a
+ * theora_info struct by theora_decode_header(). You will need a
* theora_state struct.
\verbatim
theora_state state;
-
+
theora_decode_init(&state, &info);
\endverbatim
- * -# pass in packets and retrieve decoded frames! See the yuv_buffer
+ * -# pass in packets and retrieve decoded frames! See the yuv_buffer
* documentation for information on how to retrieve raw YUV data.
\verbatim
yuf_buffer buffer;
@@ -96,20 +96,20 @@ extern "C"
theora_decode_YUVout(&state, &buffer);
}
\endverbatim
- *
+ *
*
* \subsection identification Identifying Theora Packets
*
- * All streams inside an Ogg file have a unique serial_no attached to the
- * stream. Typically, you will want to
- * - retrieve the serial_no for each b_o_s (beginning of stream) page
- * encountered within the Ogg file;
- * - test the first (only) packet on that page to determine if it is a theora
+ * All streams inside an Ogg file have a unique serial_no attached to the
+ * stream. Typically, you will want to
+ * - retrieve the serial_no for each b_o_s (beginning of stream) page
+ * encountered within the Ogg file;
+ * - test the first (only) packet on that page to determine if it is a theora
* packet;
- * - once you have found a theora b_o_s page then use the retrieved serial_no
+ * - once you have found a theora b_o_s page then use the retrieved serial_no
* to identify future packets belonging to the same theora stream.
- *
- * Note that you \e cannot use theora_packet_isheader() to determine if a
+ *
+ * Note that you \e cannot use theora_packet_isheader() to determine if a
* packet is a theora packet or not, as this function does not perform any
* checking beyond whether a header bit is present. Instead, use the
* theora_decode_header() function and check the return value; or examine the
@@ -124,9 +124,9 @@ extern "C"
* A YUV buffer for passing uncompressed frames to and from the codec.
* This holds a Y'CbCr frame in planar format. The CbCr planes can be
* subsampled and have their own separate dimensions and row stride
- * offsets. Note that the strides may be negative in some
+ * offsets. Note that the strides may be negative in some
* configurations. For theora the width and height of the largest plane
- * must be a multiple of 16. The actual meaningful picture size and
+ * must be a multiple of 16. The actual meaningful picture size and
* offset are stored in the theora_info structure; frames returned by
* the decoder may need to be cropped for display.
*
@@ -135,8 +135,8 @@ extern "C"
* are ordered from left to right.
*
* During decode, the yuv_buffer struct is allocated by the user, but all
- * fields (including luma and chroma pointers) are filled by the library.
- * These pointers address library-internal memory and their contents should
+ * fields (including luma and chroma pointers) are filled by the library.
+ * These pointers address library-internal memory and their contents should
* not be modified.
*
* Conversely, during encode the user allocates the struct and fills out all
@@ -179,14 +179,14 @@ typedef enum {
OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */
OC_PF_RSVD, /**< Reserved value */
OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */
- OC_PF_444, /**< No chroma subsampling at all (4:4:4) */
+ OC_PF_444 /**< No chroma subsampling at all (4:4:4) */
} theora_pixelformat;
/**
* Theora bitstream info.
* Contains the basic playback parameters for a stream,
* corresponding to the initial 'info' header packet.
- *
+ *
* Encoded theora frames must be a multiple of 16 in width and height.
* To handle other frame sizes, a crop rectangle is specified in
* frame_height and frame_width, offset_x and * offset_y. The offset
@@ -198,10 +198,10 @@ typedef enum {
* fraction. Aspect ratio is also stored as a rational fraction, and
* refers to the aspect ratio of the frame pixels, not of the
* overall frame itself.
- *
+ *
* See <a href="http://svn.xiph.org/trunk/theora/examples/encoder_example.c">
* examples/encoder_example.c</a> for usage examples of the
- * other paramters and good default settings for the encoder parameters.
+ * other parameters and good default settings for the encoder parameters.
*/
typedef struct {
ogg_uint32_t width; /**< encoded frame width */
@@ -253,14 +253,14 @@ typedef struct{
} theora_state;
-/**
+/**
* Comment header metadata.
*
* This structure holds the in-stream metadata corresponding to
* the 'comment' header packet.
*
* Meta data is stored as a series of (tag, value) pairs, in
- * length-encoded string vectors. The first occurence of the
+ * length-encoded string vectors. The first occurence of the
* '=' character delimits the tag and value. A particular tag
* may occur more than once. The character set encoding for
* the strings is always UTF-8, but the tag names are limited
@@ -285,7 +285,7 @@ typedef struct theora_comment{
/* \anchor decctlcodes_old
* These are the available request codes for theora_control()
* when called with a decoder instance.
- * By convention decoder control codes are odd, to distinguish
+ * By convention decoder control codes are odd, to distinguish
* them from \ref encctlcodes_old "encoder control codes" which
* are even.
*
@@ -306,7 +306,7 @@ typedef struct theora_comment{
#define TH_DECCTL_GET_PPLEVEL_MAX (1)
/**Set the post-processing level.
- * Sets the level of post-processing to use when decoding the
+ * Sets the level of post-processing to use when decoding the
* compressed stream. This must be a value between zero (off)
* and the maximum returned by TH_DECCTL_GET_PPLEVEL_MAX.
*/
@@ -345,9 +345,9 @@ typedef struct theora_comment{
* \param[in] buf #th_quant_info
* \retval OC_FAULT \a theora_state is <tt>NULL</tt>.
* \retval OC_EINVAL Encoding has already begun, the quantization parameters
- * are not acceptable to this version of the encoder,
- * \a buf is <tt>NULL</tt> and \a buf_sz is not zero,
- * or \a buf is non-<tt>NULL</tt> and \a buf_sz is
+ * are not acceptable to this version of the encoder,
+ * \a buf is <tt>NULL</tt> and \a buf_sz is not zero,
+ * or \a buf is non-<tt>NULL</tt> and \a buf_sz is
* not <tt>sizeof(#th_quant_info)</tt>.
* \retval OC_IMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_QUANT_PARAMS (2)
@@ -424,7 +424,7 @@ typedef struct theora_comment{
#define OC_NEWPACKET -25 /**< Packet is an (ignorable) unhandled extension */
#define OC_DUPFRAME 1 /**< Packet is a dropped frame */
-/**
+/**
* Retrieve a human-readable string to identify the encoder vendor and version.
* \returns A version string.
*/
@@ -462,7 +462,7 @@ extern int theora_encode_init(theora_state *th, theora_info *ti);
extern int theora_encode_YUVin(theora_state *t, yuv_buffer *yuv);
/**
- * Request the next packet of encoded video.
+ * Request the next packet of encoded video.
* The encoded data is placed in a user-provided ogg_packet structure.
* \param t A theora_state handle previously initialized for encoding.
* \param last_p whether this is the last packet the encoder should produce.
@@ -496,7 +496,11 @@ extern int theora_encode_header(theora_state *t, ogg_packet *op);
* \param op An ogg_packet structure to fill. libtheora will set all
* elements of this structure, including a pointer to the encoded
* comment data. The memory for the comment data is owned by
- * libtheora.
+ * the application, and must be freed by it using _ogg_free().
+ * On some systems (such as Windows when using dynamic linking), this
+ * may mean the free is executed in a different module from the
+ * malloc, which will crash; there is no way to free this memory on
+ * such systems.
* \retval 0 Success
*/
extern int theora_encode_comment(theora_comment *tc, ogg_packet *op);
@@ -581,8 +585,8 @@ extern int theora_decode_packetin(theora_state *th,ogg_packet *op);
* \param th A theora_state handle previously initialized for decoding.
* \param yuv A yuv_buffer in which libtheora should place the decoded data.
* Note that the buffer struct itself is allocated by the user, but
- * that the luma and chroma pointers will be filled in by the
- * library. Also note that these luma and chroma regions should be
+ * that the luma and chroma pointers will be filled in by the
+ * library. Also note that these luma and chroma regions should be
* considered read-only by the user.
* \retval 0 Success
*/
@@ -617,22 +621,22 @@ extern int theora_packet_iskeyframe(ogg_packet *op);
/**
* Report the granulepos shift radix
*
- * When embedded in Ogg, Theora uses a two-part granulepos,
+ * When embedded in Ogg, Theora uses a two-part granulepos,
* splitting the 64-bit field into two pieces. The more-significant
* section represents the frame count at the last keyframe,
* and the less-significant section represents the count of
* frames since the last keyframe. In this way the overall
* field is still non-decreasing with time, but usefully encodes
* a pointer to the last keyframe, which is necessary for
- * correctly restarting decode after a seek.
+ * correctly restarting decode after a seek.
*
* This function reports the number of bits used to represent
* the distance to the last keyframe, and thus how the granulepos
* field must be shifted or masked to obtain the two parts.
- *
+ *
* Since libtheora returns compressed data in an ogg_packet
* structure, this may be generally useful even if the Theora
- * packets are not being used in an Ogg container.
+ * packets are not being used in an Ogg container.
*
* \param ti A previously initialized theora_info struct
* \returns The bit shift dividing the two granulepos fields
@@ -644,7 +648,7 @@ int theora_granule_shift(theora_info *ti);
/**
* Convert a granulepos to an absolute frame index, starting at 0.
* The granulepos is interpreted in the context of a given theora_state handle.
- *
+ *
* Note that while the granulepos encodes the frame count (i.e. starting
* from 1) this call returns the frame index, starting from zero. Thus
* One can calculate the presentation time by multiplying the index by
@@ -670,9 +674,7 @@ extern ogg_int64_t theora_granule_frame(theora_state *th,ogg_int64_t granulepos)
* This is the "end time" for the frame, or the latest time it should
* be displayed.
* It is not the presentation time.
- * \retval -1. The given granulepos is undefined (i.e. negative), or
- * \retval -1. The function has been disabled because floating
- * point support is not available.
+ * \retval -1. The given granulepos is undefined (i.e. negative).
*/
extern double theora_granule_time(theora_state *th,ogg_int64_t granulepos);
@@ -699,7 +701,7 @@ extern void theora_clear(theora_state *t);
/**
* Initialize an allocated theora_comment structure
- * \param tc An allocated theora_comment structure
+ * \param tc An allocated theora_comment structure
**/
extern void theora_comment_init(theora_comment *tc);
@@ -720,7 +722,7 @@ extern void theora_comment_add(theora_comment *tc, char *comment);
/**
* Add a comment to an initialized theora_comment structure.
* \param tc A previously initialized theora comment structure
- * \param tag A null-terminated string containing the tag
+ * \param tag A null-terminated string containing the tag
* associated with the comment.
* \param value The corresponding value as a null-terminated string
*
@@ -752,9 +754,9 @@ extern char *theora_comment_query(theora_comment *tc, char *tag, int count);
* \param tc An initialized theora_comment structure
* \param tag The tag to look up
* \returns The number on instances of a particular tag.
- *
+ *
* Call this first when querying for a specific tag and then interate
- * over the number of instances with separate calls to
+ * over the number of instances with separate calls to
* theora_comment_query() to retrieve all instances in order.
**/
extern int theora_comment_query_count(theora_comment *tc, char *tag);
@@ -769,7 +771,7 @@ extern void theora_comment_clear(theora_comment *tc);
* This is used to provide advanced control the encoding process.
* \param th A #theora_state handle.
* \param req The control code to process.
- * See \ref encctlcodes_old "the list of available
+ * See \ref encctlcodes_old "the list of available
* control codes" for details.
* \param buf The parameters for this control code.
* \param buf_sz The size of the parameter buffer.*/
diff --git a/thirdparty/libtheora/theora/theoradec.h b/thirdparty/libtheora/theora/theoradec.h
index b20f0e3a64..77bef81909 100644
--- a/thirdparty/libtheora/theora/theoradec.h
+++ b/thirdparty/libtheora/theora/theoradec.h
@@ -92,13 +92,17 @@ extern "C" {
* <tt>sizeof(th_stripe_callback)</tt>.*/
#define TH_DECCTL_SET_STRIPE_CB (7)
-/**Enables telemetry and sets the macroblock display mode */
+/**Sets the macroblock display mode. Set to 0 to disable displaying
+ * macroblocks.*/
#define TH_DECCTL_SET_TELEMETRY_MBMODE (9)
-/**Enables telemetry and sets the motion vector display mode */
+/**Sets the motion vector display mode. Set to 0 to disable displaying motion
+ * vectors.*/
#define TH_DECCTL_SET_TELEMETRY_MV (11)
-/**Enables telemetry and sets the adaptive quantization display mode */
+/**Sets the adaptive quantization display mode. Set to 0 to disable displaying
+ * adaptive quantization. */
#define TH_DECCTL_SET_TELEMETRY_QI (13)
-/**Enables telemetry and sets the bitstream breakdown visualization mode */
+/**Sets the bitstream breakdown visualization mode. Set to 0 to disable
+ * displaying bitstream breakdown.*/
#define TH_DECCTL_SET_TELEMETRY_BITS (15)
/*@}*/
@@ -171,7 +175,7 @@ typedef struct th_setup_info th_setup_info;
/**\defgroup decfuncs Functions for Decoding*/
/*@{*/
/**\name Functions for decoding
- * You must link to <tt>libtheoradec</tt> if you use any of the
+ * You must link to <tt>libtheoradec</tt> if you use any of the
* functions in this section.
*
* The functions are listed in the order they are used in a typical decode.
@@ -267,7 +271,10 @@ extern void th_setup_free(th_setup_info *_setup);
* See \ref decctlcodes "the list of available control codes"
* for details.
* \param _buf The parameters for this control code.
- * \param _buf_sz The size of the parameter buffer.*/
+ * \param _buf_sz The size of the parameter buffer.
+ * \return Possible return values depend on the control code used.
+ * See \ref decctlcodes "the list of control codes" for
+ * specific values. Generally 0 indicates success.*/
extern int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
size_t _buf_sz);
/**Submits a packet containing encoded video data to the decoder.
@@ -283,7 +290,8 @@ extern int th_decode_ctl(th_dec_ctx *_dec,int _req,void *_buf,
* \retval 0 Success.
* A new decoded frame can be retrieved by calling
* th_decode_ycbcr_out().
- * \retval TH_DUPFRAME The packet represented a dropped (0-byte) frame.
+ * \retval TH_DUPFRAME The packet represented a dropped frame (either a
+ * 0-byte frame or an INTER frame with no coded blocks).
* The player can skip the call to th_decode_ycbcr_out(),
* as the contents of the decoded frame buffer have not
* changed.
diff --git a/thirdparty/libtheora/theora/theoraenc.h b/thirdparty/libtheora/theora/theoraenc.h
index fdf2ab21e2..79b1c2b880 100644
--- a/thirdparty/libtheora/theora/theoraenc.h
+++ b/thirdparty/libtheora/theora/theoraenc.h
@@ -43,7 +43,7 @@ extern "C" {
* <tt>NULL</tt> may be specified to revert to the default tables.
*
* \param[in] _buf <tt>#th_huff_code[#TH_NHUFFMAN_TABLES][#TH_NDCT_TOKENS]</tt>
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
* \retval TH_EINVAL Encoding has already begun or one or more of the given
* tables is not full or prefix-free, \a _buf is
* <tt>NULL</tt> and \a _buf_sz is not zero, or \a _buf is
@@ -57,8 +57,8 @@ extern "C" {
* <tt>NULL</tt> may be specified to revert to the default parameters.
*
* \param[in] _buf #th_quant_info
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
- * \retval TH_EINVAL Encoding has already begun, \a _buf is
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
+ * \retval TH_EINVAL Encoding has already begun, \a _buf is
* <tt>NULL</tt> and \a _buf_sz is not zero,
* or \a _buf is non-<tt>NULL</tt> and
* \a _buf_sz is not <tt>sizeof(#th_quant_info)</tt>.
@@ -73,7 +73,7 @@ extern "C" {
* \param[in] _buf <tt>ogg_uint32_t</tt>: The maximum distance between key
* frames.
* \param[out] _buf <tt>ogg_uint32_t</tt>: The actual maximum distance set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(ogg_uint32_t)</tt>.
* \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE (4)
@@ -101,7 +101,7 @@ extern "C" {
* 4:2:0, the picture region is smaller than the full frame,
* or if encoding has begun, preventing the quantization
* tables and codebooks from being set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_VP3_COMPATIBLE (10)
@@ -114,7 +114,7 @@ extern "C" {
* the current encoding mode (VBR vs. constant quality, etc.).
*
* \param[out] _buf <tt>int</tt>: The maximum encoding speed level.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation in the current
* encoding mode.*/
@@ -124,7 +124,7 @@ extern "C" {
*
* \param[in] _buf <tt>int</tt>: The new encoding speed level.
* 0 is slowest, larger values use less CPU.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or the
* encoding speed level is out of bounds.
* The maximum encoding speed level may be
@@ -142,7 +142,7 @@ extern "C" {
*
* \param[out] _buf <tt>int</tt>: The current encoding speed level.
* 0 is slowest, larger values use less CPU.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation in the current
* encoding mode.*/
@@ -162,7 +162,7 @@ extern "C" {
*
* \param[in] _buf <tt>int</tt>: The number of duplicates to produce.
* If this is negative or zero, no duplicates will be produced.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or the
* number of duplicates is greater than or equal to the
* maximum keyframe interval.
@@ -187,7 +187,7 @@ extern "C" {
* use.
* - #TH_RATECTL_CAP_UNDERFLOW: Don't try to make up shortfalls
* later.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt> or rate control
* is not enabled.
* \retval TH_EIMPL Not supported by this implementation in the current
@@ -211,7 +211,7 @@ extern "C" {
* \param[in] _buf <tt>int</tt>: Requested size of the reservoir measured in
* frames.
* \param[out] _buf <tt>int</tt>: The actual size of the reservoir set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or rate control
* is not enabled. The buffer has an implementation
* defined minimum and maximum size and the value in _buf
@@ -243,7 +243,7 @@ extern "C" {
* application.
* \retval >=0 The number of bytes of metric data available in the
* returned buffer.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(char *)</tt>, no target
* bitrate has been set, or the first call was made after
* the first frame was submitted for encoding.
@@ -283,7 +283,7 @@ extern "C" {
* of bytes consumed.
* \retval >0 The number of bytes of metric data required/consumed.
* \retval 0 No more data is required before the next frame.
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
* \retval TH_EINVAL No target bitrate has been set, or the first call was
* made after the first frame was submitted for
* encoding.
@@ -306,7 +306,7 @@ extern "C" {
* \param[in] _buf <tt>int</tt>: The new target quality, in the range 0...63,
* inclusive.
* \retval 0 Success.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL A target bitrate has already been specified, or the
* quality index was not in the range 0...63.
* \retval TH_EIMPL Not supported by this implementation.*/
@@ -328,10 +328,54 @@ extern "C" {
*
* \param[in] _buf <tt>long</tt>: The new target bitrate, in bits per second.
* \retval 0 Success.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL The target bitrate was not positive.
- * \retval TH_EIMPL Not supported by this implementation.*/
+ * A future version of this library may allow passing 0
+ * to disabled rate-controlled mode and return to a
+ * quality-based mode, in which case this function will
+ * not return an error for that value.
+ * \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_BITRATE (30)
+/**Sets the configuration to be compatible with that from the given setup
+ * header.
+ * This sets the Huffman codebooks and quantization parameters to match those
+ * found in the given setup header.
+ * This guarantees that packets encoded by this encoder will be decodable using
+ * a decoder configured with the passed-in setup header.
+ * It does <em>not</em> guarantee that th_encode_flushheader() will produce a
+ * bit-identical setup header, only that they will be compatible.
+ * If you need a bit-identical setup header, then use the one you passed into
+ * this command, and not the one returned by th_encode_flushheader().
+ *
+ * This also does <em>not</em> enable or disable VP3 compatibility; that is not
+ * signaled in the setup header (or anywhere else in the encoded stream), and
+ * is controlled independently by the #TH_ENCCTL_SET_VP3_COMPATIBLE function.
+ * If you wish to enable VP3 compatibility mode <em>and</em> want the codebooks
+ * and quantization parameters to match the given setup header, you should
+ * enable VP3 compatibility before invoking this command, otherwise the
+ * codebooks and quantization parameters will be reset to the VP3 defaults.
+ *
+ * The current encoder does not support Huffman codebooks which do not contain
+ * codewords for all 32 tokens.
+ * Such codebooks are legal, according to the specification, but cannot be
+ * configured with this function.
+ *
+ * \param[in] _buf <tt>unsigned char[]</tt>: The encoded setup header to copy
+ * the configuration from.
+ * This should be the original,
+ * undecoded setup header packet,
+ * and <em>not</em> a #th_setup_info
+ * structure filled in by
+ * th_decode_headerin().
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EINVAL Encoding has already begun, so the codebooks and
+ * quantization parameters cannot be changed, or the
+ * data in the setup header was not supported by this
+ * encoder.
+ * \retval TH_EBADHEADER \a _buf did not contain a valid setup header packet.
+ * \retval TH_ENOTFORMAT \a _buf did not contain a Theora header at all.
+ * \retval TH_EIMPL Not supported by this implementation.*/
+#define TH_ENCCTL_SET_COMPAT_CONFIG (32)
/*@}*/
@@ -342,7 +386,8 @@ extern "C" {
/*@{*/
/**Drop frames to keep within bitrate buffer constraints.
* This can have a severe impact on quality, but is the only way to ensure that
- * bitrate targets are met at low rates during sudden bursts of activity.*/
+ * bitrate targets are met at low rates during sudden bursts of activity.
+ * It is enabled by default.*/
#define TH_RATECTL_DROP_FRAMES (0x1)
/**Ignore bitrate buffer overflows.
* If the encoder uses so few bits that the reservoir of available bits
@@ -350,14 +395,14 @@ extern "C" {
* The encoder will not try to use these extra bits in future frames.
* At high rates this may cause the result to be undersized, but allows a
* client to play the stream using a finite buffer; it should normally be
- * enabled.*/
+ * enabled, which is the default.*/
#define TH_RATECTL_CAP_OVERFLOW (0x2)
/**Ignore bitrate buffer underflows.
* If the encoder uses so many bits that the reservoir of available bits
* underflows, ignore the deficit.
* The encoder will not try to make up these extra bits in future frames.
* At low rates this may cause the result to be oversized; it should normally
- * be disabled.*/
+ * be disabled, which is the default.*/
#define TH_RATECTL_CAP_UNDERFLOW (0x4)
/*@}*/
@@ -401,8 +446,8 @@ typedef struct th_enc_ctx th_enc_ctx;
* packets.
* - For each uncompressed frame:
* - Submit the uncompressed frame via th_encode_ycbcr_in()
- * - Repeatedly call th_encode_packetout() to retrieve any video data packets
- * that are ready.
+ * - Repeatedly call th_encode_packetout() to retrieve any video
+ * data packets that are ready.
* - Call th_encode_free() to release all encoder memory.*/
/*@{*/
/**Allocates an encoder instance.
@@ -417,7 +462,10 @@ extern th_enc_ctx *th_encode_alloc(const th_info *_info);
* See \ref encctlcodes "the list of available control codes"
* for details.
* \param _buf The parameters for this control code.
- * \param _buf_sz The size of the parameter buffer.*/
+ * \param _buf_sz The size of the parameter buffer.
+ * \return Possible return values depend on the control code used.
+ * See \ref encctlcodes "the list of control codes" for
+ * specific values. Generally 0 indicates success.*/
extern int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz);
/**Outputs the next header packet.
* This should be called repeatedly after encoder initialization until it
@@ -441,11 +489,25 @@ extern int th_encode_flushheader(th_enc_ctx *_enc,
/**Submits an uncompressed frame to the encoder.
* \param _enc A #th_enc_ctx handle.
* \param _ycbcr A buffer of Y'CbCr data to encode.
+ * If the width and height of the buffer matches the frame size
+ * the encoder was initialized with, the encoder will only
+ * reference the portion inside the picture region.
+ * Any data outside this region will be ignored, and need not map
+ * to a valid address.
+ * Alternatively, you can pass a buffer equal to the size of the
+ * picture region, if this is less than the full frame size.
+ * When using subsampled chroma planes, odd picture sizes or odd
+ * picture offsets may require an unexpected chroma plane size,
+ * and their use is generally discouraged, as they will not be
+ * well-supported by players and other media frameworks.
+ * See Section 4.4 of
+ * <a href="http://www.theora.org/doc/Theora.pdf">the Theora
+ * specification</a> for details if you wish to use them anyway.
* \retval 0 Success.
* \retval TH_EFAULT \a _enc or \a _ycbcr is <tt>NULL</tt>.
- * \retval TH_EINVAL The buffer size does not match the frame size the encoder
- * was initialized with, or encoding has already
- * completed.*/
+ * \retval TH_EINVAL The buffer size matches neither the frame size nor the
+ * picture size the encoder was initialized with, or
+ * encoding has already completed.*/
extern int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _ycbcr);
/**Retrieves encoded video data packets.
* This should be called repeatedly after each frame is submitted to flush any
diff --git a/thirdparty/libtheora/tokenize.c b/thirdparty/libtheora/tokenize.c
index 60574c3594..57b7aa8da9 100644
--- a/thirdparty/libtheora/tokenize.c
+++ b/thirdparty/libtheora/tokenize.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: tokenize.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#include <stdlib.h>
@@ -20,27 +20,26 @@
+static unsigned char OC_DCT_EOB_TOKEN[31]={
+ 0,1,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
+};
+
static int oc_make_eob_token(int _run_count){
- if(_run_count<4)return OC_DCT_EOB1_TOKEN+_run_count-1;
- else{
- int cat;
- cat=OC_ILOGNZ_32(_run_count)-3;
- cat=OC_MINI(cat,3);
- return OC_DCT_REPEAT_RUN0_TOKEN+cat;
- }
+ return _run_count<32?OC_DCT_EOB_TOKEN[_run_count-1]:OC_DCT_REPEAT_RUN3_TOKEN;
}
+static unsigned char OC_DCT_EOB_EB[31]={
+ 0,0,0,0,1,2,3,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+};
+
static int oc_make_eob_token_full(int _run_count,int *_eb){
- if(_run_count<4){
- *_eb=0;
- return OC_DCT_EOB1_TOKEN+_run_count-1;
+ if(_run_count<32){
+ *_eb=OC_DCT_EOB_EB[_run_count-1];
+ return OC_DCT_EOB_TOKEN[_run_count-1];
}
else{
- int cat;
- cat=OC_ILOGNZ_32(_run_count)-3;
- cat=OC_MINI(cat,3);
- *_eb=_run_count-OC_BYTE_TABLE32(4,8,16,0,cat);
- return OC_DCT_REPEAT_RUN0_TOKEN+cat;
+ *_eb=_run_count;
+ return OC_DCT_REPEAT_RUN3_TOKEN;
}
}
@@ -49,86 +48,330 @@ static int oc_decode_eob_token(int _token,int _eb){
return (0x20820C41U>>_token*5&0x1F)+_eb;
}
-/*TODO: This is now only used during DCT tokenization, and never for runs; it
- should be simplified.*/
-static int oc_make_dct_token_full(int _zzi,int _zzj,int _val,int *_eb){
- int neg;
- int zero_run;
- int token;
- int eb;
- neg=_val<0;
- _val=abs(_val);
- zero_run=_zzj-_zzi;
- if(zero_run>0){
- int adj;
- /*Implement a minor restriction on stack 1 so that we know during DC fixups
- that extending a dctrun token from stack 1 will never overflow.*/
- adj=_zzi!=1;
- if(_val<2&&zero_run<17+adj){
- if(zero_run<6){
- token=OC_DCT_RUN_CAT1A+zero_run-1;
- eb=neg;
- }
- else if(zero_run<10){
- token=OC_DCT_RUN_CAT1B;
- eb=zero_run-6+(neg<<2);
- }
- else{
- token=OC_DCT_RUN_CAT1C;
- eb=zero_run-10+(neg<<3);
- }
- }
- else if(_val<4&&zero_run<3+adj){
- if(zero_run<2){
- token=OC_DCT_RUN_CAT2A;
- eb=_val-2+(neg<<1);
- }
- else{
- token=OC_DCT_RUN_CAT2B;
- eb=zero_run-2+(_val-2<<1)+(neg<<2);
- }
- }
- else{
- if(zero_run<9)token=OC_DCT_SHORT_ZRL_TOKEN;
- else token=OC_DCT_ZRL_TOKEN;
- eb=zero_run-1;
- }
- }
- else if(_val<3){
- token=OC_ONE_TOKEN+(_val-1<<1)+neg;
- eb=0;
- }
- else if(_val<7){
- token=OC_DCT_VAL_CAT2+_val-3;
- eb=neg;
- }
- else if(_val<9){
- token=OC_DCT_VAL_CAT3;
- eb=_val-7+(neg<<1);
- }
- else if(_val<13){
- token=OC_DCT_VAL_CAT4;
- eb=_val-9+(neg<<2);
- }
- else if(_val<21){
- token=OC_DCT_VAL_CAT5;
- eb=_val-13+(neg<<3);
- }
- else if(_val<37){
- token=OC_DCT_VAL_CAT6;
- eb=_val-21+(neg<<4);
- }
- else if(_val<69){
- token=OC_DCT_VAL_CAT7;
- eb=_val-37+(neg<<5);
- }
- else{
- token=OC_DCT_VAL_CAT8;
- eb=_val-69+(neg<<9);
- }
- *_eb=eb;
- return token;
-}
+/*Some tables for fast construction of value tokens.*/
+
+static const unsigned char OC_DCT_VALUE_TOKEN[1161]={
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,21,21,21,21,21,21,21,21,
+ 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
+ 21,21,21,21,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+ 19,19,19,19,19,19,19,19,18,18,18,18,17,17,16,15,14,13,12,10,
+ 7,
+ 9,11,13,14,15,16,17,17,18,18,18,18,19,19,19,19,19,19,19,19,
+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,
+ 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
+ 21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
+ 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22
+};
+
+static const ogg_uint16_t OC_DCT_VALUE_EB[1161]={
+ 1023,1022,1021,1020,1019,1018,1017,1016,1015,1014,
+ 1013,1012,1011,1010,1009,1008,1007,1006,1005,1004,
+ 1003,1002,1001,1000, 999, 998, 997, 996, 995, 994,
+ 993, 992, 991, 990, 989, 988, 987, 986, 985, 984,
+ 983, 982, 981, 980, 979, 978, 977, 976, 975, 974,
+ 973, 972, 971, 970, 969, 968, 967, 966, 965, 964,
+ 963, 962, 961, 960, 959, 958, 957, 956, 955, 954,
+ 953, 952, 951, 950, 949, 948, 947, 946, 945, 944,
+ 943, 942, 941, 940, 939, 938, 937, 936, 935, 934,
+ 933, 932, 931, 930, 929, 928, 927, 926, 925, 924,
+ 923, 922, 921, 920, 919, 918, 917, 916, 915, 914,
+ 913, 912, 911, 910, 909, 908, 907, 906, 905, 904,
+ 903, 902, 901, 900, 899, 898, 897, 896, 895, 894,
+ 893, 892, 891, 890, 889, 888, 887, 886, 885, 884,
+ 883, 882, 881, 880, 879, 878, 877, 876, 875, 874,
+ 873, 872, 871, 870, 869, 868, 867, 866, 865, 864,
+ 863, 862, 861, 860, 859, 858, 857, 856, 855, 854,
+ 853, 852, 851, 850, 849, 848, 847, 846, 845, 844,
+ 843, 842, 841, 840, 839, 838, 837, 836, 835, 834,
+ 833, 832, 831, 830, 829, 828, 827, 826, 825, 824,
+ 823, 822, 821, 820, 819, 818, 817, 816, 815, 814,
+ 813, 812, 811, 810, 809, 808, 807, 806, 805, 804,
+ 803, 802, 801, 800, 799, 798, 797, 796, 795, 794,
+ 793, 792, 791, 790, 789, 788, 787, 786, 785, 784,
+ 783, 782, 781, 780, 779, 778, 777, 776, 775, 774,
+ 773, 772, 771, 770, 769, 768, 767, 766, 765, 764,
+ 763, 762, 761, 760, 759, 758, 757, 756, 755, 754,
+ 753, 752, 751, 750, 749, 748, 747, 746, 745, 744,
+ 743, 742, 741, 740, 739, 738, 737, 736, 735, 734,
+ 733, 732, 731, 730, 729, 728, 727, 726, 725, 724,
+ 723, 722, 721, 720, 719, 718, 717, 716, 715, 714,
+ 713, 712, 711, 710, 709, 708, 707, 706, 705, 704,
+ 703, 702, 701, 700, 699, 698, 697, 696, 695, 694,
+ 693, 692, 691, 690, 689, 688, 687, 686, 685, 684,
+ 683, 682, 681, 680, 679, 678, 677, 676, 675, 674,
+ 673, 672, 671, 670, 669, 668, 667, 666, 665, 664,
+ 663, 662, 661, 660, 659, 658, 657, 656, 655, 654,
+ 653, 652, 651, 650, 649, 648, 647, 646, 645, 644,
+ 643, 642, 641, 640, 639, 638, 637, 636, 635, 634,
+ 633, 632, 631, 630, 629, 628, 627, 626, 625, 624,
+ 623, 622, 621, 620, 619, 618, 617, 616, 615, 614,
+ 613, 612, 611, 610, 609, 608, 607, 606, 605, 604,
+ 603, 602, 601, 600, 599, 598, 597, 596, 595, 594,
+ 593, 592, 591, 590, 589, 588, 587, 586, 585, 584,
+ 583, 582, 581, 580, 579, 578, 577, 576, 575, 574,
+ 573, 572, 571, 570, 569, 568, 567, 566, 565, 564,
+ 563, 562, 561, 560, 559, 558, 557, 556, 555, 554,
+ 553, 552, 551, 550, 549, 548, 547, 546, 545, 544,
+ 543, 542, 541, 540, 539, 538, 537, 536, 535, 534,
+ 533, 532, 531, 530, 529, 528, 527, 526, 525, 524,
+ 523, 522, 521, 520, 519, 518, 517, 516, 515, 514,
+ 513, 512, 63, 62, 61, 60, 59, 58, 57, 56,
+ 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
+ 45, 44, 43, 42, 41, 40, 39, 38, 37, 36,
+ 35, 34, 33, 32, 31, 30, 29, 28, 27, 26,
+ 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+ 5, 4, 3, 2, 1, 1, 1, 1, 0, 0,
+ 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ 2, 3, 0, 1, 2, 3, 4, 5, 6, 7,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+ 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 300, 301,
+ 302, 303, 304, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, 318, 319, 320, 321,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, 334, 335, 336, 337, 338, 339, 340, 341,
+ 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, 359, 360, 361,
+ 362, 363, 364, 365, 366, 367, 368, 369, 370, 371,
+ 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+ 382, 383, 384, 385, 386, 387, 388, 389, 390, 391,
+ 392, 393, 394, 395, 396, 397, 398, 399, 400, 401,
+ 402, 403, 404, 405, 406, 407, 408, 409, 410, 411,
+ 412, 413, 414, 415, 416, 417, 418, 419, 420, 421,
+ 422, 423, 424, 425, 426, 427, 428, 429, 430, 431,
+ 432, 433, 434, 435, 436, 437, 438, 439, 440, 441,
+ 442, 443, 444, 445, 446, 447, 448, 449, 450, 451,
+ 452, 453, 454, 455, 456, 457, 458, 459, 460, 461,
+ 462, 463, 464, 465, 466, 467, 468, 469, 470, 471,
+ 472, 473, 474, 475, 476, 477, 478, 479, 480, 481,
+ 482, 483, 484, 485, 486, 487, 488, 489, 490, 491,
+ 492, 493, 494, 495, 496, 497, 498, 499, 500, 501,
+ 502, 503, 504, 505, 506, 507, 508, 509, 510, 511
+};
+
+/*The first DCT coefficient that both has a smaller magnitude and gets coded
+ with a different token.*/
+static const ogg_int16_t OC_DCT_TRELLIS_ALT_VALUE[1161]={
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -68, -68, -68, -68, -68, -68, -68, -68,
+ -68, -68, -36, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -36, -36, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
+ -12, -12, -12, -12, -12, -12, -12, -12, -8, -8,
+ -8, -8, -6, -6, -5, -4, -3, -2, -1, 0,
+ 0,
+ 0, 1, 2, 3, 4, 5, 6, 6, 8, 8,
+ 8, 8, 12, 12, 12, 12, 12, 12, 12, 12,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68
+};
+
+#define OC_DCT_VALUE_TOKEN_PTR (OC_DCT_VALUE_TOKEN+580)
+#define OC_DCT_VALUE_EB_PTR (OC_DCT_VALUE_EB+580)
+#define OC_DCT_TRELLIS_ALT_VALUE_PTR (OC_DCT_TRELLIS_ALT_VALUE+580)
+
+/*Some tables for fast construction of combo tokens.*/
+
+static const unsigned char OC_DCT_RUN_CAT1_TOKEN[17]={
+ 23,24,25,26,27,28,28,28,28,29,29,29,29,29,29,29,29
+};
+
+static const unsigned char OC_DCT_RUN_CAT1_EB[17][2]={
+ {0,1},{0,1},{0, 1},{0, 1},{0, 1},{0, 4},{1, 5},{2, 6},{3,7},
+ {0,8},{1,9},{2,10},{3,11},{4,12},{5,13},{6,14},{7,15}
+};
+
+static const unsigned char OC_DCT_RUN_CAT2_EB[3][2][2]={
+ { {0,1},{2,3} },{ {0,2},{4,6} },{ {1,3},{5,7} }
+};
/*Token logging to allow a few fragments of efficient rollback.
Late SKIP analysis is tied up in the tokenization process, so we need to be
@@ -211,10 +454,11 @@ struct oc_quant_token{
/*Tokenizes the AC coefficients, possibly adjusting the quantization, and then
dequantizes and de-zig-zags the result.
- The DC coefficient is not preserved; it should be restored by the caller.*/
+ The AC coefficients of _idct must be pre-initialized to zero.*/
int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
- ogg_int16_t *_qdct,const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
- int _zzi,oc_token_checkpoint **_stack,int _acmin){
+ ogg_int16_t *_idct,const ogg_int16_t *_qdct,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin){
oc_token_checkpoint *stack;
ogg_int64_t zflags;
ogg_int64_t nzflags;
@@ -242,31 +486,29 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
d2_accum[0]=0;
zzj=64;
for(zzi=OC_MINI(_zzi,63);zzi>0;zzi--){
- ogg_int32_t lambda;
ogg_uint32_t best_cost;
int best_bits=best_bits;
int best_next=best_next;
int best_token=best_token;
int best_eb=best_eb;
int best_qc=best_qc;
- int flush_bits;
ogg_uint32_t d2;
int dq;
+ int qc_m;
int e;
int c;
int s;
int tj;
- lambda=_enc->lambda;
qc=_qdct[zzi];
s=-(qc<0);
- qc=qc+s^s;
- c=_dct[OC_FZIG_ZAG[zzi]];
- if(qc<=1){
+ qc_m=qc+s^s;
+ c=_dct[zzi];
+ /*The hard case: try a zero run.*/
+ if(qc_m<=1){
ogg_uint32_t sum_d2;
int nzeros;
int dc_reserve;
- /*The hard case: try a zero run.*/
- if(!qc){
+ if(!qc_m){
/*Skip runs that are already quantized to zeros.
If we considered each zero coefficient in turn, we might
theoretically find a better way to partition long zero runs (e.g.,
@@ -281,15 +523,14 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
d2=0;
}
else{
- c=c+s^s;
d2=c*(ogg_int32_t)c;
+ c=c+s^s;
}
eob=eob_run[zzi];
nzeros=zzj-zzi;
zzj&=63;
sum_d2=d2+d2_accum[zzj];
d2_accum[zzi]=sum_d2;
- flush_bits=eob>0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0;
/*We reserve 1 spot for combo run tokens that start in the 1st AC stack
to ensure they can be extended to include the DC coefficient if
necessary; this greatly simplifies stack-rewriting later on.*/
@@ -297,7 +538,6 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
best_cost=0xFFFFFFFF;
for(;;){
if(nzflags>>zzj&1){
- int cat;
int val;
int val_s;
int zzk;
@@ -306,11 +546,10 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
tk=next&1;
zzk=next>>1;
/*Try a pure zero run to this point.*/
- cat=nzeros+55>>6;
- token=OC_DCT_SHORT_ZRL_TOKEN+cat;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
+ token=OC_DCT_SHORT_ZRL_TOKEN+(nzeros+55>>6);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
d2=sum_d2-d2_accum[zzj];
- cost=d2+lambda*bits+tokens[zzj][1].cost;
+ cost=d2+_lambda*bits+tokens[zzj][1].cost;
if(cost<=best_cost){
best_next=(zzj<<1)+1;
best_token=token;
@@ -319,25 +558,18 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
best_bits=bits+tokens[zzj][1].bits;
best_qc=0;
}
- if(nzeros<16+dc_reserve){
+ if(nzeros<17+dc_reserve){
val=_qdct[zzj];
val_s=-(val<0);
val=val+val_s^val_s;
if(val<=2){
/*Try a +/- 1 combo token.*/
- if(nzeros<6){
- token=OC_DCT_RUN_CAT1A+nzeros-1;
- eb=-val_s;
- }
- else{
- cat=nzeros+54>>6;
- token=OC_DCT_RUN_CAT1B+cat;
- eb=(-val_s<<cat+2)+nzeros-6-(cat<<2);
- }
- e=(_dct[OC_FZIG_ZAG[zzj]]+val_s^val_s)-_dequant[zzj];
+ token=OC_DCT_RUN_CAT1_TOKEN[nzeros-1];
+ eb=OC_DCT_RUN_CAT1_EB[nzeros-1][-val_s];
+ e=_dct[zzj]-(_dequant[zzj]+val_s^val_s);
d2=e*(ogg_int32_t)e+sum_d2-d2_accum[zzj];
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits+tokens[zzk][tk].cost;
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ cost=d2+_lambda*bits+tokens[zzk][tk].cost;
if(cost<=best_cost){
best_next=next;
best_token=token;
@@ -347,22 +579,23 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
best_qc=1+val_s^val_s;
}
}
- if(nzeros<2+dc_reserve&&2<=val&&val<=4){
+ if(nzeros<3+dc_reserve&&2<=val&&val<=4){
+ int sval;
/*Try a +/- 2/3 combo token.*/
- cat=nzeros>>1;
- token=OC_DCT_RUN_CAT2A+cat;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- val=2+((val+val_s^val_s)>2);
- e=(_dct[OC_FZIG_ZAG[zzj]]+val_s^val_s)-_dequant[zzj]*val;
+ token=OC_DCT_RUN_CAT2A+(nzeros>>1);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ val=2+(val>2);
+ sval=val+val_s^val_s;
+ e=_dct[zzj]-_dequant[zzj]*sval;
d2=e*(ogg_int32_t)e+sum_d2-d2_accum[zzj];
- cost=d2+lambda*bits+tokens[zzk][tk].cost;
+ cost=d2+_lambda*bits+tokens[zzk][tk].cost;
if(cost<=best_cost){
best_cost=cost;
best_bits=bits+tokens[zzk][tk].bits;
best_next=next;
best_token=token;
- best_eb=(-val_s<<1+cat)+(val-2<<cat)+(nzeros-1>>1);
- best_qc=val+val_s^val_s;
+ best_eb=OC_DCT_RUN_CAT2_EB[nzeros-1][-val_s][val-2];
+ best_qc=sval;
}
}
}
@@ -378,10 +611,10 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
/*We made it all the way to the end of the block; try an EOB token.*/
if(eob<4095){
bits=oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob+1))
- -flush_bits;
+ -(eob>0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0);
}
else bits=oc_token_bits(_enc,huffi,zzi,OC_DCT_EOB1_TOKEN);
- cost=sum_d2+bits*lambda;
+ cost=sum_d2+bits*_lambda;
/*If the best route so far is still a pure zero run to the end of the
block, force coding it as an EOB.
Even if it's not optimal for this block, it has a good chance of
@@ -408,20 +641,20 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
tokens[zzi][0].bits=best_bits;
tokens[zzi][0].qc=best_qc;
zflags|=(ogg_int64_t)1<<zzi;
- if(qc){
+ if(qc_m){
dq=_dequant[zzi];
- if(zzi<_acmin)lambda=0;
+ if(zzi<_acmin)_lambda=0;
e=dq-c;
d2=e*(ogg_int32_t)e;
token=OC_ONE_TOKEN-s;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
zzj=zzi+1&63;
tj=best_flags>>zzj&1;
next=(zzj<<1)+tj;
tokens[zzi][1].next=(unsigned char)next;
tokens[zzi][1].token=(signed char)token;
tokens[zzi][1].eb=0;
- tokens[zzi][1].cost=d2+lambda*bits+tokens[zzj][tj].cost;
+ tokens[zzi][1].cost=d2+_lambda*bits+tokens[zzj][tj].cost;
tokens[zzi][1].bits=bits+tokens[zzj][tj].bits;
tokens[zzi][1].qc=1+s^s;
nzflags|=(ogg_int64_t)1<<zzi;
@@ -430,200 +663,38 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
}
}
else{
+ int alt_qc;
eob=eob_run[zzi];
- if(zzi<_acmin)lambda=0;
- c=c+s^s;
+ if(zzi<_acmin)_lambda=0;
dq=_dequant[zzi];
/*No zero run can extend past this point.*/
d2_accum[zzi]=0;
- flush_bits=eob>0?oc_token_bits(_enc,huffi,zzi,oc_make_eob_token(eob)):0;
- if(qc<=2){
- e=2*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_TWO_TOKEN-s;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e-=dq;
- d2=e*(ogg_int32_t)e;
- token=OC_ONE_TOKEN-s;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_bits=bits;
- best_cost=cost;
- qc--;
- }
- best_eb=0;
- }
- else if(qc<=3){
- e=3*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT2;
- best_eb=-s;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e-=dq;
- d2=e*(ogg_int32_t)e;
- token=OC_TWO_TOKEN-s;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=0;
- best_bits=bits;
- best_cost=cost;
- qc--;
- }
- }
- else if(qc<=6){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT2+qc-3;
- best_eb=-s;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e-=dq;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_bits=bits;
- best_cost=cost;
- qc--;
- }
- }
- else if(qc<=8){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT3;
- best_eb=(-s<<1)+qc-7;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=6*dq-c;
- d2=e*(ogg_int32_t)e;
- token=OC_DCT_VAL_CAT2+3;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=-s;
- best_bits=bits;
- best_cost=cost;
- qc=6;
- }
- }
- else if(qc<=12){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT4;
- best_eb=(-s<<2)+qc-9;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=8*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=(-s<<1)+1;
- best_bits=bits;
- best_cost=cost;
- qc=8;
- }
- }
- else if(qc<=20){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT5;
- best_eb=(-s<<3)+qc-13;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=12*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=(-s<<2)+3;
- best_bits=bits;
- best_cost=cost;
- qc=12;
- }
- }
- else if(qc<=36){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT6;
- best_eb=(-s<<4)+qc-21;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=20*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<=best_cost){
- best_token=token;
- best_eb=(-s<<3)+7;
- best_bits=bits;
- best_cost=cost;
- qc=20;
- }
- }
- else if(qc<=68){
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT7;
- best_eb=(-s<<5)+qc-37;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=36*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<best_cost){
- best_token=token;
- best_eb=(-s<<4)+15;
- best_bits=bits;
- best_cost=cost;
- qc=36;
- }
- }
- else{
- e=qc*dq-c;
- d2=e*(ogg_int32_t)e;
- best_token=OC_DCT_VAL_CAT8;
- best_eb=(-s<<9)+qc-69;
- best_bits=flush_bits+oc_token_bits(_enc,huffi,zzi,best_token);
- best_cost=d2+lambda*best_bits;
- e=68*dq-c;
- d2=e*(ogg_int32_t)e;
- token=best_token-1;
- bits=flush_bits+oc_token_bits(_enc,huffi,zzi,token);
- cost=d2+lambda*bits;
- if(cost<best_cost){
- best_token=token;
- best_eb=(-s<<5)+31;
- best_bits=bits;
- best_cost=cost;
- qc=68;
- }
+ e=qc*dq-c;
+ d2=e*(ogg_int32_t)e;
+ best_token=*(OC_DCT_VALUE_TOKEN_PTR+qc);
+ best_bits=oc_token_bits(_enc,huffi,zzi,best_token);
+ best_cost=d2+_lambda*best_bits;
+ alt_qc=*(OC_DCT_TRELLIS_ALT_VALUE_PTR+qc);
+ e=alt_qc*dq-c;
+ d2=e*(ogg_int32_t)e;
+ token=*(OC_DCT_VALUE_TOKEN_PTR+alt_qc);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ cost=d2+_lambda*bits;
+ if(cost<best_cost){
+ best_token=token;
+ best_bits=bits;
+ best_cost=cost;
+ qc=alt_qc;
}
zzj=zzi+1&63;
tj=best_flags>>zzj&1;
next=(zzj<<1)+tj;
tokens[zzi][1].next=(unsigned char)next;
tokens[zzi][1].token=(signed char)best_token;
- tokens[zzi][1].eb=best_eb;
+ tokens[zzi][1].eb=*(OC_DCT_VALUE_EB_PTR+qc);
tokens[zzi][1].cost=best_cost+tokens[zzj][tj].cost;
tokens[zzi][1].bits=best_bits+tokens[zzj][tj].bits;
- tokens[zzi][1].qc=qc+s^s;
+ tokens[zzi][1].qc=qc;
nzflags|=(ogg_int64_t)1<<zzi;
best_flags|=(ogg_int64_t)1<<zzi;
}
@@ -631,9 +702,6 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
}
/*Emit the tokens from the best path through the trellis.*/
stack=*_stack;
- /*We blow away the first entry here so that things vectorize better.
- The DC coefficient is not actually stored in the array yet.*/
- for(zzi=0;zzi<64;zzi++)_qdct[zzi]=0;
dct_fzig_zag=_enc->state.opt_data.dct_fzig_zag;
zzi=1;
ti=best_flags>>1&1;
@@ -643,12 +711,15 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
eob=eob_run[zzi];
if(tokens[zzi][ti].token<OC_NDCT_EOB_TOKEN_MAX){
if(++eob>=4095){
- oc_enc_eob_log(_enc,_pli,zzi,eob);
+ oc_enc_token_log(_enc,_pli,zzi,OC_DCT_REPEAT_RUN3_TOKEN,eob);
eob=0;
}
eob_run[zzi]=eob;
/*We don't include the actual EOB cost for this block in the return value.
- It will be paid for by the fragment that terminates the EOB run.*/
+ It is very likely to eventually be spread over several blocks, and
+ including it more harshly penalizes the first few blocks in a long EOB
+ run.
+ Omitting it here gives a small PSNR and SSIM gain.*/
bits-=tokens[zzi][ti].bits;
zzi=_zzi;
break;
@@ -664,7 +735,7 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
zzj=(next>>1)-1&63;
/*TODO: It may be worth saving the dequantized coefficient in the trellis
above; we had to compute it to measure the error anyway.*/
- _qdct[dct_fzig_zag[zzj]]=(ogg_int16_t)(qc*(int)_dequant[zzj]);
+ _idct[dct_fzig_zag[zzj]]=(ogg_int16_t)(qc*(int)_dequant[zzj]);
zzi=next>>1;
ti=next&1;
}
@@ -673,6 +744,237 @@ int oc_enc_tokenize_ac(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
return bits;
}
+/*Simplistic R/D tokenizer.
+ The AC coefficients of _idct must be pre-initialized to zero.
+ This could be made more accurate by using more sophisticated
+ rate predictions for zeros.
+ It could be made faster by switching from R/D decisions to static
+ lambda-derived rounding biases.*/
+int oc_enc_tokenize_ac_fast(oc_enc_ctx *_enc,int _pli,ptrdiff_t _fragi,
+ ogg_int16_t *_idct,const ogg_int16_t *_qdct,
+ const ogg_uint16_t *_dequant,const ogg_int16_t *_dct,
+ int _zzi,oc_token_checkpoint **_stack,int _lambda,int _acmin){
+ const unsigned char *dct_fzig_zag;
+ ogg_uint16_t *eob_run;
+ oc_token_checkpoint *stack;
+ int huffi;
+ int zzi;
+ int zzj;
+ int zzk;
+ int total_bits;
+ int zr[4];
+ stack=*_stack;
+ total_bits=0;
+ /*The apparent bit-cost of coding a zero from observing the trellis
+ quantizer is pre-combined with lambda.
+ Four predictive cases are considered: the last optimized value is zero (+2)
+ or non-zero and the non-optimized value is zero (+1) or non-zero.*/
+ zr[0]=3*_lambda>>1;
+ zr[1]=_lambda;
+ zr[2]=4*_lambda;
+ zr[3]=7*_lambda>>1;
+ eob_run=_enc->eob_run[_pli];
+ dct_fzig_zag=_enc->state.opt_data.dct_fzig_zag;
+ huffi=_enc->huff_idxs[_enc->state.frame_type][1][_pli+1>>1];
+ for(zzj=zzi=1;zzj<_zzi&&!_qdct[zzj];zzj++);
+ while(zzj<_zzi){
+ int v;
+ int d0;
+ int d1;
+ int sign;
+ int k;
+ int eob;
+ int dq0;
+ int dq1;
+ int dd0;
+ int dd1;
+ int next_zero;
+ int eob_bits;
+ int dct_fzig_zzj;
+ dct_fzig_zzj=dct_fzig_zag[zzj];
+ v=_dct[zzj];
+ d0=_qdct[zzj];
+ eob=eob_run[zzi];
+ for(zzk=zzj+1;zzk<_zzi&&!_qdct[zzk];zzk++);
+ next_zero=zzk-zzj+62>>6;
+ dq0=d0*_dequant[zzj];
+ dd0=dq0-v;
+ dd0*=dd0;
+ sign=-(d0<0);
+ k=d0+sign^sign;
+ d1=(k-(zzj>_acmin))+sign^sign;
+ dq1=d1*_dequant[zzj];
+ dd1=dq1-v;
+ dd1*=dd1;
+ /*The cost of ending an eob run is included when the alternative is to
+ extend this eob run.
+ A per qi/zzi weight would probably be useful.
+ Including it in the overall tokenization cost was not helpful.
+ The same is true at the far end of the zero run plus token case.*/
+ if(eob>0&&d1==0&&zzk==_zzi){
+ eob_bits=oc_token_bits(_enc,huffi,zzi,OC_DCT_EOB1_TOKEN);
+ }
+ else eob_bits=0;
+ if(zzj==zzi){
+ /*No active zero run.*/
+ int best_token;
+ int best_eb;
+ int token;
+ int best_bits;
+ int bits;
+ int cost;
+ best_token=*(OC_DCT_VALUE_TOKEN_PTR+d0);
+ best_bits=oc_token_bits(_enc,huffi,zzi,best_token);
+ if(d1!=0){
+ token=*(OC_DCT_VALUE_TOKEN_PTR+d1);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ cost=dd1+(bits+eob_bits)*_lambda;
+ }
+ else{
+ token=bits=0;
+ cost=dd1+zr[next_zero];
+ }
+ if((dd0+(best_bits+eob_bits)*_lambda)>cost){
+ _idct[dct_fzig_zzj]=dq1;
+ if(d1==0){
+ zzj=zzk;
+ continue;
+ }
+ best_bits=bits;
+ best_token=token;
+ best_eb=*(OC_DCT_VALUE_EB_PTR+d1);
+ }
+ else{
+ best_eb=*(OC_DCT_VALUE_EB_PTR+d0);
+ _idct[dct_fzig_zzj]=dq0;
+ }
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzi);
+ if(eob>0){
+ oc_enc_eob_log(_enc,_pli,zzi,eob);
+ eob_run[zzi]=0;
+ }
+ oc_enc_token_log(_enc,_pli,zzi,best_token,best_eb);
+ total_bits+=best_bits;
+ }
+ else{
+ int d;
+ int dc_reserve;
+ int best_token;
+ int best_eb;
+ int best_bits;
+ int best_cost;
+ int best_bits1;
+ int best_token1;
+ int best_eb1;
+ int zr_bits;
+ int eob2;
+ int eob_bits2;
+ int bits;
+ int token;
+ int nzeros;
+ nzeros=zzj-zzi;
+ dc_reserve=zzi+62>>6;
+ /*A zero run, followed by the value alone.*/
+ best_token=best_token1=OC_DCT_SHORT_ZRL_TOKEN+(nzeros+55>>6);
+ best_eb=best_eb1=nzeros-1;
+ eob2=eob_run[zzj];
+ eob_bits2=eob2>0?oc_token_bits(_enc,huffi,zzj,OC_DCT_EOB1_TOKEN):0;
+ zr_bits=oc_token_bits(_enc,huffi,zzi,best_token)+eob_bits2;
+ best_bits=zr_bits
+ +oc_token_bits(_enc,huffi,zzj,*(OC_DCT_VALUE_TOKEN_PTR+d0));
+ d=d0;
+ best_bits1=0;
+ if(d1!=0){
+ best_bits1=zr_bits
+ +oc_token_bits(_enc,huffi,zzj,*(OC_DCT_VALUE_TOKEN_PTR+d1));
+ }
+ if(nzeros<17+dc_reserve){
+ if(k<=2){
+ /*+/- 1 combo token.*/
+ token=OC_DCT_RUN_CAT1_TOKEN[nzeros-1];
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ if(k==2&&bits<=best_bits1){
+ best_bits1=bits;
+ best_token1=token;
+ best_eb1=OC_DCT_RUN_CAT1_EB[nzeros-1][-sign];
+ }
+ if(k==1&&bits<=best_bits){
+ best_bits=bits;
+ best_token=token;
+ best_eb=OC_DCT_RUN_CAT1_EB[nzeros-1][-sign];
+ }
+ }
+ if(nzeros<3+dc_reserve&&2<=k&&k<=4){
+ /*+/- 2/3 combo token.*/
+ token=OC_DCT_RUN_CAT2A+(nzeros>>1);
+ bits=oc_token_bits(_enc,huffi,zzi,token);
+ if(k==4&&bits<=best_bits1){
+ best_bits1=bits;
+ best_token1=token;
+ best_eb1=OC_DCT_RUN_CAT2_EB[nzeros-1][-sign][1];
+ }
+ if(k!=4&&bits<=best_bits){
+ best_bits=bits;
+ best_token=token;
+ best_eb=OC_DCT_RUN_CAT2_EB[nzeros-1][-sign][k-2];
+ }
+ }
+ }
+ best_cost=dd0+(best_bits+eob_bits)*_lambda;
+ if(d1==0&&(dd1+zr[2+next_zero])<=best_cost){
+ zzj=zzk;
+ continue;
+ }
+ if(d1!=0&&dd1+(best_bits1+eob_bits)*_lambda<best_cost){
+ best_bits=best_bits1;
+ best_token=best_token1;
+ best_eb=best_eb1;
+ d=d1;
+ _idct[dct_fzig_zzj]=dq1;
+ }
+ else _idct[dct_fzig_zzj]=dq0;
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzi);
+ if(eob){
+ oc_enc_eob_log(_enc,_pli,zzi,eob);
+ eob_run[zzi]=0;
+ }
+ oc_enc_token_log(_enc,_pli,zzi,best_token,best_eb);
+ /*If a zero run won vs. the combo token we still need to code this
+ value.*/
+ if(best_token<=OC_DCT_ZRL_TOKEN){
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzj);
+ if(eob2){
+ oc_enc_eob_log(_enc,_pli,zzj,eob2);
+ /*The cost of any EOB run we disrupted is ignored because doing so
+ improved PSNR/SSIM by a small amount.*/
+ best_bits-=eob_bits2;
+ eob_run[zzj]=0;
+ }
+ oc_enc_token_log(_enc,_pli,zzj,
+ *(OC_DCT_VALUE_TOKEN_PTR+d),*(OC_DCT_VALUE_EB_PTR+d));
+ }
+ total_bits+=best_bits;
+ }
+ zzi=zzj+1;
+ zzj=zzk;
+ }
+ /*Code an EOB run to complete this block.
+ The cost of the EOB run is not included in the total as explained in
+ in a comment in the trellis tokenizer above.*/
+ if(zzi<64){
+ int eob;
+ eob=eob_run[zzi]+1;
+ oc_enc_tokenlog_checkpoint(_enc,stack++,_pli,zzi);
+ if(eob>=4095){
+ oc_enc_token_log(_enc,_pli,zzi,OC_DCT_REPEAT_RUN3_TOKEN,eob);
+ eob=0;
+ }
+ eob_run[zzi]=eob;
+ }
+ *_stack=stack;
+ return total_bits;
+}
+
void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
int _pli,int _fragy0,int _frag_yend){
const oc_fragment_plane *fplane;
@@ -695,10 +997,10 @@ void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
predictor for the same reference frame.*/
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
if(frags[fragi].coded){
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
- frag_dc[fragi]=(ogg_int16_t)(frags[fragi].dc-pred_last[ref]);
- pred_last[ref]=frags[fragi].dc;
+ int refi;
+ refi=frags[fragi].refi;
+ frag_dc[fragi]=(ogg_int16_t)(frags[fragi].dc-pred_last[refi]);
+ pred_last[refi]=frags[fragi].dc;
}
}
}
@@ -710,27 +1012,24 @@ void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
u_frags=frags-nhfrags;
l_ref=-1;
ul_ref=-1;
- u_ref=u_frags[fragi].coded?OC_FRAME_FOR_MODE(u_frags[fragi].mb_mode):-1;
+ u_ref=u_frags[fragi].refi;
for(fragx=0;fragx<nhfrags;fragx++,fragi++){
int ur_ref;
if(fragx+1>=nhfrags)ur_ref=-1;
- else{
- ur_ref=u_frags[fragi+1].coded?
- OC_FRAME_FOR_MODE(u_frags[fragi+1].mb_mode):-1;
- }
+ else ur_ref=u_frags[fragi+1].refi;
if(frags[fragi].coded){
int pred;
- int ref;
- ref=OC_FRAME_FOR_MODE(frags[fragi].mb_mode);
+ int refi;
+ refi=frags[fragi].refi;
/*We break out a separate case based on which of our neighbors use
the same reference frames.
This is somewhat faster than trying to make a generic case which
handles all of them, since it reduces lots of poorly predicted
jumps to one switch statement, and also lets a number of the
multiplications be optimized out by strength reduction.*/
- switch((l_ref==ref)|(ul_ref==ref)<<1|
- (u_ref==ref)<<2|(ur_ref==ref)<<3){
- default:pred=pred_last[ref];break;
+ switch((l_ref==refi)|(ul_ref==refi)<<1|
+ (u_ref==refi)<<2|(ur_ref==refi)<<3){
+ default:pred=pred_last[refi];break;
case 1:
case 3:pred=frags[fragi-1].dc;break;
case 2:pred=u_frags[fragi-1].dc;break;
@@ -764,8 +1063,8 @@ void oc_enc_pred_dc_frag_rows(oc_enc_ctx *_enc,
}break;
}
frag_dc[fragi]=(ogg_int16_t)(frags[fragi].dc-pred);
- pred_last[ref]=frags[fragi].dc;
- l_ref=ref;
+ pred_last[refi]=frags[fragi].dc;
+ l_ref=refi;
}
else l_ref=-1;
ul_ref=u_ref;
@@ -850,9 +1149,8 @@ void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
ti0++;
eob_run0=0;
}
- token=oc_make_dct_token_full(0,0,val,&eb);
- dct_tokens0[ti0]=(unsigned char)token;
- extra_bits0[ti0]=(ogg_uint16_t)eb;
+ dct_tokens0[ti0]=*(OC_DCT_VALUE_TOKEN_PTR+val);
+ extra_bits0[ti0]=*(OC_DCT_VALUE_EB_PTR+val);
ti0++;
}
else{
@@ -863,9 +1161,8 @@ void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
/*We're in the middle of an active EOB run in stack 1.
Move it to stack 0.*/
if(++eob_run0>=4095){
- token=oc_make_eob_token_full(eob_run0,&eb);
- dct_tokens0[ti0]=(unsigned char)token;
- extra_bits0[ti0]=(ogg_uint16_t)eb;
+ dct_tokens0[ti0]=OC_DCT_REPEAT_RUN3_TOKEN;
+ extra_bits0[ti0]=eob_run0;
ti0++;
eob_run0=0;
}
@@ -996,9 +1293,8 @@ void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
neobs1--;
/*If we have more than 4095 EOBs outstanding in stack1, flush the run.*/
if(eob_run1-neobs1>=4095){
- token=oc_make_eob_token_full(4095,&eb);
- dct_tokens1[ti1w]=(unsigned char)token;
- extra_bits1[ti1w]=(ogg_uint16_t)eb;
+ dct_tokens1[ti1w]=OC_DCT_REPEAT_RUN3_TOKEN;
+ extra_bits1[ti1w]=4095;
ti1w++;
eob_run1-=4095;
}
diff --git a/thirdparty/libtheora/x86/mmxencfrag.c b/thirdparty/libtheora/x86/mmxencfrag.c
index c79ff01fcc..cc9be8d867 100644
--- a/thirdparty/libtheora/x86/mmxencfrag.c
+++ b/thirdparty/libtheora/x86/mmxencfrag.c
@@ -65,7 +65,7 @@ unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
"paddw %%mm6,%%mm0\n\t"
"paddw %%mm2,%%mm0\n\t"
"movd %%mm0,%[ret]\n\t"
- :[ret]"=a"(ret),[src]"+%r"(_src),[ref]"+r"(_ref),[ystride3]"=&r"(ystride3)
+ :[ret]"=a"(ret),[src]"+r"(_src),[ref]"+r"(_ref),[ystride3]"=&r"(ystride3)
:[ystride]"r"((ptrdiff_t)_ystride)
);
return (unsigned)ret;
@@ -87,7 +87,9 @@ unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
The latter is exactly 1 too large when the low bit of two corresponding \
bytes is only set in one of them. \
Therefore we pxor the operands, pand to mask out the low bits, and psubb to \
- correct the output of pavgb.*/ \
+ correct the output of pavgb. \
+ TODO: This should be rewritten to compute ~pavgb(~a,~b) instead, which \
+ schedules better; currently, however, this function is unused.*/ \
"movq %%mm0,%%mm6\n\t" \
"lea (%[ref1],%[ystride],2),%[ref1]\n\t" \
"pxor %%mm1,%%mm0\n\t" \
@@ -153,7 +155,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
OC_SAD2_LOOP
OC_SAD2_LOOP
OC_SAD2_TAIL
- :[ret]"=&a"(ret),[src]"+r"(_src),[ref1]"+%r"(_ref1),[ref2]"+r"(_ref2)
+ :[ret]"=&a"(ret),[src]"+r"(_src),[ref1]"+r"(_ref1),[ref2]"+r"(_ref2)
:[ystride]"r"((ptrdiff_t)_ystride)
);
return (unsigned)ret;
@@ -163,54 +165,54 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
16-bit difference in %%mm0...%%mm7.*/
#define OC_LOAD_SUB_8x4(_off) \
"#OC_LOAD_SUB_8x4\n\t" \
- "movd "_off"(%[src]),%%mm0\n\t" \
- "movd "_off"(%[ref]),%%mm4\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm1\n\t" \
+ "movd "#_off"(%[src]),%%mm0\n\t" \
+ "movd "#_off"(%[ref]),%%mm4\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm1\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm5\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm5\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
- "movd "_off"(%[src]),%%mm2\n\t" \
- "movd "_off"(%[ref]),%%mm7\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm3\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm6\n\t" \
+ "movd "#_off"(%[src]),%%mm2\n\t" \
+ "movd "#_off"(%[ref]),%%mm7\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm3\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm6\n\t" \
"punpcklbw %%mm4,%%mm0\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
"punpcklbw %%mm4,%%mm4\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
"psubw %%mm4,%%mm0\n\t" \
- "movd "_off"(%[src]),%%mm4\n\t" \
- "movq %%mm0,"_off"*2(%[buf])\n\t" \
- "movd "_off"(%[ref]),%%mm0\n\t" \
+ "movd "#_off"(%[src]),%%mm4\n\t" \
+ "movq %%mm0,"OC_MEM_OFFS(_off*2,buf)"\n\t" \
+ "movd "#_off"(%[ref]),%%mm0\n\t" \
"punpcklbw %%mm5,%%mm1\n\t" \
"punpcklbw %%mm5,%%mm5\n\t" \
"psubw %%mm5,%%mm1\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm5\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm5\n\t" \
"punpcklbw %%mm7,%%mm2\n\t" \
"punpcklbw %%mm7,%%mm7\n\t" \
"psubw %%mm7,%%mm2\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm7\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm7\n\t" \
"punpcklbw %%mm6,%%mm3\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
"punpcklbw %%mm6,%%mm6\n\t" \
"psubw %%mm6,%%mm3\n\t" \
- "movd "_off"(%[src]),%%mm6\n\t" \
+ "movd "#_off"(%[src]),%%mm6\n\t" \
"punpcklbw %%mm0,%%mm4\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
"punpcklbw %%mm0,%%mm0\n\t" \
"lea (%[src],%[src_ystride],2),%[src]\n\t" \
"psubw %%mm0,%%mm4\n\t" \
- "movd "_off"(%[ref]),%%mm0\n\t" \
+ "movd "#_off"(%[ref]),%%mm0\n\t" \
"punpcklbw %%mm7,%%mm5\n\t" \
"neg %[src_ystride]\n\t" \
"punpcklbw %%mm7,%%mm7\n\t" \
"psubw %%mm7,%%mm5\n\t" \
- "movd "_off"(%[src],%[src_ystride]),%%mm7\n\t" \
+ "movd "#_off"(%[src],%[src_ystride]),%%mm7\n\t" \
"punpcklbw %%mm0,%%mm6\n\t" \
"lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
"punpcklbw %%mm0,%%mm0\n\t" \
"neg %[ref_ystride]\n\t" \
"psubw %%mm0,%%mm6\n\t" \
- "movd "_off"(%[ref],%[ref_ystride]),%%mm0\n\t" \
+ "movd "#_off"(%[ref],%[ref_ystride]),%%mm0\n\t" \
"lea (%[src],%[src_ystride],8),%[src]\n\t" \
"punpcklbw %%mm0,%%mm7\n\t" \
"neg %[src_ystride]\n\t" \
@@ -218,24 +220,24 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"lea (%[ref],%[ref_ystride],8),%[ref]\n\t" \
"psubw %%mm0,%%mm7\n\t" \
"neg %[ref_ystride]\n\t" \
- "movq "_off"*2(%[buf]),%%mm0\n\t" \
+ "movq "OC_MEM_OFFS(_off*2,buf)",%%mm0\n\t" \
/*Load an 8x4 array of pixel values from %[src] into %%mm0...%%mm7.*/
#define OC_LOAD_8x4(_off) \
"#OC_LOAD_8x4\n\t" \
- "movd "_off"(%[src]),%%mm0\n\t" \
- "movd "_off"(%[src],%[ystride]),%%mm1\n\t" \
- "movd "_off"(%[src],%[ystride],2),%%mm2\n\t" \
+ "movd "#_off"(%[src]),%%mm0\n\t" \
+ "movd "#_off"(%[src],%[ystride]),%%mm1\n\t" \
+ "movd "#_off"(%[src],%[ystride],2),%%mm2\n\t" \
"pxor %%mm7,%%mm7\n\t" \
- "movd "_off"(%[src],%[ystride3]),%%mm3\n\t" \
+ "movd "#_off"(%[src],%[ystride3]),%%mm3\n\t" \
"punpcklbw %%mm7,%%mm0\n\t" \
- "movd "_off"(%[src4]),%%mm4\n\t" \
+ "movd "#_off"(%[src4]),%%mm4\n\t" \
"punpcklbw %%mm7,%%mm1\n\t" \
- "movd "_off"(%[src4],%[ystride]),%%mm5\n\t" \
+ "movd "#_off"(%[src4],%[ystride]),%%mm5\n\t" \
"punpcklbw %%mm7,%%mm2\n\t" \
- "movd "_off"(%[src4],%[ystride],2),%%mm6\n\t" \
+ "movd "#_off"(%[src4],%[ystride],2),%%mm6\n\t" \
"punpcklbw %%mm7,%%mm3\n\t" \
- "movd "_off"(%[src4],%[ystride3]),%%mm7\n\t" \
+ "movd "#_off"(%[src4],%[ystride3]),%%mm7\n\t" \
"punpcklbw %%mm4,%%mm4\n\t" \
"punpcklbw %%mm5,%%mm5\n\t" \
"psrlw $8,%%mm4\n\t" \
@@ -248,7 +250,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
/*Performs the first two stages of an 8-point 1-D Hadamard transform.
The transform is performed in place, except that outputs 0-3 are swapped with
outputs 4-7.
- Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to
+ Outputs 2, 3, 6, and 7 from the second stage are negated (which allows us to
perform this stage in place with no temporary registers).*/
#define OC_HADAMARD_AB_8x4 \
"#OC_HADAMARD_AB_8x4\n\t" \
@@ -281,7 +283,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"psubw %%mm5,%%mm7\n\t" \
/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
- Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
+ Outputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
place with no temporary registers).*/
#define OC_HADAMARD_C_8x4 \
"#OC_HADAMARD_C_8x4\n\t" \
@@ -324,8 +326,8 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \
This implementation is only 26 (+4 for spilling registers).*/ \
"#OC_HADAMARD_C_ABS_ACCUM_A_8x4\n\t" \
- "movq %%mm7,"_r7"(%[buf])\n\t" \
- "movq %%mm6,"_r6"(%[buf])\n\t" \
+ "movq %%mm7,"OC_MEM_OFFS(_r7,buf)"\n\t" \
+ "movq %%mm6,"OC_MEM_OFFS(_r6,buf)"\n\t" \
/*mm7={0x7FFF}x4 \
mm0=max(abs(mm0),abs(mm1))-0x7FFF*/ \
"pcmpeqb %%mm7,%%mm7\n\t" \
@@ -343,14 +345,14 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"pmaxsw %%mm5,%%mm4\n\t" \
"paddw %%mm3,%%mm6\n\t" \
"paddw %%mm5,%%mm1\n\t" \
- "movq "_r7"(%[buf]),%%mm3\n\t" \
+ "movq "OC_MEM_OFFS(_r7,buf)",%%mm3\n\t" \
/*Performs the second part of the final stage of the Hadamard transform and
summing of absolute values.*/
#define OC_HADAMARD_C_ABS_ACCUM_B_8x4(_r6,_r7) \
"#OC_HADAMARD_C_ABS_ACCUM_B_8x4\n\t" \
"paddsw %%mm7,%%mm6\n\t" \
- "movq "_r6"(%[buf]),%%mm5\n\t" \
+ "movq "OC_MEM_OFFS(_r6,buf)",%%mm5\n\t" \
"paddsw %%mm7,%%mm1\n\t" \
"psubw %%mm6,%%mm2\n\t" \
"psubw %%mm1,%%mm4\n\t" \
@@ -391,7 +393,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
#define OC_TRANSPOSE_4x4x2(_off) \
"#OC_TRANSPOSE_4x4x2\n\t" \
/*First 4x4 transpose:*/ \
- "movq %%mm5,0x10+"_off"(%[buf])\n\t" \
+ "movq %%mm5,"OC_MEM_OFFS(0x10+(_off),buf)"\n\t" \
/*mm0 = e3 e2 e1 e0 \
mm1 = f3 f2 f1 f0 \
mm2 = g3 g2 g1 g0 \
@@ -411,13 +413,13 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
"punpckhdq %%mm2,%%mm1\n\t" \
"movq %%mm3,%%mm2\n\t" \
"punpckhdq %%mm5,%%mm3\n\t" \
- "movq %%mm0,0x40+"_off"(%[buf])\n\t" \
+ "movq %%mm0,"OC_MEM_OFFS(0x40+(_off),buf)"\n\t" \
"punpckldq %%mm5,%%mm2\n\t" \
/*mm0 = h0 g0 f0 e0 \
mm1 = h1 g1 f1 e1 \
mm2 = h2 g2 f2 e2 \
mm3 = h3 g3 f3 e3*/ \
- "movq 0x10+"_off"(%[buf]),%%mm5\n\t" \
+ "movq "OC_MEM_OFFS(0x10+(_off),buf)",%%mm5\n\t" \
/*Second 4x4 transpose:*/ \
/*mm4 = a3 a2 a1 a0 \
mm5 = b3 b2 b1 b0 \
@@ -425,11 +427,11 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm7 = d3 d2 d1 d0*/ \
"movq %%mm6,%%mm0\n\t" \
"punpcklwd %%mm7,%%mm6\n\t" \
- "movq %%mm1,0x50+"_off"(%[buf])\n\t" \
+ "movq %%mm1,"OC_MEM_OFFS(0x50+(_off),buf)"\n\t" \
"punpckhwd %%mm7,%%mm0\n\t" \
"movq %%mm4,%%mm7\n\t" \
"punpcklwd %%mm5,%%mm4\n\t" \
- "movq %%mm2,0x60+"_off"(%[buf])\n\t" \
+ "movq %%mm2,"OC_MEM_OFFS(0x60+(_off),buf)"\n\t" \
"punpckhwd %%mm5,%%mm7\n\t" \
/*mm4 = b1 a1 b0 a0 \
mm7 = b3 a3 b2 a2 \
@@ -437,7 +439,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm0 = d3 c3 d2 c2*/ \
"movq %%mm4,%%mm5\n\t" \
"punpckldq %%mm6,%%mm4\n\t" \
- "movq %%mm3,0x70+"_off"(%[buf])\n\t" \
+ "movq %%mm3,"OC_MEM_OFFS(0x70+(_off),buf)"\n\t" \
"punpckhdq %%mm6,%%mm5\n\t" \
"movq %%mm7,%%mm6\n\t" \
"punpckhdq %%mm0,%%mm7\n\t" \
@@ -447,100 +449,102 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm6 = d2 c2 b2 a2 \
mm7 = d3 c3 b3 a3*/ \
-static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
- int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret;
- unsigned ret2;
- bufp=buf;
+static unsigned oc_int_frag_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _src_ystride,
+ const unsigned char *_ref,int _ref_ystride){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ unsigned ret;
+ unsigned ret2;
+ int dc;
__asm__ __volatile__(
- OC_LOAD_SUB_8x4("0x00")
+ OC_LOAD_SUB_8x4(0x00)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x00")
+ OC_TRANSPOSE_4x4x2(0x00)
/*Finish swapping out this 8x4 block to make room for the next one.
mm0...mm3 have been swapped out already.*/
- "movq %%mm4,0x00(%[buf])\n\t"
- "movq %%mm5,0x10(%[buf])\n\t"
- "movq %%mm6,0x20(%[buf])\n\t"
- "movq %%mm7,0x30(%[buf])\n\t"
- OC_LOAD_SUB_8x4("0x04")
+ "movq %%mm4,"OC_MEM_OFFS(0x00,buf)"\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x10,buf)"\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x20,buf)"\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x30,buf)"\n\t"
+ OC_LOAD_SUB_8x4(0x04)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x08")
+ OC_TRANSPOSE_4x4x2(0x08)
/*Here the first 4x4 block of output from the last transpose is the second
4x4 block of input for the next transform.
We have cleverly arranged that it already be in the appropriate place, so
we only have to do half the loads.*/
- "movq 0x10(%[buf]),%%mm1\n\t"
- "movq 0x20(%[buf]),%%mm2\n\t"
- "movq 0x30(%[buf]),%%mm3\n\t"
- "movq 0x00(%[buf]),%%mm0\n\t"
- OC_HADAMARD_ABS_ACCUM_8x4("0x28","0x38")
+ "movq "OC_MEM_OFFS(0x10,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x20,buf)",%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x30,buf)",%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x00,buf)",%%mm0\n\t"
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x4
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
+ "movd %%mm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
for the factor of two we dropped + 3 for the vertical accumulation).
Now we finally have to promote things to dwords.
We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
latency of pmaddwd by starting the next series of loads now.*/
- "mov %[thresh],%[ret2]\n\t"
"pmaddwd %%mm7,%%mm0\n\t"
- "movq 0x50(%[buf]),%%mm1\n\t"
- "movq 0x58(%[buf]),%%mm5\n\t"
+ "movq "OC_MEM_OFFS(0x50,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x58,buf)",%%mm5\n\t"
"movq %%mm0,%%mm4\n\t"
- "movq 0x60(%[buf]),%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x60,buf)",%%mm2\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
- "movq 0x68(%[buf]),%%mm6\n\t"
+ "movq "OC_MEM_OFFS(0x68,buf)",%%mm6\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movq 0x70(%[buf]),%%mm3\n\t"
- "movd %%mm4,%[ret]\n\t"
- "movq 0x78(%[buf]),%%mm7\n\t"
- /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
- added to them, and a factor of two removed; correct the final sum here.*/
- "lea -32(%[ret],%[ret]),%[ret]\n\t"
- "movq 0x40(%[buf]),%%mm0\n\t"
- "cmp %[ret2],%[ret]\n\t"
- "movq 0x48(%[buf]),%%mm4\n\t"
- "jae 1f\n\t"
- OC_HADAMARD_ABS_ACCUM_8x4("0x68","0x78")
+ "movq "OC_MEM_OFFS(0x70,buf)",%%mm3\n\t"
+ "movd %%mm4,%[ret2]\n\t"
+ "movq "OC_MEM_OFFS(0x78,buf)",%%mm7\n\t"
+ "movq "OC_MEM_OFFS(0x40,buf)",%%mm0\n\t"
+ "movq "OC_MEM_OFFS(0x48,buf)",%%mm4\n\t"
+ OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
"pmaddwd %%mm7,%%mm0\n\t"
- /*There isn't much to stick in here to hide the latency this time, but the
- alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose
- latency is even worse.*/
- "sub $32,%[ret]\n\t"
+ /*Subtract abs(dc) from 2*ret2.*/
+ "movsx %w[dc],%[dc]\n\t"
+ "cdq\n\t"
+ "lea (%[ret],%[ret2],2),%[ret2]\n\t"
"movq %%mm0,%%mm4\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
+ "xor %[dc],%[ret]\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movd %%mm4,%[ret2]\n\t"
- "lea (%[ret],%[ret2],2),%[ret]\n\t"
- ".p2align 4,,15\n\t"
- "1:\n\t"
- /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
+ added to them, a factor of two removed, and the DC value included;
+ correct the final sum here.*/
+ "sub %[ret],%[ret2]\n\t"
+ "movd %%mm4,%[ret]\n\t"
+ "lea -64(%[ret2],%[ret],2),%[ret]\n\t"
+ /*Although it looks like we're using 8 registers here, gcc can alias %[ret]
and %[ret2] with some of the inputs, since for once we don't write to
- them until after we're done using everything but %[buf] (which is also
- listed as an output to ensure gcc _doesn't_ alias them against it).*/
+ them until after we're done using everything but %[buf].*/
/*Note that _src_ystride and _ref_ystride must be given non-overlapping
constraints, otherewise if gcc can prove they're equal it will allocate
them to the same register (which is bad); _src and _ref face a similar
problem, though those are never actually the same.*/
- :[ret]"=a"(ret),[ret2]"=r"(ret2),[buf]"+r"(bufp)
+ :[ret]"=d"(ret),[ret2]"=r"(ret2),[dc]"=a"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,64))
:[src]"r"(_src),[src_ystride]"c"((ptrdiff_t)_src_ystride),
- [ref]"r"(_ref),[ref_ystride]"d"((ptrdiff_t)_ref_ystride),
- [thresh]"m"(_thresh)
+ [ref]"r"(_ref),[ref_ystride]"d"((ptrdiff_t)_ref_ystride)
/*We have to use neg, so we actually clobber the condition codes for once
(not to mention cmp, sub, and add).*/
:"cc"
);
+ *_dc=dc;
return ret;
}
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh);
+unsigned oc_enc_frag_satd_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,_ref,_ystride);
}
/*Our internal implementation of frag_copy2 takes an extra stride parameter so
- we can share code with oc_enc_frag_satd2_thresh_mmxext().*/
-static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
+ we can share code with oc_enc_frag_satd2_mmxext().*/
+void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){
__asm__ __volatile__(
/*Load the first 3 rows.*/
@@ -649,55 +653,53 @@ static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
"psubb %%mm4,%%mm2\n\t"
/*%%mm2 (row 7) is done, write it out.*/
"movq %%mm2,(%[dst],%[dst_ystride])\n\t"
- :[dst]"+r"(_dst),[src1]"+%r"(_src1),[src2]"+r"(_src2)
+ :[dst]"+r"(_dst),[src1]"+r"(_src1),[src2]"+r"(_src2)
:[dst_ystride]"r"((ptrdiff_t)_dst_ystride),
[src_ystride]"r"((ptrdiff_t)_src_ystride)
:"memory"
);
}
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
+unsigned oc_enc_frag_satd2_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
OC_ALIGN8(unsigned char ref[64]);
oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh);
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,ref,8);
}
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
- int _ystride){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret;
- unsigned ret2;
- bufp=buf;
+unsigned oc_enc_frag_intra_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _ystride){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ unsigned ret;
+ unsigned ret2;
+ int dc;
__asm__ __volatile__(
- OC_LOAD_8x4("0x00")
+ OC_LOAD_8x4(0x00)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x00")
+ OC_TRANSPOSE_4x4x2(0x00)
/*Finish swapping out this 8x4 block to make room for the next one.
mm0...mm3 have been swapped out already.*/
- "movq %%mm4,0x00(%[buf])\n\t"
- "movq %%mm5,0x10(%[buf])\n\t"
- "movq %%mm6,0x20(%[buf])\n\t"
- "movq %%mm7,0x30(%[buf])\n\t"
- OC_LOAD_8x4("0x04")
+ "movq %%mm4,"OC_MEM_OFFS(0x00,buf)"\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x10,buf)"\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x20,buf)"\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x30,buf)"\n\t"
+ OC_LOAD_8x4(0x04)
OC_HADAMARD_8x4
- OC_TRANSPOSE_4x4x2("0x08")
+ OC_TRANSPOSE_4x4x2(0x08)
/*Here the first 4x4 block of output from the last transpose is the second
4x4 block of input for the next transform.
We have cleverly arranged that it already be in the appropriate place, so
we only have to do half the loads.*/
- "movq 0x10(%[buf]),%%mm1\n\t"
- "movq 0x20(%[buf]),%%mm2\n\t"
- "movq 0x30(%[buf]),%%mm3\n\t"
- "movq 0x00(%[buf]),%%mm0\n\t"
+ "movq "OC_MEM_OFFS(0x10,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x20,buf)",%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x30,buf)",%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x00,buf)",%%mm0\n\t"
/*We split out the stages here so we can save the DC coefficient in the
middle.*/
OC_HADAMARD_AB_8x4
- OC_HADAMARD_C_ABS_ACCUM_A_8x4("0x28","0x38")
- "movd %%mm1,%[ret]\n\t"
- OC_HADAMARD_C_ABS_ACCUM_B_8x4("0x28","0x38")
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
+ "movd %%mm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
for the factor of two we dropped + 3 for the vertical accumulation).
@@ -705,41 +707,43 @@ unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
latency of pmaddwd by starting the next series of loads now.*/
"pmaddwd %%mm7,%%mm0\n\t"
- "movq 0x50(%[buf]),%%mm1\n\t"
- "movq 0x58(%[buf]),%%mm5\n\t"
- "movq 0x60(%[buf]),%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x50,buf)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x58,buf)",%%mm5\n\t"
+ "movq "OC_MEM_OFFS(0x60,buf)",%%mm2\n\t"
"movq %%mm0,%%mm4\n\t"
- "movq 0x68(%[buf]),%%mm6\n\t"
+ "movq "OC_MEM_OFFS(0x68,buf)",%%mm6\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
- "movq 0x70(%[buf]),%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x70,buf)",%%mm3\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movq 0x78(%[buf]),%%mm7\n\t"
- "movd %%mm4,%[ret2]\n\t"
- "movq 0x40(%[buf]),%%mm0\n\t"
- "movq 0x48(%[buf]),%%mm4\n\t"
- OC_HADAMARD_ABS_ACCUM_8x4("0x68","0x78")
+ "movq "OC_MEM_OFFS(0x78,buf)",%%mm7\n\t"
+ "movd %%mm4,%[ret]\n\t"
+ "movq "OC_MEM_OFFS(0x40,buf)",%%mm0\n\t"
+ "movq "OC_MEM_OFFS(0x48,buf)",%%mm4\n\t"
+ OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
"pmaddwd %%mm7,%%mm0\n\t"
/*We assume that the DC coefficient is always positive (which is true,
because the input to the INTRA transform was not a difference).*/
- "movzx %w[ret],%[ret]\n\t"
- "add %[ret2],%[ret2]\n\t"
- "sub %[ret],%[ret2]\n\t"
+ "movzx %w[dc],%[dc]\n\t"
+ "add %[ret],%[ret]\n\t"
+ "sub %[dc],%[ret]\n\t"
"movq %%mm0,%%mm4\n\t"
"punpckhdq %%mm0,%%mm0\n\t"
"paddd %%mm0,%%mm4\n\t"
- "movd %%mm4,%[ret]\n\t"
- "lea -64(%[ret2],%[ret],2),%[ret]\n\t"
- /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ "movd %%mm4,%[ret2]\n\t"
+ "lea -64(%[ret],%[ret2],2),%[ret]\n\t"
+ /*Although it looks like we're using 8 registers here, gcc can alias %[ret]
and %[ret2] with some of the inputs, since for once we don't write to
them until after we're done using everything but %[buf] (which is also
listed as an output to ensure gcc _doesn't_ alias them against it).*/
- :[ret]"=a"(ret),[ret2]"=r"(ret2),[buf]"+r"(bufp)
+ :[ret]"=a"(ret),[ret2]"=r"(ret2),[dc]"=r"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,64))
:[src]"r"(_src),[src4]"r"(_src+4*_ystride),
[ystride]"r"((ptrdiff_t)_ystride),[ystride3]"r"((ptrdiff_t)3*_ystride)
/*We have to use sub, so we actually clobber the condition codes for once
(not to mention add).*/
:"cc"
);
+ *_dc=dc;
return ret;
}
diff --git a/thirdparty/libtheora/x86/mmxfdct.c b/thirdparty/libtheora/x86/mmxfdct.c
index 211875255e..17668358b8 100644
--- a/thirdparty/libtheora/x86/mmxfdct.c
+++ b/thirdparty/libtheora/x86/mmxfdct.c
@@ -12,6 +12,7 @@
/*MMX fDCT implementation for x86_32*/
/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
#include "x86enc.h"
+#include "x86zigzag.h"
#if defined(OC_X86_ASM)
@@ -462,8 +463,9 @@
mm7 = d3 c3 b3 a3*/ \
/*MMX implementation of the fDCT.*/
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- ptrdiff_t a;
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ptrdiff_t a;
__asm__ __volatile__(
/*Add two extra bits of working precision to improve accuracy; any more and
we could overflow.*/
@@ -586,77 +588,88 @@ void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
"movq 0x30(%[y]),%%mm3\n\t"
OC_FDCT_STAGE1_8x4
OC_FDCT8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38")
- OC_TRANSPOSE8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38")
- /*mm0={-2}x4*/
- "pcmpeqw %%mm0,%%mm0\n\t"
- "paddw %%mm0,%%mm0\n\t"
- /*Round the results.*/
- "psubw %%mm0,%%mm1\n\t"
- "psubw %%mm0,%%mm2\n\t"
- "psraw $2,%%mm1\n\t"
- "psubw %%mm0,%%mm3\n\t"
- "movq %%mm1,0x18(%[y])\n\t"
- "psraw $2,%%mm2\n\t"
- "psubw %%mm0,%%mm4\n\t"
- "movq 0x08(%[y]),%%mm1\n\t"
- "psraw $2,%%mm3\n\t"
- "psubw %%mm0,%%mm5\n\t"
+ /*mm2={-2}x4*/
+ "pcmpeqw %%mm2,%%mm2\n\t"
+ "paddw %%mm2,%%mm2\n\t"
+ /*Round and store the results (no transpose).*/
+ "movq 0x10(%[y]),%%mm7\n\t"
+ "psubw %%mm2,%%mm4\n\t"
+ "psubw %%mm2,%%mm6\n\t"
"psraw $2,%%mm4\n\t"
- "psubw %%mm0,%%mm6\n\t"
- "psraw $2,%%mm5\n\t"
- "psubw %%mm0,%%mm7\n\t"
+ "psubw %%mm2,%%mm0\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x00,buf)"\n\t"
+ "movq 0x30(%[y]),%%mm4\n\t"
"psraw $2,%%mm6\n\t"
- "psubw %%mm0,%%mm1\n\t"
+ "psubw %%mm2,%%mm5\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x20,buf)"\n\t"
+ "psraw $2,%%mm0\n\t"
+ "psubw %%mm2,%%mm3\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x40,buf)"\n\t"
+ "psraw $2,%%mm5\n\t"
+ "psubw %%mm2,%%mm1\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x50,buf)"\n\t"
+ "psraw $2,%%mm3\n\t"
+ "psubw %%mm2,%%mm7\n\t"
+ "movq %%mm3,"OC_MEM_OFFS(0x60,buf)"\n\t"
+ "psraw $2,%%mm1\n\t"
+ "psubw %%mm2,%%mm4\n\t"
+ "movq %%mm1,"OC_MEM_OFFS(0x70,buf)"\n\t"
"psraw $2,%%mm7\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x10,buf)"\n\t"
+ "psraw $2,%%mm4\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x30,buf)"\n\t"
+ /*Load the next block.*/
"movq 0x40(%[y]),%%mm0\n\t"
- "psraw $2,%%mm1\n\t"
- "movq %%mm7,0x30(%[y])\n\t"
"movq 0x78(%[y]),%%mm7\n\t"
- "movq %%mm1,0x08(%[y])\n\t"
"movq 0x50(%[y]),%%mm1\n\t"
- "movq %%mm6,0x20(%[y])\n\t"
"movq 0x68(%[y]),%%mm6\n\t"
- "movq %%mm2,0x28(%[y])\n\t"
"movq 0x60(%[y]),%%mm2\n\t"
- "movq %%mm5,0x10(%[y])\n\t"
"movq 0x58(%[y]),%%mm5\n\t"
- "movq %%mm3,0x38(%[y])\n\t"
"movq 0x70(%[y]),%%mm3\n\t"
- "movq %%mm4,0x00(%[y])\n\t"
"movq 0x48(%[y]),%%mm4\n\t"
OC_FDCT_STAGE1_8x4
OC_FDCT8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78")
- OC_TRANSPOSE8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78")
- /*mm0={-2}x4*/
- "pcmpeqw %%mm0,%%mm0\n\t"
- "paddw %%mm0,%%mm0\n\t"
- /*Round the results.*/
- "psubw %%mm0,%%mm1\n\t"
- "psubw %%mm0,%%mm2\n\t"
- "psraw $2,%%mm1\n\t"
- "psubw %%mm0,%%mm3\n\t"
- "movq %%mm1,0x58(%[y])\n\t"
- "psraw $2,%%mm2\n\t"
- "psubw %%mm0,%%mm4\n\t"
- "movq 0x48(%[y]),%%mm1\n\t"
- "psraw $2,%%mm3\n\t"
- "psubw %%mm0,%%mm5\n\t"
- "movq %%mm2,0x68(%[y])\n\t"
+ /*mm2={-2}x4*/
+ "pcmpeqw %%mm2,%%mm2\n\t"
+ "paddw %%mm2,%%mm2\n\t"
+ /*Round and store the results (no transpose).*/
+ "movq 0x50(%[y]),%%mm7\n\t"
+ "psubw %%mm2,%%mm4\n\t"
+ "psubw %%mm2,%%mm6\n\t"
"psraw $2,%%mm4\n\t"
- "psubw %%mm0,%%mm6\n\t"
- "movq %%mm3,0x78(%[y])\n\t"
- "psraw $2,%%mm5\n\t"
- "psubw %%mm0,%%mm7\n\t"
- "movq %%mm4,0x40(%[y])\n\t"
+ "psubw %%mm2,%%mm0\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x08,buf)"\n\t"
+ "movq 0x70(%[y]),%%mm4\n\t"
"psraw $2,%%mm6\n\t"
- "psubw %%mm0,%%mm1\n\t"
- "movq %%mm5,0x50(%[y])\n\t"
- "psraw $2,%%mm7\n\t"
- "movq %%mm6,0x60(%[y])\n\t"
+ "psubw %%mm2,%%mm5\n\t"
+ "movq %%mm6,"OC_MEM_OFFS(0x28,buf)"\n\t"
+ "psraw $2,%%mm0\n\t"
+ "psubw %%mm2,%%mm3\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x48,buf)"\n\t"
+ "psraw $2,%%mm5\n\t"
+ "psubw %%mm2,%%mm1\n\t"
+ "movq %%mm5,"OC_MEM_OFFS(0x58,buf)"\n\t"
+ "psraw $2,%%mm3\n\t"
+ "psubw %%mm2,%%mm7\n\t"
+ "movq %%mm3,"OC_MEM_OFFS(0x68,buf)"\n\t"
"psraw $2,%%mm1\n\t"
- "movq %%mm7,0x70(%[y])\n\t"
- "movq %%mm1,0x48(%[y])\n\t"
- :[a]"=&r"(a)
+ "psubw %%mm2,%%mm4\n\t"
+ "movq %%mm1,"OC_MEM_OFFS(0x78,buf)"\n\t"
+ "psraw $2,%%mm7\n\t"
+ "movq %%mm7,"OC_MEM_OFFS(0x18,buf)"\n\t"
+ "psraw $2,%%mm4\n\t"
+ "movq %%mm4,"OC_MEM_OFFS(0x38,buf)"\n\t"
+ /*Final transpose and zig-zag.*/
+#define OC_ZZ_LOAD_ROW_LO(_row,_reg) \
+ "movq "OC_MEM_OFFS(16*_row,buf)","_reg"\n\t" \
+
+#define OC_ZZ_LOAD_ROW_HI(_row,_reg) \
+ "movq "OC_MEM_OFFS(16*_row+8,buf)","_reg"\n\t" \
+
+ OC_TRANSPOSE_ZIG_ZAG_MMXEXT
+#undef OC_ZZ_LOAD_ROW_LO
+#undef OC_ZZ_LOAD_ROW_HI
+ :[a]"=&r"(a),[buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,64))
:[y]"r"(_y),[x]"r"(_x)
:"memory"
);
diff --git a/thirdparty/libtheora/x86/mmxfrag.c b/thirdparty/libtheora/x86/mmxfrag.c
index 2c732939c3..b3ec508956 100644
--- a/thirdparty/libtheora/x86/mmxfrag.c
+++ b/thirdparty/libtheora/x86/mmxfrag.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxfrag.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -22,17 +22,92 @@
The iteration each instruction belongs to is marked in the comments as #i.*/
#include <stddef.h>
#include "x86int.h"
-#include "mmxfrag.h"
#if defined(OC_X86_ASM)
/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
between rows.*/
+# define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
+ do{ \
+ const unsigned char *src; \
+ unsigned char *dst; \
+ ptrdiff_t ystride3; \
+ src=(_src); \
+ dst=(_dst); \
+ __asm__ __volatile__( \
+ /*src+0*ystride*/ \
+ "movq (%[src]),%%mm0\n\t" \
+ /*src+1*ystride*/ \
+ "movq (%[src],%[ystride]),%%mm1\n\t" \
+ /*ystride3=ystride*3*/ \
+ "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" \
+ /*src+2*ystride*/ \
+ "movq (%[src],%[ystride],2),%%mm2\n\t" \
+ /*src+3*ystride*/ \
+ "movq (%[src],%[ystride3]),%%mm3\n\t" \
+ /*dst+0*ystride*/ \
+ "movq %%mm0,(%[dst])\n\t" \
+ /*dst+1*ystride*/ \
+ "movq %%mm1,(%[dst],%[ystride])\n\t" \
+ /*Pointer to next 4.*/ \
+ "lea (%[src],%[ystride],4),%[src]\n\t" \
+ /*dst+2*ystride*/ \
+ "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
+ /*dst+3*ystride*/ \
+ "movq %%mm3,(%[dst],%[ystride3])\n\t" \
+ /*Pointer to next 4.*/ \
+ "lea (%[dst],%[ystride],4),%[dst]\n\t" \
+ /*src+0*ystride*/ \
+ "movq (%[src]),%%mm0\n\t" \
+ /*src+1*ystride*/ \
+ "movq (%[src],%[ystride]),%%mm1\n\t" \
+ /*src+2*ystride*/ \
+ "movq (%[src],%[ystride],2),%%mm2\n\t" \
+ /*src+3*ystride*/ \
+ "movq (%[src],%[ystride3]),%%mm3\n\t" \
+ /*dst+0*ystride*/ \
+ "movq %%mm0,(%[dst])\n\t" \
+ /*dst+1*ystride*/ \
+ "movq %%mm1,(%[dst],%[ystride])\n\t" \
+ /*dst+2*ystride*/ \
+ "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
+ /*dst+3*ystride*/ \
+ "movq %%mm3,(%[dst],%[ystride3])\n\t" \
+ :[dst]"+r"(dst),[src]"+r"(src),[ystride3]"=&r"(ystride3) \
+ :[ystride]"r"((ptrdiff_t)(_ystride)) \
+ :"memory" \
+ ); \
+ } \
+ while(0)
+
+/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
+ between rows.*/
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride){
OC_FRAG_COPY_MMX(_dst,_src,_ystride);
}
+/*Copies the fragments specified by the lists of fragment indices from one
+ frame to another.
+ _dst_frame: The reference frame to copy to.
+ _src_frame: The reference frame to copy from.
+ _ystride: The row stride of the reference frames.
+ _fragis: A pointer to a list of fragment indices.
+ _nfragis: The number of fragment indices to copy.
+ _frag_buf_offs: The offsets of fragments in the reference frames.*/
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs){
+ ptrdiff_t fragii;
+ for(fragii=0;fragii<_nfragis;fragii++){
+ ptrdiff_t frag_buf_off;
+ frag_buf_off=_frag_buf_offs[_fragis[fragii]];
+ OC_FRAG_COPY_MMX(_dst_frame+frag_buf_off,
+ _src_frame+frag_buf_off,_ystride);
+ }
+}
+
+
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue){
__asm__ __volatile__(
@@ -280,7 +355,7 @@ void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
/*Advance dest ptr.*/
"lea (%[dst],%[ystride],2),%[dst]\n\t"
:[dst]"+r"(_dst),[residue]"+r"(_residue),
- [src1]"+%r"(_src1),[src2]"+r"(_src2)
+ [src1]"+r"(_src1),[src2]"+r"(_src2)
:[ystride]"r"((ptrdiff_t)_ystride)
:"memory"
);
diff --git a/thirdparty/libtheora/x86/mmxfrag.h b/thirdparty/libtheora/x86/mmxfrag.h
deleted file mode 100644
index a398427629..0000000000
--- a/thirdparty/libtheora/x86/mmxfrag.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#if !defined(_x86_mmxfrag_H)
-# define _x86_mmxfrag_H (1)
-# include <stddef.h>
-# include "x86int.h"
-
-#if defined(OC_X86_ASM)
-
-/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
- between rows.*/
-#define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
- do{ \
- const unsigned char *src; \
- unsigned char *dst; \
- ptrdiff_t ystride3; \
- src=(_src); \
- dst=(_dst); \
- __asm__ __volatile__( \
- /*src+0*ystride*/ \
- "movq (%[src]),%%mm0\n\t" \
- /*src+1*ystride*/ \
- "movq (%[src],%[ystride]),%%mm1\n\t" \
- /*ystride3=ystride*3*/ \
- "lea (%[ystride],%[ystride],2),%[ystride3]\n\t" \
- /*src+2*ystride*/ \
- "movq (%[src],%[ystride],2),%%mm2\n\t" \
- /*src+3*ystride*/ \
- "movq (%[src],%[ystride3]),%%mm3\n\t" \
- /*dst+0*ystride*/ \
- "movq %%mm0,(%[dst])\n\t" \
- /*dst+1*ystride*/ \
- "movq %%mm1,(%[dst],%[ystride])\n\t" \
- /*Pointer to next 4.*/ \
- "lea (%[src],%[ystride],4),%[src]\n\t" \
- /*dst+2*ystride*/ \
- "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
- /*dst+3*ystride*/ \
- "movq %%mm3,(%[dst],%[ystride3])\n\t" \
- /*Pointer to next 4.*/ \
- "lea (%[dst],%[ystride],4),%[dst]\n\t" \
- /*src+0*ystride*/ \
- "movq (%[src]),%%mm0\n\t" \
- /*src+1*ystride*/ \
- "movq (%[src],%[ystride]),%%mm1\n\t" \
- /*src+2*ystride*/ \
- "movq (%[src],%[ystride],2),%%mm2\n\t" \
- /*src+3*ystride*/ \
- "movq (%[src],%[ystride3]),%%mm3\n\t" \
- /*dst+0*ystride*/ \
- "movq %%mm0,(%[dst])\n\t" \
- /*dst+1*ystride*/ \
- "movq %%mm1,(%[dst],%[ystride])\n\t" \
- /*dst+2*ystride*/ \
- "movq %%mm2,(%[dst],%[ystride],2)\n\t" \
- /*dst+3*ystride*/ \
- "movq %%mm3,(%[dst],%[ystride3])\n\t" \
- :[dst]"+r"(dst),[src]"+r"(src),[ystride3]"=&r"(ystride3) \
- :[ystride]"r"((ptrdiff_t)(_ystride)) \
- :"memory" \
- ); \
- } \
- while(0)
-
-# endif
-#endif
diff --git a/thirdparty/libtheora/x86/mmxidct.c b/thirdparty/libtheora/x86/mmxidct.c
index 76424e6364..b8e3077066 100644
--- a/thirdparty/libtheora/x86/mmxidct.c
+++ b/thirdparty/libtheora/x86/mmxidct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -30,89 +30,66 @@
-/*A table of constants used by the MMX routines.*/
-static const ogg_uint16_t __attribute__((aligned(8),used))
- OC_IDCT_CONSTS[(7+1)*4]={
- (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
- (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
- (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
- (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
- (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
- (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
- (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
- (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
- (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
- (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
- (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
- (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
- (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- 8, 8, 8, 8
-};
-
-/*Converts the expression in the argument to a string.*/
-#define OC_M2STR(_s) #_s
-
/*38 cycles*/
-#define OC_IDCT_BEGIN \
+#define OC_IDCT_BEGIN(_y,_x) \
"#OC_IDCT_BEGIN\n\t" \
- "movq "OC_I(3)",%%mm2\n\t" \
- "movq "OC_C(3)",%%mm6\n\t" \
+ "movq "OC_I(3,_x)",%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x30,c)",%%mm6\n\t" \
"movq %%mm2,%%mm4\n\t" \
- "movq "OC_J(5)",%%mm7\n\t" \
+ "movq "OC_J(5,_x)",%%mm7\n\t" \
"pmulhw %%mm6,%%mm4\n\t" \
- "movq "OC_C(5)",%%mm1\n\t" \
+ "movq "OC_MEM_OFFS(0x50,c)",%%mm1\n\t" \
"pmulhw %%mm7,%%mm6\n\t" \
"movq %%mm1,%%mm5\n\t" \
"pmulhw %%mm2,%%mm1\n\t" \
- "movq "OC_I(1)",%%mm3\n\t" \
+ "movq "OC_I(1,_x)",%%mm3\n\t" \
"pmulhw %%mm7,%%mm5\n\t" \
- "movq "OC_C(1)",%%mm0\n\t" \
+ "movq "OC_MEM_OFFS(0x10,c)",%%mm0\n\t" \
"paddw %%mm2,%%mm4\n\t" \
"paddw %%mm7,%%mm6\n\t" \
"paddw %%mm1,%%mm2\n\t" \
- "movq "OC_J(7)",%%mm1\n\t" \
+ "movq "OC_J(7,_x)",%%mm1\n\t" \
"paddw %%mm5,%%mm7\n\t" \
"movq %%mm0,%%mm5\n\t" \
"pmulhw %%mm3,%%mm0\n\t" \
"paddw %%mm7,%%mm4\n\t" \
"pmulhw %%mm1,%%mm5\n\t" \
- "movq "OC_C(7)",%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x70,c)",%%mm7\n\t" \
"psubw %%mm2,%%mm6\n\t" \
"paddw %%mm3,%%mm0\n\t" \
"pmulhw %%mm7,%%mm3\n\t" \
- "movq "OC_I(2)",%%mm2\n\t" \
+ "movq "OC_I(2,_x)",%%mm2\n\t" \
"pmulhw %%mm1,%%mm7\n\t" \
"paddw %%mm1,%%mm5\n\t" \
"movq %%mm2,%%mm1\n\t" \
- "pmulhw "OC_C(2)",%%mm2\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x20,c)",%%mm2\n\t" \
"psubw %%mm5,%%mm3\n\t" \
- "movq "OC_J(6)",%%mm5\n\t" \
+ "movq "OC_J(6,_x)",%%mm5\n\t" \
"paddw %%mm7,%%mm0\n\t" \
"movq %%mm5,%%mm7\n\t" \
"psubw %%mm4,%%mm0\n\t" \
- "pmulhw "OC_C(2)",%%mm5\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x20,c)",%%mm5\n\t" \
"paddw %%mm1,%%mm2\n\t" \
- "pmulhw "OC_C(6)",%%mm1\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x60,c)",%%mm1\n\t" \
"paddw %%mm4,%%mm4\n\t" \
"paddw %%mm0,%%mm4\n\t" \
"psubw %%mm6,%%mm3\n\t" \
"paddw %%mm7,%%mm5\n\t" \
"paddw %%mm6,%%mm6\n\t" \
- "pmulhw "OC_C(6)",%%mm7\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x60,c)",%%mm7\n\t" \
"paddw %%mm3,%%mm6\n\t" \
- "movq %%mm4,"OC_I(1)"\n\t" \
+ "movq %%mm4,"OC_I(1,_y)"\n\t" \
"psubw %%mm5,%%mm1\n\t" \
- "movq "OC_C(4)",%%mm4\n\t" \
+ "movq "OC_MEM_OFFS(0x40,c)",%%mm4\n\t" \
"movq %%mm3,%%mm5\n\t" \
"pmulhw %%mm4,%%mm3\n\t" \
"paddw %%mm2,%%mm7\n\t" \
- "movq %%mm6,"OC_I(2)"\n\t" \
+ "movq %%mm6,"OC_I(2,_y)"\n\t" \
"movq %%mm0,%%mm2\n\t" \
- "movq "OC_I(0)",%%mm6\n\t" \
+ "movq "OC_I(0,_x)",%%mm6\n\t" \
"pmulhw %%mm4,%%mm0\n\t" \
"paddw %%mm3,%%mm5\n\t" \
- "movq "OC_J(4)",%%mm3\n\t" \
+ "movq "OC_J(4,_x)",%%mm3\n\t" \
"psubw %%mm1,%%mm5\n\t" \
"paddw %%mm0,%%mm2\n\t" \
"psubw %%mm3,%%mm6\n\t" \
@@ -126,18 +103,18 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"paddw %%mm0,%%mm6\n\t" \
"psubw %%mm2,%%mm6\n\t" \
"paddw %%mm2,%%mm2\n\t" \
- "movq "OC_I(1)",%%mm0\n\t" \
+ "movq "OC_I(1,_y)",%%mm0\n\t" \
"paddw %%mm6,%%mm2\n\t" \
"paddw %%mm3,%%mm4\n\t" \
"psubw %%mm1,%%mm2\n\t" \
"#end OC_IDCT_BEGIN\n\t" \
/*38+8=46 cycles.*/
-#define OC_ROW_IDCT \
+#define OC_ROW_IDCT(_y,_x) \
"#OC_ROW_IDCT\n" \
- OC_IDCT_BEGIN \
+ OC_IDCT_BEGIN(_y,_x) \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r4=E'=E-G*/ \
"psubw %%mm7,%%mm4\n\t" \
/*r1=H'+H'*/ \
@@ -162,7 +139,7 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"psubw %%mm0,%%mm7\n\t" \
"paddw %%mm0,%%mm0\n\t" \
/*Save R1.*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r0=R0=G.+C.*/ \
"paddw %%mm7,%%mm0\n\t" \
"#end OC_ROW_IDCT\n\t" \
@@ -195,11 +172,11 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
Since r1 is free at entry, we calculate the Js first.*/
/*19 cycles.*/
-#define OC_TRANSPOSE \
+#define OC_TRANSPOSE(_y) \
"#OC_TRANSPOSE\n\t" \
"movq %%mm4,%%mm1\n\t" \
"punpcklwd %%mm5,%%mm4\n\t" \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"punpckhwd %%mm5,%%mm1\n\t" \
"movq %%mm6,%%mm0\n\t" \
"punpcklwd %%mm7,%%mm6\n\t" \
@@ -207,17 +184,17 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"punpckldq %%mm6,%%mm4\n\t" \
"punpckhdq %%mm6,%%mm5\n\t" \
"movq %%mm1,%%mm6\n\t" \
- "movq %%mm4,"OC_J(4)"\n\t" \
+ "movq %%mm4,"OC_J(4,_y)"\n\t" \
"punpckhwd %%mm7,%%mm0\n\t" \
- "movq %%mm5,"OC_J(5)"\n\t" \
+ "movq %%mm5,"OC_J(5,_y)"\n\t" \
"punpckhdq %%mm0,%%mm6\n\t" \
- "movq "OC_I(0)",%%mm4\n\t" \
+ "movq "OC_I(0,_y)",%%mm4\n\t" \
"punpckldq %%mm0,%%mm1\n\t" \
- "movq "OC_I(1)",%%mm5\n\t" \
+ "movq "OC_I(1,_y)",%%mm5\n\t" \
"movq %%mm4,%%mm0\n\t" \
- "movq %%mm6,"OC_J(7)"\n\t" \
+ "movq %%mm6,"OC_J(7,_y)"\n\t" \
"punpcklwd %%mm5,%%mm0\n\t" \
- "movq %%mm1,"OC_J(6)"\n\t" \
+ "movq %%mm1,"OC_J(6,_y)"\n\t" \
"punpckhwd %%mm5,%%mm4\n\t" \
"movq %%mm2,%%mm5\n\t" \
"punpcklwd %%mm3,%%mm2\n\t" \
@@ -225,20 +202,20 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"punpckldq %%mm2,%%mm0\n\t" \
"punpckhdq %%mm2,%%mm1\n\t" \
"movq %%mm4,%%mm2\n\t" \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"punpckhwd %%mm3,%%mm5\n\t" \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
"punpckhdq %%mm5,%%mm4\n\t" \
"punpckldq %%mm5,%%mm2\n\t" \
- "movq %%mm4,"OC_I(3)"\n\t" \
- "movq %%mm2,"OC_I(2)"\n\t" \
+ "movq %%mm4,"OC_I(3,_y)"\n\t" \
+ "movq %%mm2,"OC_I(2,_y)"\n\t" \
"#end OC_TRANSPOSE\n\t" \
/*38+19=57 cycles.*/
-#define OC_COLUMN_IDCT \
+#define OC_COLUMN_IDCT(_y) \
"#OC_COLUMN_IDCT\n" \
- OC_IDCT_BEGIN \
- "paddw "OC_8",%%mm2\n\t" \
+ OC_IDCT_BEGIN(_y,_y) \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm2\n\t" \
/*r1=H'+H'*/ \
"paddw %%mm1,%%mm1\n\t" \
/*r1=R1=A''+H'*/ \
@@ -250,18 +227,18 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
/*r1=NR1*/ \
"psraw $4,%%mm1\n\t" \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r7=G+G*/ \
"paddw %%mm7,%%mm7\n\t" \
/*Store NR2 at I(2).*/ \
- "movq %%mm2,"OC_I(2)"\n\t" \
+ "movq %%mm2,"OC_I(2,_y)"\n\t" \
/*r7=G'=E+G*/ \
"paddw %%mm4,%%mm7\n\t" \
/*Store NR1 at I(1).*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r4=R4=E'-D'*/ \
"psubw %%mm3,%%mm4\n\t" \
- "paddw "OC_8",%%mm4\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm4\n\t" \
/*r3=D'+D'*/ \
"paddw %%mm3,%%mm3\n\t" \
/*r3=R3=E'+D'*/ \
@@ -272,7 +249,7 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
"psubw %%mm5,%%mm6\n\t" \
/*r3=NR3*/ \
"psraw $4,%%mm3\n\t" \
- "paddw "OC_8",%%mm6\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm6\n\t" \
/*r5=B''+B''*/ \
"paddw %%mm5,%%mm5\n\t" \
/*r5=R5=F'+B''*/ \
@@ -280,14 +257,14 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
/*r6=NR6*/ \
"psraw $4,%%mm6\n\t" \
/*Store NR4 at J(4).*/ \
- "movq %%mm4,"OC_J(4)"\n\t" \
+ "movq %%mm4,"OC_J(4,_y)"\n\t" \
/*r5=NR5*/ \
"psraw $4,%%mm5\n\t" \
/*Store NR3 at I(3).*/ \
- "movq %%mm3,"OC_I(3)"\n\t" \
+ "movq %%mm3,"OC_I(3,_y)"\n\t" \
/*r7=R7=G'-C'*/ \
"psubw %%mm0,%%mm7\n\t" \
- "paddw "OC_8",%%mm7\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm7\n\t" \
/*r0=C'+C'*/ \
"paddw %%mm0,%%mm0\n\t" \
/*r0=R0=G'+C'*/ \
@@ -295,113 +272,121 @@ static const ogg_uint16_t __attribute__((aligned(8),used))
/*r7=NR7*/ \
"psraw $4,%%mm7\n\t" \
/*Store NR6 at J(6).*/ \
- "movq %%mm6,"OC_J(6)"\n\t" \
+ "movq %%mm6,"OC_J(6,_y)"\n\t" \
/*r0=NR0*/ \
"psraw $4,%%mm0\n\t" \
/*Store NR5 at J(5).*/ \
- "movq %%mm5,"OC_J(5)"\n\t" \
+ "movq %%mm5,"OC_J(5,_y)"\n\t" \
/*Store NR7 at J(7).*/ \
- "movq %%mm7,"OC_J(7)"\n\t" \
+ "movq %%mm7,"OC_J(7,_y)"\n\t" \
/*Store NR0 at I(0).*/ \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"#end OC_COLUMN_IDCT\n\t" \
-#define OC_MID(_m,_i) OC_M2STR(_m+(_i)*8)"(%[c])"
-#define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1)
-#define OC_8 OC_MID(OC_EIGHT_OFFSET,0)
-
-static void oc_idct8x8_slow(ogg_int16_t _y[64]){
+static void oc_idct8x8_slow_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ int i;
/*This routine accepts an 8x8 matrix, but in partially transposed form.
Every 4x4 block is transposed.*/
__asm__ __volatile__(
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_M2STR(((_k-4)*16)+8)"(%[y])"
- OC_ROW_IDCT
- OC_TRANSPOSE
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_MEM_OFFS(((_k)-4)*16+8,_y)
+ OC_ROW_IDCT(y,x)
+ OC_TRANSPOSE(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16)+64)"(%[y])"
-#define OC_J(_k) OC_M2STR(((_k-4)*16)+72)"(%[y])"
- OC_ROW_IDCT
- OC_TRANSPOSE
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16+64,_y)
+#define OC_J(_k,_y) OC_MEM_OFFS(((_k)-4)*16+72,_y)
+ OC_ROW_IDCT(y,x)
+ OC_TRANSPOSE(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16)+8)"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16+8,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(y)
#undef OC_I
#undef OC_J
- :
- :[y]"r"(_y),[c]"r"(OC_IDCT_CONSTS)
+ :[y]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_y,64)
+ :[x]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64),
+ [c]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128)
);
+ __asm__ __volatile__("pxor %%mm0,%%mm0\n\t"::);
+ for(i=0;i<4;i++){
+ __asm__ __volatile__(
+ "movq %%mm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x08,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x18,x)"\n\t"
+ :[x]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_x+16*i,16)
+ );
+ }
}
/*25 cycles.*/
-#define OC_IDCT_BEGIN_10 \
+#define OC_IDCT_BEGIN_10(_y,_x) \
"#OC_IDCT_BEGIN_10\n\t" \
- "movq "OC_I(3)",%%mm2\n\t" \
+ "movq "OC_I(3,_x)",%%mm2\n\t" \
"nop\n\t" \
- "movq "OC_C(3)",%%mm6\n\t" \
+ "movq "OC_MEM_OFFS(0x30,c)",%%mm6\n\t" \
"movq %%mm2,%%mm4\n\t" \
- "movq "OC_C(5)",%%mm1\n\t" \
+ "movq "OC_MEM_OFFS(0x50,c)",%%mm1\n\t" \
"pmulhw %%mm6,%%mm4\n\t" \
- "movq "OC_I(1)",%%mm3\n\t" \
+ "movq "OC_I(1,_x)",%%mm3\n\t" \
"pmulhw %%mm2,%%mm1\n\t" \
- "movq "OC_C(1)",%%mm0\n\t" \
+ "movq "OC_MEM_OFFS(0x10,c)",%%mm0\n\t" \
"paddw %%mm2,%%mm4\n\t" \
"pxor %%mm6,%%mm6\n\t" \
"paddw %%mm1,%%mm2\n\t" \
- "movq "OC_I(2)",%%mm5\n\t" \
+ "movq "OC_I(2,_x)",%%mm5\n\t" \
"pmulhw %%mm3,%%mm0\n\t" \
"movq %%mm5,%%mm1\n\t" \
"paddw %%mm3,%%mm0\n\t" \
- "pmulhw "OC_C(7)",%%mm3\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x70,c)",%%mm3\n\t" \
"psubw %%mm2,%%mm6\n\t" \
- "pmulhw "OC_C(2)",%%mm5\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x20,c)",%%mm5\n\t" \
"psubw %%mm4,%%mm0\n\t" \
- "movq "OC_I(2)",%%mm7\n\t" \
+ "movq "OC_I(2,_x)",%%mm7\n\t" \
"paddw %%mm4,%%mm4\n\t" \
"paddw %%mm5,%%mm7\n\t" \
"paddw %%mm0,%%mm4\n\t" \
- "pmulhw "OC_C(6)",%%mm1\n\t" \
+ "pmulhw "OC_MEM_OFFS(0x60,c)",%%mm1\n\t" \
"psubw %%mm6,%%mm3\n\t" \
- "movq %%mm4,"OC_I(1)"\n\t" \
+ "movq %%mm4,"OC_I(1,_y)"\n\t" \
"paddw %%mm6,%%mm6\n\t" \
- "movq "OC_C(4)",%%mm4\n\t" \
+ "movq "OC_MEM_OFFS(0x40,c)",%%mm4\n\t" \
"paddw %%mm3,%%mm6\n\t" \
"movq %%mm3,%%mm5\n\t" \
"pmulhw %%mm4,%%mm3\n\t" \
- "movq %%mm6,"OC_I(2)"\n\t" \
+ "movq %%mm6,"OC_I(2,_y)"\n\t" \
"movq %%mm0,%%mm2\n\t" \
- "movq "OC_I(0)",%%mm6\n\t" \
+ "movq "OC_I(0,_x)",%%mm6\n\t" \
"pmulhw %%mm4,%%mm0\n\t" \
"paddw %%mm3,%%mm5\n\t" \
"paddw %%mm0,%%mm2\n\t" \
"psubw %%mm1,%%mm5\n\t" \
"pmulhw %%mm4,%%mm6\n\t" \
- "paddw "OC_I(0)",%%mm6\n\t" \
+ "paddw "OC_I(0,_x)",%%mm6\n\t" \
"paddw %%mm1,%%mm1\n\t" \
"movq %%mm6,%%mm4\n\t" \
"paddw %%mm5,%%mm1\n\t" \
"psubw %%mm2,%%mm6\n\t" \
"paddw %%mm2,%%mm2\n\t" \
- "movq "OC_I(1)",%%mm0\n\t" \
+ "movq "OC_I(1,_y)",%%mm0\n\t" \
"paddw %%mm6,%%mm2\n\t" \
"psubw %%mm1,%%mm2\n\t" \
"nop\n\t" \
"#end OC_IDCT_BEGIN_10\n\t" \
/*25+8=33 cycles.*/
-#define OC_ROW_IDCT_10 \
+#define OC_ROW_IDCT_10(_y,_x) \
"#OC_ROW_IDCT_10\n\t" \
- OC_IDCT_BEGIN_10 \
+ OC_IDCT_BEGIN_10(_y,_x) \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r4=E'=E-G*/ \
"psubw %%mm7,%%mm4\n\t" \
/*r1=H'+H'*/ \
@@ -426,16 +411,16 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
"psubw %%mm0,%%mm7\n\t" \
"paddw %%mm0,%%mm0\n\t" \
/*Save R1.*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r0=R0=G'+C'*/ \
"paddw %%mm7,%%mm0\n\t" \
"#end OC_ROW_IDCT_10\n\t" \
/*25+19=44 cycles'*/
-#define OC_COLUMN_IDCT_10 \
+#define OC_COLUMN_IDCT_10(_y) \
"#OC_COLUMN_IDCT_10\n\t" \
- OC_IDCT_BEGIN_10 \
- "paddw "OC_8",%%mm2\n\t" \
+ OC_IDCT_BEGIN_10(_y,_y) \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm2\n\t" \
/*r1=H'+H'*/ \
"paddw %%mm1,%%mm1\n\t" \
/*r1=R1=A''+H'*/ \
@@ -447,18 +432,18 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r1=NR1*/ \
"psraw $4,%%mm1\n\t" \
/*r3=D'*/ \
- "movq "OC_I(2)",%%mm3\n\t" \
+ "movq "OC_I(2,_y)",%%mm3\n\t" \
/*r7=G+G*/ \
"paddw %%mm7,%%mm7\n\t" \
/*Store NR2 at I(2).*/ \
- "movq %%mm2,"OC_I(2)"\n\t" \
+ "movq %%mm2,"OC_I(2,_y)"\n\t" \
/*r7=G'=E+G*/ \
"paddw %%mm4,%%mm7\n\t" \
/*Store NR1 at I(1).*/ \
- "movq %%mm1,"OC_I(1)"\n\t" \
+ "movq %%mm1,"OC_I(1,_y)"\n\t" \
/*r4=R4=E'-D'*/ \
"psubw %%mm3,%%mm4\n\t" \
- "paddw "OC_8",%%mm4\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm4\n\t" \
/*r3=D'+D'*/ \
"paddw %%mm3,%%mm3\n\t" \
/*r3=R3=E'+D'*/ \
@@ -469,7 +454,7 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
"psubw %%mm5,%%mm6\n\t" \
/*r3=NR3*/ \
"psraw $4,%%mm3\n\t" \
- "paddw "OC_8",%%mm6\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm6\n\t" \
/*r5=B''+B''*/ \
"paddw %%mm5,%%mm5\n\t" \
/*r5=R5=F'+B''*/ \
@@ -477,14 +462,14 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r6=NR6*/ \
"psraw $4,%%mm6\n\t" \
/*Store NR4 at J(4).*/ \
- "movq %%mm4,"OC_J(4)"\n\t" \
+ "movq %%mm4,"OC_J(4,_y)"\n\t" \
/*r5=NR5*/ \
"psraw $4,%%mm5\n\t" \
/*Store NR3 at I(3).*/ \
- "movq %%mm3,"OC_I(3)"\n\t" \
+ "movq %%mm3,"OC_I(3,_y)"\n\t" \
/*r7=R7=G'-C'*/ \
"psubw %%mm0,%%mm7\n\t" \
- "paddw "OC_8",%%mm7\n\t" \
+ "paddw "OC_MEM_OFFS(0x00,c)",%%mm7\n\t" \
/*r0=C'+C'*/ \
"paddw %%mm0,%%mm0\n\t" \
/*r0=R0=G'+C'*/ \
@@ -492,46 +477,55 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r7=NR7*/ \
"psraw $4,%%mm7\n\t" \
/*Store NR6 at J(6).*/ \
- "movq %%mm6,"OC_J(6)"\n\t" \
+ "movq %%mm6,"OC_J(6,_y)"\n\t" \
/*r0=NR0*/ \
"psraw $4,%%mm0\n\t" \
/*Store NR5 at J(5).*/ \
- "movq %%mm5,"OC_J(5)"\n\t" \
+ "movq %%mm5,"OC_J(5,_y)"\n\t" \
/*Store NR7 at J(7).*/ \
- "movq %%mm7,"OC_J(7)"\n\t" \
+ "movq %%mm7,"OC_J(7,_y)"\n\t" \
/*Store NR0 at I(0).*/ \
- "movq %%mm0,"OC_I(0)"\n\t" \
+ "movq %%mm0,"OC_I(0,_y)"\n\t" \
"#end OC_COLUMN_IDCT_10\n\t" \
-static void oc_idct8x8_10(ogg_int16_t _y[64]){
+static void oc_idct8x8_10_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64]){
__asm__ __volatile__(
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_M2STR(((_k-4)*16)+8)"(%[y])"
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_MEM_OFFS(((_k)-4)*16+8,_y)
/*Done with dequant, descramble, and partial transpose.
Now do the iDCT itself.*/
- OC_ROW_IDCT_10
- OC_TRANSPOSE
+ OC_ROW_IDCT_10(y,x)
+ OC_TRANSPOSE(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16))"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) OC_M2STR((_k*16)+8)"(%[y])"
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) OC_MEM_OFFS((_k)*16+8,_y)
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(y)
#undef OC_I
#undef OC_J
- :
- :[y]"r"(_y),[c]"r"(OC_IDCT_CONSTS)
+ :[y]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_y,64)
+ :[x]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64),
+ [c]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128)
+ );
+ __asm__ __volatile__(
+ "pxor %%mm0,%%mm0\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x20,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x30,x)"\n\t"
+ :[x]"+m"OC_ARRAY_OPERAND(ogg_int16_t,_x,28)
);
}
/*Performs an inverse 8x8 Type-II DCT transform.
The input is assumed to be scaled by a factor of 4 relative to orthonormal
version of the transform.*/
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
/*_last_zzi is subtly different from an actual count of the number of
coefficients we decoded for this block.
It contains the value of zzi BEFORE the final token in the block was
@@ -557,8 +551,8 @@ void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
gets.
Needless to say we inherited this approach from VP3.*/
/*Then perform the iDCT.*/
- if(_last_zzi<10)oc_idct8x8_10(_y);
- else oc_idct8x8_slow(_y);
+ if(_last_zzi<=10)oc_idct8x8_10_mmx(_y,_x);
+ else oc_idct8x8_slow_mmx(_y,_x);
}
#endif
diff --git a/thirdparty/libtheora/x86/mmxloop.h b/thirdparty/libtheora/x86/mmxloop.h
index 2e870c795d..1f6090b567 100644
--- a/thirdparty/libtheora/x86/mmxloop.h
+++ b/thirdparty/libtheora/x86/mmxloop.h
@@ -9,88 +9,191 @@
On exit, mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)} and
mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}; mm0 and mm3 are clobbered.*/
#define OC_LOOP_FILTER8_MMX \
- "#OC_LOOP_FILTER8_MMX\n\t" \
- /*mm7=0*/ \
- "pxor %%mm7,%%mm7\n\t" \
- /*mm6:mm0={a0,...,a7}*/ \
- "movq %%mm0,%%mm6\n\t" \
- "punpcklbw %%mm7,%%mm0\n\t" \
- "punpckhbw %%mm7,%%mm6\n\t" \
- /*mm3:mm5={d0,...,d7}*/ \
- "movq %%mm3,%%mm5\n\t" \
- "punpcklbw %%mm7,%%mm3\n\t" \
- "punpckhbw %%mm7,%%mm5\n\t" \
- /*mm6:mm0={a0-d0,...,a7-d7}*/ \
- "psubw %%mm3,%%mm0\n\t" \
- "psubw %%mm5,%%mm6\n\t" \
- /*mm3:mm1={b0,...,b7}*/ \
- "movq %%mm1,%%mm3\n\t" \
- "punpcklbw %%mm7,%%mm1\n\t" \
- "movq %%mm2,%%mm4\n\t" \
- "punpckhbw %%mm7,%%mm3\n\t" \
- /*mm5:mm4={c0,...,c7}*/ \
- "movq %%mm2,%%mm5\n\t" \
- "punpcklbw %%mm7,%%mm4\n\t" \
- "punpckhbw %%mm7,%%mm5\n\t" \
- /*mm7={3}x4 \
- mm5:mm4={c0-b0,...,c7-b7}*/ \
- "pcmpeqw %%mm7,%%mm7\n\t" \
- "psubw %%mm1,%%mm4\n\t" \
- "psrlw $14,%%mm7\n\t" \
- "psubw %%mm3,%%mm5\n\t" \
- /*Scale by 3.*/ \
- "pmullw %%mm7,%%mm4\n\t" \
- "pmullw %%mm7,%%mm5\n\t" \
- /*mm7={4}x4 \
- mm5:mm4=f={a0-d0+3*(c0-b0),...,a7-d7+3*(c7-b7)}*/ \
- "psrlw $1,%%mm7\n\t" \
- "paddw %%mm0,%%mm4\n\t" \
- "psllw $2,%%mm7\n\t" \
- "movq (%[ll]),%%mm0\n\t" \
- "paddw %%mm6,%%mm5\n\t" \
- /*R_i has the range [-127,128], so we compute -R_i instead. \
- mm4=-R_i=-(f+4>>3)=0xFF^(f-4>>3)*/ \
- "psubw %%mm7,%%mm4\n\t" \
- "psubw %%mm7,%%mm5\n\t" \
- "psraw $3,%%mm4\n\t" \
- "psraw $3,%%mm5\n\t" \
- "pcmpeqb %%mm7,%%mm7\n\t" \
- "packsswb %%mm5,%%mm4\n\t" \
- "pxor %%mm6,%%mm6\n\t" \
- "pxor %%mm7,%%mm4\n\t" \
- "packuswb %%mm3,%%mm1\n\t" \
- /*Now compute lflim of -mm4 cf. Section 7.10 of the sepc.*/ \
- /*There's no unsigned byte+signed byte with unsigned saturation op code, so \
- we have to split things by sign (the other option is to work in 16 bits, \
- but working in 8 bits gives much better parallelism). \
- We compute abs(R_i), but save a mask of which terms were negative in mm6. \
- Then we compute mm4=abs(lflim(R_i,L))=min(abs(R_i),max(2*L-abs(R_i),0)). \
- Finally, we split mm4 into positive and negative pieces using the mask in \
- mm6, and add and subtract them as appropriate.*/ \
- /*mm4=abs(-R_i)*/ \
- /*mm7=255-2*L*/ \
- "pcmpgtb %%mm4,%%mm6\n\t" \
- "psubb %%mm0,%%mm7\n\t" \
- "pxor %%mm6,%%mm4\n\t" \
- "psubb %%mm0,%%mm7\n\t" \
- "psubb %%mm6,%%mm4\n\t" \
- /*mm7=255-max(2*L-abs(R_i),0)*/ \
- "paddusb %%mm4,%%mm7\n\t" \
- /*mm4=min(abs(R_i),max(2*L-abs(R_i),0))*/ \
- "paddusb %%mm7,%%mm4\n\t" \
- "psubusb %%mm7,%%mm4\n\t" \
- /*Now split mm4 by the original sign of -R_i.*/ \
- "movq %%mm4,%%mm5\n\t" \
- "pand %%mm6,%%mm4\n\t" \
- "pandn %%mm5,%%mm6\n\t" \
- /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \
- /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \
- "paddusb %%mm4,%%mm1\n\t" \
- "psubusb %%mm4,%%mm2\n\t" \
- "psubusb %%mm6,%%mm1\n\t" \
- "paddusb %%mm6,%%mm2\n\t" \
+ "#OC_LOOP_FILTER8_MMX\n\t" \
+ /*mm7=0*/ \
+ "pxor %%mm7,%%mm7\n\t" \
+ /*mm6:mm0={a0,...,a7}*/ \
+ "movq %%mm0,%%mm6\n\t" \
+ "punpcklbw %%mm7,%%mm0\n\t" \
+ "punpckhbw %%mm7,%%mm6\n\t" \
+ /*mm3:mm5={d0,...,d7}*/ \
+ "movq %%mm3,%%mm5\n\t" \
+ "punpcklbw %%mm7,%%mm3\n\t" \
+ "punpckhbw %%mm7,%%mm5\n\t" \
+ /*mm6:mm0={a0-d0,...,a7-d7}*/ \
+ "psubw %%mm3,%%mm0\n\t" \
+ "psubw %%mm5,%%mm6\n\t" \
+ /*mm3:mm1={b0,...,b7}*/ \
+ "movq %%mm1,%%mm3\n\t" \
+ "punpcklbw %%mm7,%%mm1\n\t" \
+ "movq %%mm2,%%mm4\n\t" \
+ "punpckhbw %%mm7,%%mm3\n\t" \
+ /*mm5:mm4={c0,...,c7}*/ \
+ "movq %%mm2,%%mm5\n\t" \
+ "punpcklbw %%mm7,%%mm4\n\t" \
+ "punpckhbw %%mm7,%%mm5\n\t" \
+ /*mm7={3}x4 \
+ mm5:mm4={c0-b0,...,c7-b7}*/ \
+ "pcmpeqw %%mm7,%%mm7\n\t" \
+ "psubw %%mm1,%%mm4\n\t" \
+ "psrlw $14,%%mm7\n\t" \
+ "psubw %%mm3,%%mm5\n\t" \
+ /*Scale by 3.*/ \
+ "pmullw %%mm7,%%mm4\n\t" \
+ "pmullw %%mm7,%%mm5\n\t" \
+ /*mm7={4}x4 \
+ mm5:mm4=f={a0-d0+3*(c0-b0),...,a7-d7+3*(c7-b7)}*/ \
+ "psrlw $1,%%mm7\n\t" \
+ "paddw %%mm0,%%mm4\n\t" \
+ "psllw $2,%%mm7\n\t" \
+ "movq (%[ll]),%%mm0\n\t" \
+ "paddw %%mm6,%%mm5\n\t" \
+ /*R_i has the range [-127,128], so we compute -R_i instead. \
+ mm4=-R_i=-(f+4>>3)=0xFF^(f-4>>3)*/ \
+ "psubw %%mm7,%%mm4\n\t" \
+ "psubw %%mm7,%%mm5\n\t" \
+ "psraw $3,%%mm4\n\t" \
+ "psraw $3,%%mm5\n\t" \
+ "pcmpeqb %%mm7,%%mm7\n\t" \
+ "packsswb %%mm5,%%mm4\n\t" \
+ "pxor %%mm6,%%mm6\n\t" \
+ "pxor %%mm7,%%mm4\n\t" \
+ "packuswb %%mm3,%%mm1\n\t" \
+ /*Now compute lflim of -mm4 cf. Section 7.10 of the sepc.*/ \
+ /*There's no unsigned byte+signed byte with unsigned saturation op code, so \
+ we have to split things by sign (the other option is to work in 16 bits, \
+ but working in 8 bits gives much better parallelism). \
+ We compute abs(R_i), but save a mask of which terms were negative in mm6. \
+ Then we compute mm4=abs(lflim(R_i,L))=min(abs(R_i),max(2*L-abs(R_i),0)). \
+ Finally, we split mm4 into positive and negative pieces using the mask in \
+ mm6, and add and subtract them as appropriate.*/ \
+ /*mm4=abs(-R_i)*/ \
+ /*mm7=255-2*L*/ \
+ "pcmpgtb %%mm4,%%mm6\n\t" \
+ "psubb %%mm0,%%mm7\n\t" \
+ "pxor %%mm6,%%mm4\n\t" \
+ "psubb %%mm0,%%mm7\n\t" \
+ "psubb %%mm6,%%mm4\n\t" \
+ /*mm7=255-max(2*L-abs(R_i),0)*/ \
+ "paddusb %%mm4,%%mm7\n\t" \
+ /*mm4=min(abs(R_i),max(2*L-abs(R_i),0))*/ \
+ "paddusb %%mm7,%%mm4\n\t" \
+ "psubusb %%mm7,%%mm4\n\t" \
+ /*Now split mm4 by the original sign of -R_i.*/ \
+ "movq %%mm4,%%mm5\n\t" \
+ "pand %%mm6,%%mm4\n\t" \
+ "pandn %%mm5,%%mm6\n\t" \
+ /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \
+ /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \
+ "paddusb %%mm4,%%mm1\n\t" \
+ "psubusb %%mm4,%%mm2\n\t" \
+ "psubusb %%mm6,%%mm1\n\t" \
+ "paddusb %%mm6,%%mm2\n\t" \
-#define OC_LOOP_FILTER_V_MMX(_pix,_ystride,_ll) \
+/*On entry, mm0={a0,...,a7}, mm1={b0,...,b7}, mm2={c0,...,c7}, mm3={d0,...d7}.
+ On exit, mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)} and
+ mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}.
+ All other MMX registers are clobbered.*/
+#define OC_LOOP_FILTER8_MMXEXT \
+ "#OC_LOOP_FILTER8_MMXEXT\n\t" \
+ /*R_i=(a_i-3*b_i+3*c_i-d_i+4>>3) has the range [-127,128], so we compute \
+ -R_i=(-a_i+3*b_i-3*c_i+d_i+3>>3) instead.*/ \
+ /*This first part is based on the transformation \
+ f = -(3*(c-b)+a-d+4>>3) \
+ = -(3*(c+255-b)+(a+255-d)+4-1020>>3) \
+ = -(3*(c+~b)+(a+~d)-1016>>3) \
+ = 127-(3*(c+~b)+(a+~d)>>3) \
+ = 128+~(3*(c+~b)+(a+~d)>>3) (mod 256). \
+ Although pavgb(a,b) = (a+b+1>>1) (biased up), we rely heavily on the \
+ fact that ~pavgb(~a,~b) = (a+b>>1) (biased down). \
+ Using this, the last expression above can be computed in 8 bits of working \
+ precision via: \
+ u = ~pavgb(~b,c); \
+ v = pavgb(b,~c); \
+ This mask is 0 or 0xFF, and controls whether t is biased up or down: \
+ m = u-v; \
+ t = m^pavgb(m^~a,m^d); \
+ f = 128+pavgb(pavgb(t,u),v); \
+ This required some careful analysis to ensure that carries are propagated \
+ correctly in all cases, but has been checked exhaustively.*/ \
+ /*input (a, b, c, d, ., ., ., .)*/ \
+ /*ff=0xFF; \
+ u=b; \
+ v=c; \
+ ll=255-2*L;*/ \
+ "pcmpeqb %%mm7,%%mm7\n\t" \
+ "movq %%mm1,%%mm4\n\t" \
+ "movq %%mm2,%%mm5\n\t" \
+ "movq (%[ll]),%%mm6\n\t" \
+ /*allocated u, v, ll, ff: (a, b, c, d, u, v, ll, ff)*/ \
+ /*u^=ff; \
+ v^=ff;*/ \
+ "pxor %%mm7,%%mm4\n\t" \
+ "pxor %%mm7,%%mm5\n\t" \
+ /*allocated ll: (a, b, c, d, u, v, ll, ff)*/ \
+ /*u=pavgb(u,c); \
+ v=pavgb(v,b);*/ \
+ "pavgb %%mm2,%%mm4\n\t" \
+ "pavgb %%mm1,%%mm5\n\t" \
+ /*u^=ff; \
+ a^=ff;*/ \
+ "pxor %%mm7,%%mm4\n\t" \
+ "pxor %%mm7,%%mm0\n\t" \
+ /*m=u-v;*/ \
+ "psubb %%mm5,%%mm4\n\t" \
+ /*freed u, allocated m: (a, b, c, d, m, v, ll, ff)*/ \
+ /*a^=m; \
+ d^=m;*/ \
+ "pxor %%mm4,%%mm0\n\t" \
+ "pxor %%mm4,%%mm3\n\t" \
+ /*t=pavgb(a,d);*/ \
+ "pavgb %%mm3,%%mm0\n\t" \
+ "psllw $7,%%mm7\n\t" \
+ /*freed a, d, ff, allocated t, of: (t, b, c, ., m, v, ll, of)*/ \
+ /*t^=m; \
+ u=m+v;*/ \
+ "pxor %%mm4,%%mm0\n\t" \
+ "paddb %%mm5,%%mm4\n\t" \
+ /*freed t, m, allocated f, u: (f, b, c, ., u, v, ll, of)*/ \
+ /*f=pavgb(f,u); \
+ of=128;*/ \
+ "pavgb %%mm4,%%mm0\n\t" \
+ "packsswb %%mm7,%%mm7\n\t" \
+ /*freed u, ff, allocated ll: (f, b, c, ., ll, v, ll, of)*/ \
+ /*f=pavgb(f,v);*/ \
+ "pavgb %%mm5,%%mm0\n\t" \
+ "movq %%mm7,%%mm3\n\t" \
+ "movq %%mm6,%%mm4\n\t" \
+ /*freed v, allocated of: (f, b, c, of, ll, ., ll, of)*/ \
+ /*Now compute lflim of R_i=-(128+mm0) cf. Section 7.10 of the sepc.*/ \
+ /*There's no unsigned byte+signed byte with unsigned saturation op code, so \
+ we have to split things by sign (the other option is to work in 16 bits, \
+ but staying in 8 bits gives much better parallelism).*/ \
+ /*Instead of adding the offset of 128 in mm3, we use it to split mm0. \
+ This is the same number of instructions as computing a mask and splitting \
+ after the lflim computation, but has shorter dependency chains.*/ \
+ /*mm0=R_i<0?-R_i:0 (denoted abs(R_i<0))\
+ mm3=R_i>0?R_i:0* (denoted abs(R_i>0))*/ \
+ "psubusb %%mm0,%%mm3\n\t" \
+ "psubusb %%mm7,%%mm0\n\t" \
+ /*mm6=255-max(2*L-abs(R_i<0),0) \
+ mm4=255-max(2*L-abs(R_i>0),0)*/ \
+ "paddusb %%mm3,%%mm4\n\t" \
+ "paddusb %%mm0,%%mm6\n\t" \
+ /*mm0=min(abs(R_i<0),max(2*L-abs(R_i<0),0)) \
+ mm3=min(abs(R_i>0),max(2*L-abs(R_i>0),0))*/ \
+ "paddusb %%mm4,%%mm3\n\t" \
+ "paddusb %%mm6,%%mm0\n\t" \
+ "psubusb %%mm4,%%mm3\n\t" \
+ "psubusb %%mm6,%%mm0\n\t" \
+ /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \
+ /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \
+ "paddusb %%mm3,%%mm1\n\t" \
+ "psubusb %%mm3,%%mm2\n\t" \
+ "psubusb %%mm0,%%mm1\n\t" \
+ "paddusb %%mm0,%%mm2\n\t" \
+
+#define OC_LOOP_FILTER_V(_filter,_pix,_ystride,_ll) \
do{ \
ptrdiff_t ystride3__; \
__asm__ __volatile__( \
@@ -104,7 +207,7 @@
"movq (%[pix],%[ystride]),%%mm1\n\t" \
/*mm2={c0,...,c7}*/ \
"movq (%[pix],%[ystride],2),%%mm2\n\t" \
- OC_LOOP_FILTER8_MMX \
+ _filter \
/*Write it back out.*/ \
"movq %%mm1,(%[pix],%[ystride])\n\t" \
"movq %%mm2,(%[pix],%[ystride],2)\n\t" \
@@ -116,7 +219,7 @@
} \
while(0)
-#define OC_LOOP_FILTER_H_MMX(_pix,_ystride,_ll) \
+#define OC_LOOP_FILTER_H(_filter,_pix,_ystride,_ll) \
do{ \
unsigned char *pix__; \
ptrdiff_t ystride3__; \
@@ -174,7 +277,7 @@
"punpckldq %%mm5,%%mm2\n\t" \
/*mm3=d7 d6 d5 d4 d3 d2 d1 d0*/ \
"punpckhdq %%mm5,%%mm3\n\t" \
- OC_LOOP_FILTER8_MMX \
+ _filter \
/*mm2={b0+R_0'',...,b7+R_7''}*/ \
"movq %%mm1,%%mm0\n\t" \
/*mm1={b0+R_0'',c0-R_0'',...,b3+R_3'',c3-R_3''}*/ \
diff --git a/thirdparty/libtheora/x86/mmxstate.c b/thirdparty/libtheora/x86/mmxstate.c
index 808b0a789b..eebea14fba 100644
--- a/thirdparty/libtheora/x86/mmxstate.c
+++ b/thirdparty/libtheora/x86/mmxstate.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxstate.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,23 +19,23 @@
Originally written by Rudolf Marek.*/
#include <string.h>
#include "x86int.h"
-#include "mmxfrag.h"
#include "mmxloop.h"
#if defined(OC_X86_ASM)
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){
unsigned char *dst;
ptrdiff_t frag_buf_off;
int ystride;
- int mb_mode;
+ int refi;
/*Apply the inverse transform.*/
/*Special case only having a DC component.*/
if(_last_zzi<2){
/*Note that this value must be unsigned, to keep the __asm__ block from
sign-extending it when it puts it in a register.*/
ogg_uint16_t p;
+ int i;
/*We round this dequant product (and not any of the others) because there's
no iDCT rounding.*/
p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5);
@@ -47,81 +47,48 @@ void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
"punpcklwd %%mm0,%%mm0\n\t"
/*mm0=AAAA AAAA AAAA AAAA*/
"punpckldq %%mm0,%%mm0\n\t"
- "movq %%mm0,(%[y])\n\t"
- "movq %%mm0,8(%[y])\n\t"
- "movq %%mm0,16(%[y])\n\t"
- "movq %%mm0,24(%[y])\n\t"
- "movq %%mm0,32(%[y])\n\t"
- "movq %%mm0,40(%[y])\n\t"
- "movq %%mm0,48(%[y])\n\t"
- "movq %%mm0,56(%[y])\n\t"
- "movq %%mm0,64(%[y])\n\t"
- "movq %%mm0,72(%[y])\n\t"
- "movq %%mm0,80(%[y])\n\t"
- "movq %%mm0,88(%[y])\n\t"
- "movq %%mm0,96(%[y])\n\t"
- "movq %%mm0,104(%[y])\n\t"
- "movq %%mm0,112(%[y])\n\t"
- "movq %%mm0,120(%[y])\n\t"
:
- :[y]"r"(_dct_coeffs),[p]"r"((unsigned)p)
- :"memory"
+ :[p]"r"((unsigned)p)
);
+ for(i=0;i<4;i++){
+ __asm__ __volatile__(
+ "movq %%mm0,"OC_MEM_OFFS(0x00,y)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x08,y)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,y)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x18,y)"\n\t"
+ :[y]"=m"OC_ARRAY_OPERAND(ogg_int16_t,_dct_coeffs+64+16*i,16)
+ );
+ }
}
else{
/*Dequantize the DC coefficient.*/
_dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
- oc_idct8x8_mmx(_dct_coeffs,_last_zzi);
+ oc_idct8x8(_state,_dct_coeffs+64,_dct_coeffs,_last_zzi);
}
/*Fill in the target buffer.*/
frag_buf_off=_state->frag_buf_offs[_fragi];
- mb_mode=_state->frags[_fragi].mb_mode;
+ refi=_state->frags[_fragi].refi;
ystride=_state->ref_ystride[_pli];
- dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off;
- if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs);
+ dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off;
+ if(refi==OC_FRAME_SELF)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs+64);
else{
const unsigned char *ref;
int mvoffsets[2];
- ref=
- _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]
- +frag_buf_off;
+ ref=_state->ref_frame_data[refi]+frag_buf_off;
if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
- _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){
+ _state->frag_mvs[_fragi])>1){
oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,
- _dct_coeffs);
+ _dct_coeffs+64);
}
- else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs);
+ else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs+64);
}
}
/*We copy these entire function to inline the actual MMX routines so that we
use only a single indirect call.*/
-/*Copies the fragments specified by the lists of fragment indices from one
- frame to another.
- _fragis: A pointer to a list of fragment indices.
- _nfragis: The number of fragment indices to copy.
- _dst_frame: The reference frame to copy to.
- _src_frame: The reference frame to copy from.
- _pli: The color plane the fragments lie in.*/
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- const ptrdiff_t *frag_buf_offs;
- const unsigned char *src_frame_data;
- unsigned char *dst_frame_data;
- ptrdiff_t fragii;
- int ystride;
- dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
- src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
- ystride=_state->ref_ystride[_pli];
- frag_buf_offs=_state->frag_buf_offs;
- for(fragii=0;fragii<_nfragis;fragii++){
- ptrdiff_t frag_buf_off;
- frag_buf_off=frag_buf_offs[_fragis[fragii]];
- OC_FRAG_COPY_MMX(dst_frame_data+frag_buf_off,
- src_frame_data+frag_buf_off,ystride);
- }
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit){
+ memset(_bv,_flimit,8);
}
/*Apply the loop filter to a given set of fragment rows in the given plane.
@@ -133,7 +100,7 @@ void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
_fragy0: The Y coordinate of the first fragment row to filter.
_fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
OC_ALIGN8(unsigned char ll[8]);
const oc_fragment_plane *fplane;
const oc_fragment *frags;
@@ -170,13 +137,84 @@ void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
if(frags[fragi].coded){
unsigned char *ref;
ref=ref_frame_data+frag_buf_offs[fragi];
- if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,ll);
- if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,ll);
+ if(fragi>fragi0){
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMX,ref,ystride,ll);
+ }
+ if(fragi0>fragi_top){
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMX,ref,ystride,ll);
+ }
+ if(fragi+1<fragi_end&&!frags[fragi+1].coded){
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMX,ref+8,ystride,ll);
+ }
+ if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMX,ref+(ystride<<3),ystride,ll);
+ }
+ }
+ fragi++;
+ }
+ fragi0+=nhfrags;
+ }
+}
+
+void oc_loop_filter_init_mmxext(signed char _bv[256],int _flimit){
+ memset(_bv,~(_flimit<<1),8);
+}
+
+/*Apply the loop filter to a given set of fragment rows in the given plane.
+ The filter may be run on the bottom edge, affecting pixels in the next row of
+ fragments, so this row also needs to be available.
+ _bv: The bounding values array.
+ _refi: The index of the frame buffer to filter.
+ _pli: The color plane to filter.
+ _fragy0: The Y coordinate of the first fragment row to filter.
+ _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
+void oc_state_loop_filter_frag_rows_mmxext(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
+ const oc_fragment_plane *fplane;
+ const oc_fragment *frags;
+ const ptrdiff_t *frag_buf_offs;
+ unsigned char *ref_frame_data;
+ ptrdiff_t fragi_top;
+ ptrdiff_t fragi_bot;
+ ptrdiff_t fragi0;
+ ptrdiff_t fragi0_end;
+ int ystride;
+ int nhfrags;
+ fplane=_state->fplanes+_pli;
+ nhfrags=fplane->nhfrags;
+ fragi_top=fplane->froffset;
+ fragi_bot=fragi_top+fplane->nfrags;
+ fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
+ fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags;
+ ystride=_state->ref_ystride[_pli];
+ frags=_state->frags;
+ frag_buf_offs=_state->frag_buf_offs;
+ ref_frame_data=_state->ref_frame_data[_refi];
+ /*The following loops are constructed somewhat non-intuitively on purpose.
+ The main idea is: if a block boundary has at least one coded fragment on
+ it, the filter is applied to it.
+ However, the order that the filters are applied in matters, and VP3 chose
+ the somewhat strange ordering used below.*/
+ while(fragi0<fragi0_end){
+ ptrdiff_t fragi;
+ ptrdiff_t fragi_end;
+ fragi=fragi0;
+ fragi_end=fragi+nhfrags;
+ while(fragi<fragi_end){
+ if(frags[fragi].coded){
+ unsigned char *ref;
+ ref=ref_frame_data+frag_buf_offs[fragi];
+ if(fragi>fragi0){
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMXEXT,ref,ystride,_bv);
+ }
+ if(fragi0>fragi_top){
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMXEXT,ref,ystride,_bv);
+ }
if(fragi+1<fragi_end&&!frags[fragi+1].coded){
- OC_LOOP_FILTER_H_MMX(ref+8,ystride,ll);
+ OC_LOOP_FILTER_H(OC_LOOP_FILTER8_MMXEXT,ref+8,ystride,_bv);
}
if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
- OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,ll);
+ OC_LOOP_FILTER_V(OC_LOOP_FILTER8_MMXEXT,ref+(ystride<<3),ystride,_bv);
}
}
fragi++;
diff --git a/thirdparty/libtheora/x86/sse2encfrag.c b/thirdparty/libtheora/x86/sse2encfrag.c
new file mode 100644
index 0000000000..43aeb17711
--- /dev/null
+++ b/thirdparty/libtheora/x86/sse2encfrag.c
@@ -0,0 +1,501 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: dsp_mmx.c 14579 2008-03-12 06:42:40Z xiphmont $
+
+ ********************************************************************/
+#include <stddef.h>
+#include "x86enc.h"
+#include "sse2trans.h"
+
+#if defined(OC_X86_ASM)
+
+/*Load a 4x8 array of pixels values from %[src] and %[ref] and compute their
+ 16-bit differences.
+ On output, these are stored in _m0, xmm1, xmm2, and xmm3.
+ xmm4 and xmm5 are clobbered.*/
+#define OC_LOAD_SUB_4x8(_m0) \
+ "#OC_LOAD_SUB_4x8\n\t" \
+ /*Load the first three rows.*/ \
+ "movq (%[src]),"_m0"\n\t" \
+ "movq (%[ref]),%%xmm4\n\t" \
+ "movq (%[src],%[ystride]),%%xmm1\n\t" \
+ "movq (%[ref],%[ystride]),%%xmm3\n\t" \
+ "movq (%[src],%[ystride],2),%%xmm2\n\t" \
+ "movq (%[ref],%[ystride],2),%%xmm5\n\t" \
+ /*Unpack and subtract.*/ \
+ "punpcklbw %%xmm4,"_m0"\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "punpcklbw %%xmm3,%%xmm1\n\t" \
+ "punpcklbw %%xmm3,%%xmm3\n\t" \
+ "psubw %%xmm4,"_m0"\n\t" \
+ "psubw %%xmm3,%%xmm1\n\t" \
+ /*Load the last row.*/ \
+ "movq (%[src],%[ystride3]),%%xmm3\n\t" \
+ "movq (%[ref],%[ystride3]),%%xmm4\n\t" \
+ /*Unpack, subtract, and advance the pointers.*/ \
+ "punpcklbw %%xmm5,%%xmm2\n\t" \
+ "punpcklbw %%xmm5,%%xmm5\n\t" \
+ "lea (%[src],%[ystride],4),%[src]\n\t" \
+ "psubw %%xmm5,%%xmm2\n\t" \
+ "punpcklbw %%xmm4,%%xmm3\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "lea (%[ref],%[ystride],4),%[ref]\n\t" \
+ "psubw %%xmm4,%%xmm3\n\t" \
+
+/*Square and accumulate four rows of differences in _m0, xmm1, xmm2, and xmm3.
+ On output, xmm0 contains the sum of two of the rows, and the other two are
+ added to xmm7.*/
+#define OC_SSD_4x8(_m0) \
+ "pmaddwd "_m0","_m0"\n\t" \
+ "pmaddwd %%xmm1,%%xmm1\n\t" \
+ "pmaddwd %%xmm2,%%xmm2\n\t" \
+ "pmaddwd %%xmm3,%%xmm3\n\t" \
+ "paddd %%xmm1,"_m0"\n\t" \
+ "paddd %%xmm3,%%xmm2\n\t" \
+ "paddd %%xmm2,%%xmm7\n\t" \
+
+unsigned oc_enc_frag_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ unsigned ret;
+ __asm__ __volatile__(
+ OC_LOAD_SUB_4x8("%%xmm7")
+ OC_SSD_4x8("%%xmm7")
+ OC_LOAD_SUB_4x8("%%xmm0")
+ OC_SSD_4x8("%%xmm0")
+ "paddd %%xmm0,%%xmm7\n\t"
+ "movdqa %%xmm7,%%xmm6\n\t"
+ "punpckhqdq %%xmm7,%%xmm7\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "pshufd $1,%%xmm7,%%xmm6\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "movd %%xmm7,%[ret]\n\t"
+ :[ret]"=a"(ret)
+ :[src]"r"(_src),[ref]"r"(_ref),[ystride]"r"((ptrdiff_t)_ystride),
+ [ystride3]"r"((ptrdiff_t)_ystride*3)
+ );
+ return ret;
+}
+
+static const unsigned char __attribute__((aligned(16))) OC_MASK_CONSTS[8]={
+ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
+};
+
+/*Load a 2x8 array of pixels values from %[src] and %[ref] and compute their
+ horizontal sums as well as their 16-bit differences subject to a mask.
+ %%xmm5 must contain OC_MASK_CONSTS[0...7] and %%xmm6 must contain 0.*/
+#define OC_LOAD_SUB_MASK_2x8 \
+ "#OC_LOAD_SUB_MASK_2x8\n\t" \
+ /*Start the loads and expand the next 8 bits of the mask.*/ \
+ "shl $8,%[m]\n\t" \
+ "movq (%[src]),%%xmm0\n\t" \
+ "mov %h[m],%b[m]\n\t" \
+ "movq (%[ref]),%%xmm2\n\t" \
+ "movd %[m],%%xmm4\n\t" \
+ "shr $8,%[m]\n\t" \
+ "pshuflw $0x00,%%xmm4,%%xmm4\n\t" \
+ "mov %h[m],%b[m]\n\t" \
+ "pand %%xmm6,%%xmm4\n\t" \
+ "pcmpeqb %%xmm6,%%xmm4\n\t" \
+ /*Perform the masking.*/ \
+ "pand %%xmm4,%%xmm0\n\t" \
+ "pand %%xmm4,%%xmm2\n\t" \
+ /*Finish the loads while unpacking the first set of rows, and expand the next
+ 8 bits of the mask.*/ \
+ "movd %[m],%%xmm4\n\t" \
+ "movq (%[src],%[ystride]),%%xmm1\n\t" \
+ "pshuflw $0x00,%%xmm4,%%xmm4\n\t" \
+ "movq (%[ref],%[ystride]),%%xmm3\n\t" \
+ "pand %%xmm6,%%xmm4\n\t" \
+ "punpcklbw %%xmm2,%%xmm0\n\t" \
+ "pcmpeqb %%xmm6,%%xmm4\n\t" \
+ "punpcklbw %%xmm2,%%xmm2\n\t" \
+ /*Mask and unpack the second set of rows.*/ \
+ "pand %%xmm4,%%xmm1\n\t" \
+ "pand %%xmm4,%%xmm3\n\t" \
+ "punpcklbw %%xmm3,%%xmm1\n\t" \
+ "punpcklbw %%xmm3,%%xmm3\n\t" \
+ "psubw %%xmm2,%%xmm0\n\t" \
+ "psubw %%xmm3,%%xmm1\n\t" \
+
+unsigned oc_enc_frag_border_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask){
+ ptrdiff_t ystride;
+ unsigned ret;
+ int i;
+ ystride=_ystride;
+ __asm__ __volatile__(
+ "pxor %%xmm7,%%xmm7\n\t"
+ "movq %[c],%%xmm6\n\t"
+ :
+ :[c]"m"(OC_CONST_ARRAY_OPERAND(unsigned char,OC_MASK_CONSTS,8))
+ );
+ for(i=0;i<4;i++){
+ unsigned m;
+ m=_mask&0xFFFF;
+ _mask>>=16;
+ if(m){
+ __asm__ __volatile__(
+ OC_LOAD_SUB_MASK_2x8
+ "pmaddwd %%xmm0,%%xmm0\n\t"
+ "pmaddwd %%xmm1,%%xmm1\n\t"
+ "paddd %%xmm0,%%xmm7\n\t"
+ "paddd %%xmm1,%%xmm7\n\t"
+ :[src]"+r"(_src),[ref]"+r"(_ref),[ystride]"+r"(ystride),[m]"+Q"(m)
+ );
+ }
+ _src+=2*ystride;
+ _ref+=2*ystride;
+ }
+ __asm__ __volatile__(
+ "movdqa %%xmm7,%%xmm6\n\t"
+ "punpckhqdq %%xmm7,%%xmm7\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "pshufd $1,%%xmm7,%%xmm6\n\t"
+ "paddd %%xmm6,%%xmm7\n\t"
+ "movd %%xmm7,%[ret]\n\t"
+ :[ret]"=a"(ret)
+ );
+ return ret;
+}
+
+
+/*Load an 8x8 array of pixel values from %[src] and %[ref] and compute their
+ 16-bit difference in %%xmm0...%%xmm7.*/
+#define OC_LOAD_SUB_8x8 \
+ "#OC_LOAD_SUB_8x8\n\t" \
+ "movq (%[src]),%%xmm0\n\t" \
+ "movq (%[ref]),%%xmm4\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm1\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm5\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "movq (%[src]),%%xmm2\n\t" \
+ "movq (%[ref]),%%xmm7\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm3\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm6\n\t" \
+ "punpcklbw %%xmm4,%%xmm0\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "psubw %%xmm4,%%xmm0\n\t" \
+ "movq (%[src]),%%xmm4\n\t" \
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ "movq (%[ref]),%%xmm0\n\t" \
+ "punpcklbw %%xmm5,%%xmm1\n\t" \
+ "punpcklbw %%xmm5,%%xmm5\n\t" \
+ "psubw %%xmm5,%%xmm1\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm5\n\t" \
+ "punpcklbw %%xmm7,%%xmm2\n\t" \
+ "punpcklbw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm7,%%xmm2\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm7\n\t" \
+ "punpcklbw %%xmm6,%%xmm3\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "punpcklbw %%xmm6,%%xmm6\n\t" \
+ "psubw %%xmm6,%%xmm3\n\t" \
+ "movq (%[src]),%%xmm6\n\t" \
+ "punpcklbw %%xmm0,%%xmm4\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "punpcklbw %%xmm0,%%xmm0\n\t" \
+ "lea (%[src],%[src_ystride],2),%[src]\n\t" \
+ "psubw %%xmm0,%%xmm4\n\t" \
+ "movq (%[ref]),%%xmm0\n\t" \
+ "punpcklbw %%xmm7,%%xmm5\n\t" \
+ "neg %[src_ystride]\n\t" \
+ "punpcklbw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm7,%%xmm5\n\t" \
+ "movq (%[src],%[src_ystride]),%%xmm7\n\t" \
+ "punpcklbw %%xmm0,%%xmm6\n\t" \
+ "lea (%[ref],%[ref_ystride],2),%[ref]\n\t" \
+ "punpcklbw %%xmm0,%%xmm0\n\t" \
+ "neg %[ref_ystride]\n\t" \
+ "psubw %%xmm0,%%xmm6\n\t" \
+ "movq (%[ref],%[ref_ystride]),%%xmm0\n\t" \
+ "punpcklbw %%xmm0,%%xmm7\n\t" \
+ "punpcklbw %%xmm0,%%xmm0\n\t" \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm0\n\t" \
+
+/*Load an 8x8 array of pixel values from %[src] into %%xmm0...%%xmm7.*/
+#define OC_LOAD_8x8 \
+ "#OC_LOAD_8x8\n\t" \
+ "movq (%[src]),%%xmm0\n\t" \
+ "movq (%[src],%[ystride]),%%xmm1\n\t" \
+ "movq (%[src],%[ystride],2),%%xmm2\n\t" \
+ "pxor %%xmm7,%%xmm7\n\t" \
+ "movq (%[src],%[ystride3]),%%xmm3\n\t" \
+ "punpcklbw %%xmm7,%%xmm0\n\t" \
+ "movq (%[src4]),%%xmm4\n\t" \
+ "punpcklbw %%xmm7,%%xmm1\n\t" \
+ "movq (%[src4],%[ystride]),%%xmm5\n\t" \
+ "punpcklbw %%xmm7,%%xmm2\n\t" \
+ "movq (%[src4],%[ystride],2),%%xmm6\n\t" \
+ "punpcklbw %%xmm7,%%xmm3\n\t" \
+ "movq (%[src4],%[ystride3]),%%xmm7\n\t" \
+ "punpcklbw %%xmm4,%%xmm4\n\t" \
+ "punpcklbw %%xmm5,%%xmm5\n\t" \
+ "psrlw $8,%%xmm4\n\t" \
+ "psrlw $8,%%xmm5\n\t" \
+ "punpcklbw %%xmm6,%%xmm6\n\t" \
+ "punpcklbw %%xmm7,%%xmm7\n\t" \
+ "psrlw $8,%%xmm6\n\t" \
+ "psrlw $8,%%xmm7\n\t" \
+
+/*Performs the first two stages of an 8-point 1-D Hadamard transform in place.
+ Outputs 1, 3, 4, and 5 from the second stage are negated (which allows us to
+ perform this stage in place with no temporary registers).*/
+#define OC_HADAMARD_AB_8x8 \
+ "#OC_HADAMARD_AB_8x8\n\t" \
+ /*Stage A:*/ \
+ "paddw %%xmm5,%%xmm1\n\t" \
+ "paddw %%xmm6,%%xmm2\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "paddw %%xmm6,%%xmm6\n\t" \
+ "psubw %%xmm1,%%xmm5\n\t" \
+ "psubw %%xmm2,%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm3\n\t" \
+ "paddw %%xmm4,%%xmm0\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "paddw %%xmm4,%%xmm4\n\t" \
+ "psubw %%xmm3,%%xmm7\n\t" \
+ "psubw %%xmm0,%%xmm4\n\t" \
+ /*Stage B:*/ \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "paddw %%xmm3,%%xmm1\n\t" \
+ "paddw %%xmm6,%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm5\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm6,%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm0,%%xmm2\n\t" \
+ "psubw %%xmm1,%%xmm3\n\t" \
+ "psubw %%xmm4,%%xmm6\n\t" \
+ "psubw %%xmm5,%%xmm7\n\t" \
+
+/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
+ Outputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
+ place with no temporary registers).*/
+#define OC_HADAMARD_C_8x8 \
+ "#OC_HADAMARD_C_8x8\n\t" \
+ /*Stage C:*/ \
+ "paddw %%xmm1,%%xmm0\n\t" \
+ "paddw %%xmm3,%%xmm2\n\t" \
+ "paddw %%xmm5,%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm1\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm0,%%xmm1\n\t" \
+ "psubw %%xmm2,%%xmm3\n\t" \
+ "psubw %%xmm4,%%xmm5\n\t" \
+ "psubw %%xmm6,%%xmm7\n\t" \
+
+/*Performs an 8-point 1-D Hadamard transform in place.
+ Outputs 1, 2, 4, and 7 are negated (which allows us to perform the transform
+ in place with no temporary registers).*/
+#define OC_HADAMARD_8x8 \
+ OC_HADAMARD_AB_8x8 \
+ OC_HADAMARD_C_8x8 \
+
+/*Performs the first part of the final stage of the Hadamard transform and
+ summing of absolute values.
+ At the end of this part, %%xmm1 will contain the DC coefficient of the
+ transform.*/
+#define OC_HADAMARD_C_ABS_ACCUM_A_8x8 \
+ /*We use the fact that \
+ (abs(a+b)+abs(a-b))/2=max(abs(a),abs(b)) \
+ to merge the final butterfly with the abs and the first stage of \
+ accumulation. \
+ Thus we can avoid using pabsw, which is not available until SSSE3. \
+ Emulating pabsw takes 3 instructions, so the straightforward SSE2 \
+ implementation would be (3+3)*8+7=55 instructions (+4 for spilling \
+ registers). \
+ Even with pabsw, it would be (3+1)*8+7=39 instructions (with no spills). \
+ This implementation is only 26 (+4 for spilling registers).*/ \
+ "#OC_HADAMARD_C_ABS_ACCUM_A_8x8\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ "movdqa %%xmm6,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*xmm7={0x7FFF}x4 \
+ xmm4=max(abs(xmm4),abs(xmm5))-0x7FFF*/ \
+ "pcmpeqb %%xmm7,%%xmm7\n\t" \
+ "movdqa %%xmm4,%%xmm6\n\t" \
+ "psrlw $1,%%xmm7\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "pmaxsw %%xmm5,%%xmm4\n\t" \
+ "paddsw %%xmm7,%%xmm6\n\t" \
+ "psubw %%xmm6,%%xmm4\n\t" \
+ /*xmm2=max(abs(xmm2),abs(xmm3))-0x7FFF \
+ xmm0=max(abs(xmm0),abs(xmm1))-0x7FFF*/ \
+ "movdqa %%xmm2,%%xmm6\n\t" \
+ "movdqa %%xmm0,%%xmm5\n\t" \
+ "pmaxsw %%xmm3,%%xmm2\n\t" \
+ "pmaxsw %%xmm1,%%xmm0\n\t" \
+ "paddw %%xmm3,%%xmm6\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm3\n\t" \
+ "paddw %%xmm5,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm5\n\t" \
+
+/*Performs the second part of the final stage of the Hadamard transform and
+ summing of absolute values.*/
+#define OC_HADAMARD_C_ABS_ACCUM_B_8x8 \
+ "#OC_HADAMARD_C_ABS_ACCUM_B_8x8\n\t" \
+ "paddsw %%xmm7,%%xmm6\n\t" \
+ "paddsw %%xmm7,%%xmm1\n\t" \
+ "psubw %%xmm6,%%xmm2\n\t" \
+ "psubw %%xmm1,%%xmm0\n\t" \
+ /*xmm7={1}x4 (needed for the horizontal add that follows) \
+ xmm0+=xmm2+xmm4+max(abs(xmm3),abs(xmm5))-0x7FFF*/ \
+ "movdqa %%xmm3,%%xmm6\n\t" \
+ "pmaxsw %%xmm5,%%xmm3\n\t" \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm0\n\t" \
+ "paddsw %%xmm7,%%xmm6\n\t" \
+ "paddw %%xmm3,%%xmm0\n\t" \
+ "psrlw $14,%%xmm7\n\t" \
+ "psubw %%xmm6,%%xmm0\n\t" \
+
+/*Performs the last stage of an 8-point 1-D Hadamard transform, takes the
+ absolute value of each component, and accumulates everything into xmm0.*/
+#define OC_HADAMARD_C_ABS_ACCUM_8x8 \
+ OC_HADAMARD_C_ABS_ACCUM_A_8x8 \
+ OC_HADAMARD_C_ABS_ACCUM_B_8x8 \
+
+/*Performs an 8-point 1-D Hadamard transform, takes the absolute value of each
+ component, and accumulates everything into xmm0.
+ Note that xmm0 will have an extra 4 added to each column, and that after
+ removing this value, the remainder will be half the conventional value.*/
+#define OC_HADAMARD_ABS_ACCUM_8x8 \
+ OC_HADAMARD_AB_8x8 \
+ OC_HADAMARD_C_ABS_ACCUM_8x8
+
+static unsigned oc_int_frag_satd_sse2(int *_dc,
+ const unsigned char *_src,int _src_ystride,
+ const unsigned char *_ref,int _ref_ystride){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ unsigned ret;
+ unsigned ret2;
+ int dc;
+ __asm__ __volatile__(
+ OC_LOAD_SUB_8x8
+ OC_HADAMARD_8x8
+ OC_TRANSPOSE_8x8
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x8
+ OC_HADAMARD_C_ABS_ACCUM_A_8x8
+ "movd %%xmm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x8
+ /*Up to this point, everything fit in 16 bits (8 input + 1 for the
+ difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
+ for the factor of two we dropped + 3 for the vertical accumulation).
+ Now we finally have to promote things to dwords.
+ We break this part out of OC_HADAMARD_ABS_ACCUM_8x8 to hide the long
+ latency of pmaddwd by starting to compute abs(dc) here.*/
+ "pmaddwd %%xmm7,%%xmm0\n\t"
+ "movsx %w[dc],%[dc]\n\t"
+ "cdq\n\t"
+ "movdqa %%xmm0,%%xmm1\n\t"
+ "punpckhqdq %%xmm0,%%xmm0\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "pshuflw $0xE,%%xmm0,%%xmm1\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "movd %%xmm0,%[ret]\n\t"
+ /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x8 each have an extra 4
+ added to them, a factor of two removed, and the DC value included;
+ correct the final sum here.*/
+ "lea -64(%[ret2],%[ret],2),%[ret]\n\t"
+ "xor %[dc],%[ret2]\n\t"
+ "sub %[ret2],%[ret]\n\t"
+ /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ and %[dc] with some of the inputs, since for once we don't write to
+ them until after we're done using everything but %[buf].*/
+ /*Note that _src_ystride and _ref_ystride must be given non-overlapping
+ constraints, otherewise if gcc can prove they're equal it will allocate
+ them to the same register (which is bad); _src and _ref face a similar
+ problem.
+ All four are destructively modified, but if we list them as output
+ constraints, gcc can't alias them with other outputs.*/
+ :[ret]"=r"(ret),[ret2]"=d"(ret2),[dc]"=a"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,16))
+ :[src]"S"(_src),[src_ystride]"c"((ptrdiff_t)_src_ystride),
+ [ref]"a"(_ref),[ref_ystride]"d"((ptrdiff_t)_ref_ystride)
+ /*We have to use neg, so we actually clobber the condition codes for once
+ (not to mention sub, and add).*/
+ :"cc"
+ );
+ *_dc=dc;
+ return ret;
+}
+
+unsigned oc_enc_frag_satd_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ return oc_int_frag_satd_sse2(_dc,_src,_ystride,_ref,_ystride);
+}
+
+unsigned oc_enc_frag_satd2_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
+ OC_ALIGN8(unsigned char ref[64]);
+ oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
+ return oc_int_frag_satd_sse2(_dc,_src,_ystride,ref,8);
+}
+
+unsigned oc_enc_frag_intra_satd_sse2(int *_dc,
+ const unsigned char *_src,int _ystride){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ unsigned ret;
+ int dc;
+ __asm__ __volatile__(
+ OC_LOAD_8x8
+ OC_HADAMARD_8x8
+ OC_TRANSPOSE_8x8
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x8
+ OC_HADAMARD_C_ABS_ACCUM_A_8x8
+ "movd %%xmm1,%[dc]\n\t"
+ OC_HADAMARD_C_ABS_ACCUM_B_8x8
+ /*Up to this point, everything fit in 16 bits (8 input + 1 for the
+ difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
+ for the factor of two we dropped + 3 for the vertical accumulation).
+ Now we finally have to promote things to dwords.*/
+ "pmaddwd %%xmm7,%%xmm0\n\t"
+ /*We assume that the DC coefficient is always positive (which is true,
+ because the input to the INTRA transform was not a difference).*/
+ "movzx %w[dc],%[dc]\n\t"
+ "movdqa %%xmm0,%%xmm1\n\t"
+ "punpckhqdq %%xmm0,%%xmm0\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "pshuflw $0xE,%%xmm0,%%xmm1\n\t"
+ "paddd %%xmm1,%%xmm0\n\t"
+ "movd %%xmm0,%[ret]\n\t"
+ "lea -64(%[ret],%[ret]),%[ret]\n\t"
+ "sub %[dc],%[ret]\n\t"
+ /*Although it looks like we're using 7 registers here, gcc can alias %[ret]
+ and %[dc] with some of the inputs, since for once we don't write to
+ them until after we're done using everything but %[buf].*/
+ :[ret]"=a"(ret),[dc]"=r"(dc),
+ [buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,16))
+ :[src]"r"(_src),[src4]"r"(_src+4*_ystride),
+ [ystride]"r"((ptrdiff_t)_ystride),[ystride3]"r"((ptrdiff_t)3*_ystride)
+ /*We have to use sub, so we actually clobber the condition codes for once.*/
+ :"cc"
+ );
+ *_dc=dc;
+ return ret;
+}
+
+#endif
diff --git a/thirdparty/libtheora/x86/sse2fdct.c b/thirdparty/libtheora/x86/sse2fdct.c
index 86c17d68b1..64c1d27372 100644
--- a/thirdparty/libtheora/x86/sse2fdct.c
+++ b/thirdparty/libtheora/x86/sse2fdct.c
@@ -13,12 +13,14 @@
/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
#include <stddef.h>
#include "x86enc.h"
+#include "x86zigzag.h"
+#include "sse2trans.h"
#if defined(OC_X86_64_ASM)
-# define OC_FDCT8x8 \
+# define OC_FDCT_8x8 \
/*Note: xmm15={0}x8 and xmm14={-1}x8.*/ \
- "#OC_FDCT8x8\n\t" \
+ "#OC_FDCT_8x8\n\t" \
/*Stage 1:*/ \
"movdqa %%xmm0,%%xmm11\n\t" \
"movdqa %%xmm1,%%xmm10\n\t" \
@@ -349,81 +351,6 @@
"psubw %%xmm14,%%xmm10\n\t" \
"paddw %%xmm10,%%xmm7\n\t " \
-# define OC_TRANSPOSE8x8 \
- "#OC_TRANSPOSE8x8\n\t" \
- "movdqa %%xmm4,%%xmm8\n\t" \
- /*xmm4 = f3 e3 f2 e2 f1 e1 f0 e0*/ \
- "punpcklwd %%xmm5,%%xmm4\n\t" \
- /*xmm8 = f7 e7 f6 e6 f5 e5 f4 e4*/ \
- "punpckhwd %%xmm5,%%xmm8\n\t" \
- /*xmm5 is free.*/ \
- "movdqa %%xmm0,%%xmm5\n\t" \
- /*xmm0 = b3 a3 b2 a2 b1 a1 b0 a0*/ \
- "punpcklwd %%xmm1,%%xmm0\n\t" \
- /*xmm5 = b7 a7 b6 a6 b5 a5 b4 a4*/ \
- "punpckhwd %%xmm1,%%xmm5\n\t" \
- /*xmm1 is free.*/ \
- "movdqa %%xmm6,%%xmm1\n\t" \
- /*xmm6 = h3 g3 h2 g2 h1 g1 h0 g0*/ \
- "punpcklwd %%xmm7,%%xmm6\n\t" \
- /*xmm1 = h7 g7 h6 g6 h5 g5 h4 g4*/ \
- "punpckhwd %%xmm7,%%xmm1\n\t" \
- /*xmm7 is free.*/ \
- "movdqa %%xmm2,%%xmm7\n\t" \
- /*xmm7 = d3 c3 d2 c2 d1 c1 d0 c0*/ \
- "punpcklwd %%xmm3,%%xmm7\n\t" \
- /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
- "punpckhwd %%xmm3,%%xmm2\n\t" \
- /*xmm3 is free.*/ \
- "movdqa %%xmm0,%%xmm3\n\t" \
- /*xmm0 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
- "punpckldq %%xmm7,%%xmm0\n\t" \
- /*xmm3 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
- "punpckhdq %%xmm7,%%xmm3\n\t" \
- /*xmm7 is free.*/ \
- "movdqa %%xmm5,%%xmm7\n\t" \
- /*xmm5 = d5 c5 b5 a5 d4 c4 b4 a4*/ \
- "punpckldq %%xmm2,%%xmm5\n\t" \
- /*xmm7 = d7 c7 b7 a7 d6 c6 b6 a6*/ \
- "punpckhdq %%xmm2,%%xmm7\n\t" \
- /*xmm2 is free.*/ \
- "movdqa %%xmm4,%%xmm2\n\t" \
- /*xmm2 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
- "punpckldq %%xmm6,%%xmm2\n\t" \
- /*xmm4 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
- "punpckhdq %%xmm6,%%xmm4\n\t" \
- /*xmm6 is free.*/ \
- "movdqa %%xmm8,%%xmm6\n\t" \
- /*xmm6 = h5 g5 f5 e5 h4 g4 f4 e4*/ \
- "punpckldq %%xmm1,%%xmm6\n\t" \
- /*xmm8 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
- "punpckhdq %%xmm1,%%xmm8\n\t" \
- /*xmm1 is free.*/ \
- "movdqa %%xmm0,%%xmm1\n\t" \
- /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
- "punpcklqdq %%xmm2,%%xmm0\n\t" \
- /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
- "punpckhqdq %%xmm2,%%xmm1\n\t" \
- /*xmm2 is free.*/ \
- "movdqa %%xmm3,%%xmm2\n\t" \
- /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
- "punpcklqdq %%xmm4,%%xmm2\n\t" \
- /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
- "punpckhqdq %%xmm4,%%xmm3\n\t" \
- /*xmm4 is free.*/ \
- "movdqa %%xmm5,%%xmm4\n\t" \
- /*xmm4 = h4 g4 f4 e4 d4 c4 b4 a4*/ \
- "punpcklqdq %%xmm6,%%xmm4\n\t" \
- /*xmm5 = h5 g5 f5 e5 d5 c5 b5 a5*/ \
- "punpckhqdq %%xmm6,%%xmm5\n\t" \
- /*xmm6 is free.*/ \
- "movdqa %%xmm7,%%xmm6\n\t" \
- /*xmm6 = h6 g6 f6 e6 d6 c6 b6 a6*/ \
- "punpcklqdq %%xmm8,%%xmm6\n\t" \
- /*xmm7 = h7 g7 f7 e7 d7 c7 b7 a7*/ \
- "punpckhqdq %%xmm8,%%xmm7\n\t" \
- /*xmm8 is free.*/ \
-
/*SSE2 implementation of the fDCT for x86-64 only.
Because of the 8 extra XMM registers on x86-64, this version can operate
without any temporary stack access at all.*/
@@ -482,12 +409,10 @@ void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
/*xmm1=_x[15...8]-{0,0,0,0,0,0,0,1}*/
"psubw %%xmm9,%%xmm1\n\t"
/*Transform columns.*/
- OC_FDCT8x8
+ OC_FDCT_8x8
/*Transform rows.*/
- OC_TRANSPOSE8x8
- OC_FDCT8x8
- /*TODO: zig-zag ordering?*/
- OC_TRANSPOSE8x8
+ OC_TRANSPOSE_8x8
+ OC_FDCT_8x8
/*xmm14={-2,-2,-2,-2,-2,-2,-2,-2}*/
"paddw %%xmm14,%%xmm14\n\t"
"psubw %%xmm14,%%xmm0\n\t"
@@ -506,15 +431,19 @@ void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
"psubw %%xmm14,%%xmm7\n\t"
"psraw $2,%%xmm6\n\t"
"psraw $2,%%xmm7\n\t"
- /*Store the result.*/
- "movdqa %%xmm0,0x00(%[y])\n\t"
- "movdqa %%xmm1,0x10(%[y])\n\t"
- "movdqa %%xmm2,0x20(%[y])\n\t"
- "movdqa %%xmm3,0x30(%[y])\n\t"
- "movdqa %%xmm4,0x40(%[y])\n\t"
- "movdqa %%xmm5,0x50(%[y])\n\t"
- "movdqa %%xmm6,0x60(%[y])\n\t"
- "movdqa %%xmm7,0x70(%[y])\n\t"
+ /*Transpose, zig-zag, and store the result.*/
+ /*We could probably do better using SSSE3's palignr, but re-using MMXEXT
+ version will do for now.*/
+#define OC_ZZ_LOAD_ROW_LO(_row,_reg) \
+ "movdq2q %%xmm"#_row","_reg"\n\t" \
+
+#define OC_ZZ_LOAD_ROW_HI(_row,_reg) \
+ "punpckhqdq %%xmm"#_row",%%xmm"#_row"\n\t" \
+ "movdq2q %%xmm"#_row","_reg"\n\t" \
+
+ OC_TRANSPOSE_ZIG_ZAG_MMXEXT
+#undef OC_ZZ_LOAD_ROW_LO
+#undef OC_ZZ_LOAD_ROW_HI
:[a]"=&r"(a)
:[y]"r"(_y),[x]"r"(_x)
:"memory"
diff --git a/thirdparty/libtheora/x86/sse2idct.c b/thirdparty/libtheora/x86/sse2idct.c
new file mode 100644
index 0000000000..4597ab074f
--- /dev/null
+++ b/thirdparty/libtheora/x86/sse2idct.c
@@ -0,0 +1,456 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $
+
+ ********************************************************************/
+
+/*SSE2 acceleration of Theora's iDCT.*/
+#include "x86int.h"
+#include "sse2trans.h"
+#include "../dct.h"
+
+#if defined(OC_X86_ASM)
+
+/*A table of constants used by the MMX routines.*/
+const unsigned short __attribute__((aligned(16),used)) OC_IDCT_CONSTS[64]={
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,OC_C1S7,
+ OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,OC_C2S6,
+ OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,OC_C3S5,
+ OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,OC_C4S4,
+ OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,OC_C5S3,
+ OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,OC_C6S2,
+ OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1,OC_C7S1
+};
+
+
+/*Performs the first three stages of the iDCT.
+ xmm2, xmm6, xmm3, and xmm5 must contain the corresponding rows of the input
+ (accessed in that order).
+ The remaining rows must be in _x at their corresponding locations.
+ On output, xmm7 down to xmm4 contain rows 0 through 3, and xmm0 up to xmm3
+ contain rows 4 through 7.*/
+#define OC_IDCT_8x8_ABC(_x) \
+ "#OC_IDCT_8x8_ABC\n\t" \
+ /*Stage 1:*/ \
+ /*2-3 rotation by 6pi/16. \
+ xmm4=xmm7=C6, xmm0=xmm1=C2, xmm2=X2, xmm6=X6.*/ \
+ "movdqa "OC_MEM_OFFS(0x20,c)",%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x60,c)",%%xmm4\n\t" \
+ "movdqa %%xmm1,%%xmm0\n\t" \
+ "pmulhw %%xmm2,%%xmm1\n\t" \
+ "movdqa %%xmm4,%%xmm7\n\t" \
+ "pmulhw %%xmm6,%%xmm0\n\t" \
+ "pmulhw %%xmm2,%%xmm7\n\t" \
+ "pmulhw %%xmm6,%%xmm4\n\t" \
+ "paddw %%xmm6,%%xmm0\n\t" \
+ "movdqa "OC_MEM_OFFS(0x30,c)",%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm2\n\t" \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ "paddw %%xmm4,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x50,c)",%%xmm4\n\t" \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ /*5-6 rotation by 3pi/16. \
+ xmm4=xmm2=C5, xmm1=xmm6=C3, xmm3=X3, xmm5=X5.*/ \
+ "movdqa %%xmm4,%%xmm2\n\t" \
+ "movdqa %%xmm6,%%xmm1\n\t" \
+ "pmulhw %%xmm3,%%xmm4\n\t" \
+ "pmulhw %%xmm5,%%xmm1\n\t" \
+ "pmulhw %%xmm3,%%xmm6\n\t" \
+ "pmulhw %%xmm5,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm4\n\t" \
+ "paddw %%xmm5,%%xmm3\n\t" \
+ "paddw %%xmm6,%%xmm3\n\t" \
+ "movdqa "OC_MEM_OFFS(0x70,_x)",%%xmm6\n\t" \
+ "paddw %%xmm5,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,_x)",%%xmm5\n\t" \
+ "paddw %%xmm3,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x70,c)",%%xmm3\n\t" \
+ "psubw %%xmm4,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,c)",%%xmm4\n\t" \
+ /*4-7 rotation by 7pi/16. \
+ xmm4=xmm7=C1, xmm3=xmm0=C7, xmm5=X1, xmm6=X7.*/ \
+ "movdqa %%xmm3,%%xmm0\n\t" \
+ "movdqa %%xmm4,%%xmm7\n\t" \
+ "pmulhw %%xmm5,%%xmm3\n\t" \
+ "pmulhw %%xmm5,%%xmm7\n\t" \
+ "pmulhw %%xmm6,%%xmm4\n\t" \
+ "pmulhw %%xmm6,%%xmm0\n\t" \
+ "paddw %%xmm6,%%xmm4\n\t" \
+ "movdqa "OC_MEM_OFFS(0x40,_x)",%%xmm6\n\t" \
+ "paddw %%xmm5,%%xmm7\n\t" \
+ "psubw %%xmm4,%%xmm3\n\t" \
+ "movdqa "OC_MEM_OFFS(0x40,c)",%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm0\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,_x)",%%xmm7\n\t" \
+ /*0-1 butterfly. \
+ xmm4=xmm5=C4, xmm7=X0, xmm6=X4.*/ \
+ "paddw %%xmm7,%%xmm6\n\t" \
+ "movdqa %%xmm4,%%xmm5\n\t" \
+ "pmulhw %%xmm6,%%xmm4\n\t" \
+ "paddw %%xmm7,%%xmm7\n\t" \
+ "psubw %%xmm6,%%xmm7\n\t" \
+ "paddw %%xmm6,%%xmm4\n\t" \
+ /*Stage 2:*/ \
+ /*4-5 butterfly: xmm3=t[4], xmm1=t[5] \
+ 7-6 butterfly: xmm2=t[6], xmm0=t[7]*/ \
+ "movdqa %%xmm3,%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm3\n\t" \
+ "psubw %%xmm1,%%xmm6\n\t" \
+ "movdqa %%xmm5,%%xmm1\n\t" \
+ "pmulhw %%xmm7,%%xmm5\n\t" \
+ "paddw %%xmm7,%%xmm5\n\t" \
+ "movdqa %%xmm0,%%xmm7\n\t" \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "psubw %%xmm2,%%xmm7\n\t" \
+ "movdqa %%xmm1,%%xmm2\n\t" \
+ "pmulhw %%xmm6,%%xmm1\n\t" \
+ "pmulhw %%xmm7,%%xmm2\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm7\n\t" \
+ /*Stage 3: \
+ 6-5 butterfly: xmm1=t[5], xmm2=t[6] -> xmm1=t[6]+t[5], xmm2=t[6]-t[5] \
+ 0-3 butterfly: xmm4=t[0], xmm7=t[3] -> xmm7=t[0]+t[3], xmm4=t[0]-t[3] \
+ 1-2 butterfly: xmm5=t[1], xmm6=t[2] -> xmm6=t[1]+t[2], xmm5=t[1]-t[2]*/ \
+ "paddw %%xmm2,%%xmm1\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm7\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm4,%%xmm4\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "psubw %%xmm1,%%xmm2\n\t" \
+ "psubw %%xmm7,%%xmm4\n\t" \
+ "psubw %%xmm6,%%xmm5\n\t" \
+
+/*Performs the last stage of the iDCT.
+ On input, xmm7 down to xmm4 contain rows 0 through 3, and xmm0 up to xmm3
+ contain rows 4 through 7.
+ On output, xmm0 through xmm7 contain the corresponding rows.*/
+#define OC_IDCT_8x8_D \
+ "#OC_IDCT_8x8_D\n\t" \
+ /*Stage 4: \
+ 0-7 butterfly: xmm7=t[0], xmm0=t[7] -> xmm0=t[0]+t[7], xmm7=t[0]-t[7] \
+ 1-6 butterfly: xmm6=t[1], xmm1=t[6] -> xmm1=t[1]+t[6], xmm6=t[1]-t[6] \
+ 2-5 butterfly: xmm5=t[2], xmm2=t[5] -> xmm2=t[2]+t[5], xmm5=t[2]-t[5] \
+ 3-4 butterfly: xmm4=t[3], xmm3=t[4] -> xmm3=t[3]+t[4], xmm4=t[3]-t[4]*/ \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "psubw %%xmm1,%%xmm6\n\t" \
+ "psubw %%xmm2,%%xmm5\n\t" \
+ "psubw %%xmm3,%%xmm4\n\t" \
+ "paddw %%xmm0,%%xmm0\n\t" \
+ "paddw %%xmm1,%%xmm1\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm7,%%xmm0\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "paddw %%xmm5,%%xmm2\n\t" \
+ "paddw %%xmm4,%%xmm3\n\t" \
+
+/*Performs the last stage of the iDCT.
+ On input, xmm7 down to xmm4 contain rows 0 through 3, and xmm0 up to xmm3
+ contain rows 4 through 7.
+ On output, xmm0 through xmm7 contain the corresponding rows.*/
+#define OC_IDCT_8x8_D_STORE \
+ "#OC_IDCT_8x8_D_STORE\n\t" \
+ /*Stage 4: \
+ 0-7 butterfly: xmm7=t[0], xmm0=t[7] -> xmm0=t[0]+t[7], xmm7=t[0]-t[7] \
+ 1-6 butterfly: xmm6=t[1], xmm1=t[6] -> xmm1=t[1]+t[6], xmm6=t[1]-t[6] \
+ 2-5 butterfly: xmm5=t[2], xmm2=t[5] -> xmm2=t[2]+t[5], xmm5=t[2]-t[5] \
+ 3-4 butterfly: xmm4=t[3], xmm3=t[4] -> xmm3=t[3]+t[4], xmm4=t[3]-t[4]*/ \
+ "psubw %%xmm3,%%xmm4\n\t" \
+ "movdqa %%xmm4,"OC_MEM_OFFS(0x40,y)"\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,c)",%%xmm4\n\t" \
+ "psubw %%xmm0,%%xmm7\n\t" \
+ "psubw %%xmm1,%%xmm6\n\t" \
+ "psubw %%xmm2,%%xmm5\n\t" \
+ "paddw %%xmm4,%%xmm7\n\t" \
+ "paddw %%xmm4,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm5\n\t" \
+ "paddw "OC_MEM_OFFS(0x40,y)",%%xmm4\n\t" \
+ "paddw %%xmm0,%%xmm0\n\t" \
+ "paddw %%xmm1,%%xmm1\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm3,%%xmm3\n\t" \
+ "paddw %%xmm7,%%xmm0\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "psraw $4,%%xmm0\n\t" \
+ "paddw %%xmm5,%%xmm2\n\t" \
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,y)"\n\t" \
+ "psraw $4,%%xmm1\n\t" \
+ "paddw %%xmm4,%%xmm3\n\t" \
+ "movdqa %%xmm1,"OC_MEM_OFFS(0x10,y)"\n\t" \
+ "psraw $4,%%xmm2\n\t" \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x20,y)"\n\t" \
+ "psraw $4,%%xmm3\n\t" \
+ "movdqa %%xmm3,"OC_MEM_OFFS(0x30,y)"\n\t" \
+ "psraw $4,%%xmm4\n\t" \
+ "movdqa %%xmm4,"OC_MEM_OFFS(0x40,y)"\n\t" \
+ "psraw $4,%%xmm5\n\t" \
+ "movdqa %%xmm5,"OC_MEM_OFFS(0x50,y)"\n\t" \
+ "psraw $4,%%xmm6\n\t" \
+ "movdqa %%xmm6,"OC_MEM_OFFS(0x60,y)"\n\t" \
+ "psraw $4,%%xmm7\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x70,y)"\n\t" \
+
+static void oc_idct8x8_slow_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ int i;
+ /*This routine accepts an 8x8 matrix pre-transposed.*/
+ __asm__ __volatile__(
+ /*Load rows 2, 3, 5, and 6 for the first stage of the iDCT.*/
+ "movdqa "OC_MEM_OFFS(0x20,x)",%%xmm2\n\t"
+ "movdqa "OC_MEM_OFFS(0x60,x)",%%xmm6\n\t"
+ "movdqa "OC_MEM_OFFS(0x30,x)",%%xmm3\n\t"
+ "movdqa "OC_MEM_OFFS(0x50,x)",%%xmm5\n\t"
+ OC_IDCT_8x8_ABC(x)
+ OC_IDCT_8x8_D
+ OC_TRANSPOSE_8x8
+ /*Clear out rows 0, 1, 4, and 7 for the first stage of the iDCT.*/
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x70,y)"\n\t"
+ "movdqa %%xmm4,"OC_MEM_OFFS(0x40,y)"\n\t"
+ "movdqa %%xmm1,"OC_MEM_OFFS(0x10,y)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,y)"\n\t"
+ OC_IDCT_8x8_ABC(y)
+ OC_IDCT_8x8_D_STORE
+ :[buf]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,buf,16)),
+ [y]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,_y,64))
+ :[x]"m"(OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64)),
+ [c]"m"(OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128))
+ );
+ __asm__ __volatile__("pxor %%xmm0,%%xmm0\n\t"::);
+ /*Clear input data for next block (decoder only).*/
+ for(i=0;i<2;i++){
+ __asm__ __volatile__(
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x20,x)"\n\t"
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x30,x)"\n\t"
+ :[x]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,_x+i*32,32))
+ );
+ }
+}
+
+/*For the first step of the 10-coefficient version of the 8x8 iDCT, we only
+ need to work with four columns at a time.
+ Doing this in MMX is faster on processors with a 64-bit data path.*/
+#define OC_IDCT_8x8_10_MMX \
+ "#OC_IDCT_8x8_10_MMX\n\t" \
+ /*Stage 1:*/ \
+ /*2-3 rotation by 6pi/16. \
+ mm7=C6, mm6=C2, mm2=X2, X6=0.*/ \
+ "movq "OC_MEM_OFFS(0x60,c)",%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x20,c)",%%mm6\n\t" \
+ "pmulhw %%mm2,%%mm6\n\t" \
+ "pmulhw %%mm2,%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x50,c)",%%mm5\n\t" \
+ "paddw %%mm6,%%mm2\n\t" \
+ "movq %%mm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ "movq "OC_MEM_OFFS(0x30,c)",%%mm2\n\t" \
+ "movq %%mm7,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*5-6 rotation by 3pi/16. \
+ mm5=C5, mm2=C3, mm3=X3, X5=0.*/ \
+ "pmulhw %%mm3,%%mm5\n\t" \
+ "pmulhw %%mm3,%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x10,c)",%%mm7\n\t" \
+ "paddw %%mm3,%%mm5\n\t" \
+ "paddw %%mm3,%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x70,c)",%%mm3\n\t" \
+ /*4-7 rotation by 7pi/16. \
+ mm7=C1, mm3=C7, mm1=X1, X7=0.*/ \
+ "pmulhw %%mm1,%%mm3\n\t" \
+ "pmulhw %%mm1,%%mm7\n\t" \
+ "movq "OC_MEM_OFFS(0x40,c)",%%mm4\n\t" \
+ "movq %%mm3,%%mm6\n\t" \
+ "paddw %%mm1,%%mm7\n\t" \
+ /*0-1 butterfly. \
+ mm4=C4, mm0=X0, X4=0.*/ \
+ /*Stage 2:*/ \
+ /*4-5 butterfly: mm3=t[4], mm5=t[5] \
+ 7-6 butterfly: mm2=t[6], mm7=t[7]*/ \
+ "psubw %%mm5,%%mm3\n\t" \
+ "paddw %%mm5,%%mm6\n\t" \
+ "movq %%mm4,%%mm1\n\t" \
+ "pmulhw %%mm0,%%mm4\n\t" \
+ "paddw %%mm0,%%mm4\n\t" \
+ "movq %%mm7,%%mm0\n\t" \
+ "movq %%mm4,%%mm5\n\t" \
+ "paddw %%mm2,%%mm0\n\t" \
+ "psubw %%mm2,%%mm7\n\t" \
+ "movq %%mm1,%%mm2\n\t" \
+ "pmulhw %%mm6,%%mm1\n\t" \
+ "pmulhw %%mm7,%%mm2\n\t" \
+ "paddw %%mm6,%%mm1\n\t" \
+ "movq "OC_MEM_OFFS(0x00,buf)",%%mm6\n\t" \
+ "paddw %%mm7,%%mm2\n\t" \
+ "movq "OC_MEM_OFFS(0x10,buf)",%%mm7\n\t" \
+ /*Stage 3: \
+ 6-5 butterfly: mm1=t[5], mm2=t[6] -> mm1=t[6]+t[5], mm2=t[6]-t[5] \
+ 0-3 butterfly: mm4=t[0], mm7=t[3] -> mm7=t[0]+t[3], mm4=t[0]-t[3] \
+ 1-2 butterfly: mm5=t[1], mm6=t[2] -> mm6=t[1]+t[2], mm5=t[1]-t[2]*/ \
+ "paddw %%mm2,%%mm1\n\t" \
+ "paddw %%mm5,%%mm6\n\t" \
+ "paddw %%mm4,%%mm7\n\t" \
+ "paddw %%mm2,%%mm2\n\t" \
+ "paddw %%mm4,%%mm4\n\t" \
+ "paddw %%mm5,%%mm5\n\t" \
+ "psubw %%mm1,%%mm2\n\t" \
+ "psubw %%mm7,%%mm4\n\t" \
+ "psubw %%mm6,%%mm5\n\t" \
+ /*Stage 4: \
+ 0-7 butterfly: mm7=t[0], mm0=t[7] -> mm0=t[0]+t[7], mm7=t[0]-t[7] \
+ 1-6 butterfly: mm6=t[1], mm1=t[6] -> mm1=t[1]+t[6], mm6=t[1]-t[6] \
+ 2-5 butterfly: mm5=t[2], mm2=t[5] -> mm2=t[2]+t[5], mm5=t[2]-t[5] \
+ 3-4 butterfly: mm4=t[3], mm3=t[4] -> mm3=t[3]+t[4], mm4=t[3]-t[4]*/ \
+ "psubw %%mm0,%%mm7\n\t" \
+ "psubw %%mm1,%%mm6\n\t" \
+ "psubw %%mm2,%%mm5\n\t" \
+ "psubw %%mm3,%%mm4\n\t" \
+ "paddw %%mm0,%%mm0\n\t" \
+ "paddw %%mm1,%%mm1\n\t" \
+ "paddw %%mm2,%%mm2\n\t" \
+ "paddw %%mm3,%%mm3\n\t" \
+ "paddw %%mm7,%%mm0\n\t" \
+ "paddw %%mm6,%%mm1\n\t" \
+ "paddw %%mm5,%%mm2\n\t" \
+ "paddw %%mm4,%%mm3\n\t" \
+
+#define OC_IDCT_8x8_10_ABC \
+ "#OC_IDCT_8x8_10_ABC\n\t" \
+ /*Stage 1:*/ \
+ /*2-3 rotation by 6pi/16. \
+ xmm7=C6, xmm6=C2, xmm2=X2, X6=0.*/ \
+ "movdqa "OC_MEM_OFFS(0x60,c)",%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x20,c)",%%xmm6\n\t" \
+ "pmulhw %%xmm2,%%xmm6\n\t" \
+ "pmulhw %%xmm2,%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x50,c)",%%xmm5\n\t" \
+ "paddw %%xmm6,%%xmm2\n\t" \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ "movdqa "OC_MEM_OFFS(0x30,c)",%%xmm2\n\t" \
+ "movdqa %%xmm7,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*5-6 rotation by 3pi/16. \
+ xmm5=C5, xmm2=C3, xmm3=X3, X5=0.*/ \
+ "pmulhw %%xmm3,%%xmm5\n\t" \
+ "pmulhw %%xmm3,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,c)",%%xmm7\n\t" \
+ "paddw %%xmm3,%%xmm5\n\t" \
+ "paddw %%xmm3,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x70,c)",%%xmm3\n\t" \
+ /*4-7 rotation by 7pi/16. \
+ xmm7=C1, xmm3=C7, xmm1=X1, X7=0.*/ \
+ "pmulhw %%xmm1,%%xmm3\n\t" \
+ "pmulhw %%xmm1,%%xmm7\n\t" \
+ "movdqa "OC_MEM_OFFS(0x40,c)",%%xmm4\n\t" \
+ "movdqa %%xmm3,%%xmm6\n\t" \
+ "paddw %%xmm1,%%xmm7\n\t" \
+ /*0-1 butterfly. \
+ xmm4=C4, xmm0=X0, X4=0.*/ \
+ /*Stage 2:*/ \
+ /*4-5 butterfly: xmm3=t[4], xmm5=t[5] \
+ 7-6 butterfly: xmm2=t[6], xmm7=t[7]*/ \
+ "psubw %%xmm5,%%xmm3\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "movdqa %%xmm4,%%xmm1\n\t" \
+ "pmulhw %%xmm0,%%xmm4\n\t" \
+ "paddw %%xmm0,%%xmm4\n\t" \
+ "movdqa %%xmm7,%%xmm0\n\t" \
+ "movdqa %%xmm4,%%xmm5\n\t" \
+ "paddw %%xmm2,%%xmm0\n\t" \
+ "psubw %%xmm2,%%xmm7\n\t" \
+ "movdqa %%xmm1,%%xmm2\n\t" \
+ "pmulhw %%xmm6,%%xmm1\n\t" \
+ "pmulhw %%xmm7,%%xmm2\n\t" \
+ "paddw %%xmm6,%%xmm1\n\t" \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm6\n\t" \
+ "paddw %%xmm7,%%xmm2\n\t" \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm7\n\t" \
+ /*Stage 3: \
+ 6-5 butterfly: xmm1=t[5], xmm2=t[6] -> xmm1=t[6]+t[5], xmm2=t[6]-t[5] \
+ 0-3 butterfly: xmm4=t[0], xmm7=t[3] -> xmm7=t[0]+t[3], xmm4=t[0]-t[3] \
+ 1-2 butterfly: xmm5=t[1], xmm6=t[2] -> xmm6=t[1]+t[2], xmm5=t[1]-t[2]*/ \
+ "paddw %%xmm2,%%xmm1\n\t" \
+ "paddw %%xmm5,%%xmm6\n\t" \
+ "paddw %%xmm4,%%xmm7\n\t" \
+ "paddw %%xmm2,%%xmm2\n\t" \
+ "paddw %%xmm4,%%xmm4\n\t" \
+ "paddw %%xmm5,%%xmm5\n\t" \
+ "psubw %%xmm1,%%xmm2\n\t" \
+ "psubw %%xmm7,%%xmm4\n\t" \
+ "psubw %%xmm6,%%xmm5\n\t" \
+
+static void oc_idct8x8_10_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ OC_ALIGN16(ogg_int16_t buf[16]);
+ /*This routine accepts an 8x8 matrix pre-transposed.*/
+ __asm__ __volatile__(
+ "movq "OC_MEM_OFFS(0x20,x)",%%mm2\n\t"
+ "movq "OC_MEM_OFFS(0x30,x)",%%mm3\n\t"
+ "movq "OC_MEM_OFFS(0x10,x)",%%mm1\n\t"
+ "movq "OC_MEM_OFFS(0x00,x)",%%mm0\n\t"
+ OC_IDCT_8x8_10_MMX
+ OC_TRANSPOSE_8x4_MMX2SSE
+ OC_IDCT_8x8_10_ABC
+ OC_IDCT_8x8_D_STORE
+ :[buf]"=m"(OC_ARRAY_OPERAND(short,buf,16)),
+ [y]"=m"(OC_ARRAY_OPERAND(ogg_int16_t,_y,64))
+ :[x]"m"OC_CONST_ARRAY_OPERAND(ogg_int16_t,_x,64),
+ [c]"m"(OC_CONST_ARRAY_OPERAND(ogg_int16_t,OC_IDCT_CONSTS,128))
+ );
+ /*Clear input data for next block (decoder only).*/
+ __asm__ __volatile__(
+ "pxor %%mm0,%%mm0\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x00,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x10,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x20,x)"\n\t"
+ "movq %%mm0,"OC_MEM_OFFS(0x30,x)"\n\t"
+ :[x]"+m"(OC_ARRAY_OPERAND(ogg_int16_t,_x,28))
+ );
+}
+
+/*Performs an inverse 8x8 Type-II DCT transform.
+ The input is assumed to be scaled by a factor of 4 relative to orthonormal
+ version of the transform.*/
+void oc_idct8x8_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
+ /*_last_zzi is subtly different from an actual count of the number of
+ coefficients we decoded for this block.
+ It contains the value of zzi BEFORE the final token in the block was
+ decoded.
+ In most cases this is an EOB token (the continuation of an EOB run from a
+ previous block counts), and so this is the same as the coefficient count.
+ However, in the case that the last token was NOT an EOB token, but filled
+ the block up with exactly 64 coefficients, _last_zzi will be less than 64.
+ Provided the last token was not a pure zero run, the minimum value it can
+ be is 46, and so that doesn't affect any of the cases in this routine.
+ However, if the last token WAS a pure zero run of length 63, then _last_zzi
+ will be 1 while the number of coefficients decoded is 64.
+ Thus, we will trigger the following special case, where the real
+ coefficient count would not.
+ Note also that a zero run of length 64 will give _last_zzi a value of 0,
+ but we still process the DC coefficient, which might have a non-zero value
+ due to DC prediction.
+ Although convoluted, this is arguably the correct behavior: it allows us to
+ use a smaller transform when the block ends with a long zero run instead
+ of a normal EOB token.
+ It could be smarter... multiple separate zero runs at the end of a block
+ will fool it, but an encoder that generates these really deserves what it
+ gets.
+ Needless to say we inherited this approach from VP3.*/
+ /*Then perform the iDCT.*/
+ if(_last_zzi<=10)oc_idct8x8_10_sse2(_y,_x);
+ else oc_idct8x8_slow_sse2(_y,_x);
+}
+
+#endif
diff --git a/thirdparty/libtheora/x86/sse2trans.h b/thirdparty/libtheora/x86/sse2trans.h
new file mode 100644
index 0000000000..e76da5140b
--- /dev/null
+++ b/thirdparty/libtheora/x86/sse2trans.h
@@ -0,0 +1,242 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: sse2trans.h 15675 2009-02-06 09:43:27Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_sse2trans_H)
+# define _x86_sse2trans_H (1)
+# include "x86int.h"
+
+# if defined(OC_X86_64_ASM)
+/*On x86-64 we can transpose in-place without spilling registers.
+ By clever choices of the order to apply the butterflies and the order of
+ their outputs, we can take the rows in order and output the columns in order
+ without any extra operations and using just one temporary register.*/
+# define OC_TRANSPOSE_8x8 \
+ "#OC_TRANSPOSE_8x8\n\t" \
+ "movdqa %%xmm4,%%xmm8\n\t" \
+ /*xmm4 = f3 e3 f2 e2 f1 e1 f0 e0*/ \
+ "punpcklwd %%xmm5,%%xmm4\n\t" \
+ /*xmm8 = f7 e7 f6 e6 f5 e5 f4 e4*/ \
+ "punpckhwd %%xmm5,%%xmm8\n\t" \
+ /*xmm5 is free.*/ \
+ "movdqa %%xmm0,%%xmm5\n\t" \
+ /*xmm0 = b3 a3 b2 a2 b1 a1 b0 a0*/ \
+ "punpcklwd %%xmm1,%%xmm0\n\t" \
+ /*xmm5 = b7 a7 b6 a6 b5 a5 b4 a4*/ \
+ "punpckhwd %%xmm1,%%xmm5\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm6,%%xmm1\n\t" \
+ /*xmm6 = h3 g3 h2 g2 h1 g1 h0 g0*/ \
+ "punpcklwd %%xmm7,%%xmm6\n\t" \
+ /*xmm1 = h7 g7 h6 g6 h5 g5 h4 g4*/ \
+ "punpckhwd %%xmm7,%%xmm1\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm2,%%xmm7\n\t" \
+ /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "punpckhwd %%xmm3,%%xmm2\n\t" \
+ /*xmm7 = d3 c3 d2 c2 d1 c1 d0 c0*/ \
+ "punpcklwd %%xmm3,%%xmm7\n\t" \
+ /*xmm3 is free.*/ \
+ "movdqa %%xmm0,%%xmm3\n\t" \
+ /*xmm0 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
+ "punpckldq %%xmm7,%%xmm0\n\t" \
+ /*xmm3 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
+ "punpckhdq %%xmm7,%%xmm3\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm5,%%xmm7\n\t" \
+ /*xmm5 = d5 c5 b5 a5 d4 c4 b4 a4*/ \
+ "punpckldq %%xmm2,%%xmm5\n\t" \
+ /*xmm7 = d7 c7 b7 a7 d6 c6 b6 a6*/ \
+ "punpckhdq %%xmm2,%%xmm7\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm4,%%xmm2\n\t" \
+ /*xmm4 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
+ "punpckhdq %%xmm6,%%xmm4\n\t" \
+ /*xmm2 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
+ "punpckldq %%xmm6,%%xmm2\n\t" \
+ /*xmm6 is free.*/ \
+ "movdqa %%xmm8,%%xmm6\n\t" \
+ /*xmm6 = h5 g5 f5 e5 h4 g4 f4 e4*/ \
+ "punpckldq %%xmm1,%%xmm6\n\t" \
+ /*xmm8 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "punpckhdq %%xmm1,%%xmm8\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm0,%%xmm1\n\t" \
+ /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "punpcklqdq %%xmm2,%%xmm0\n\t" \
+ /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
+ "punpckhqdq %%xmm2,%%xmm1\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm3,%%xmm2\n\t" \
+ /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
+ "punpckhqdq %%xmm4,%%xmm3\n\t" \
+ /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
+ "punpcklqdq %%xmm4,%%xmm2\n\t" \
+ /*xmm4 is free.*/ \
+ "movdqa %%xmm5,%%xmm4\n\t" \
+ /*xmm5 = h5 g5 f5 e5 d5 c5 b5 a5*/ \
+ "punpckhqdq %%xmm6,%%xmm5\n\t" \
+ /*xmm4 = h4 g4 f4 e4 d4 c4 b4 a4*/ \
+ "punpcklqdq %%xmm6,%%xmm4\n\t" \
+ /*xmm6 is free.*/ \
+ "movdqa %%xmm7,%%xmm6\n\t" \
+ /*xmm7 = h7 g7 f7 e7 d7 c7 b7 a7*/ \
+ "punpckhqdq %%xmm8,%%xmm7\n\t" \
+ /*xmm6 = h6 g6 f6 e6 d6 c6 b6 a6*/ \
+ "punpcklqdq %%xmm8,%%xmm6\n\t" \
+ /*xmm8 is free.*/ \
+
+# else
+/*Otherwise, we need to spill some values to %[buf] temporarily.
+ Again, the butterflies are carefully arranged to get the columns to come out
+ in order, minimizing register spills and maximizing the delay between a load
+ and when the value loaded is actually used.*/
+# define OC_TRANSPOSE_8x8 \
+ "#OC_TRANSPOSE_8x8\n\t" \
+ /*buf[0] = a7 a6 a5 a4 a3 a2 a1 a0*/ \
+ "movdqa %%xmm0,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*xmm0 is free.*/ \
+ "movdqa %%xmm2,%%xmm0\n\t" \
+ /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "punpckhwd %%xmm3,%%xmm2\n\t" \
+ /*xmm0 = d3 c3 d2 c2 d1 c1 d0 c0*/ \
+ "punpcklwd %%xmm3,%%xmm0\n\t" \
+ /*xmm3 = a7 a6 a5 a4 a3 a2 a1 a0*/ \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm3\n\t" \
+ /*buf[1] = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm6,%%xmm2\n\t" \
+ /*xmm6 = h3 g3 h2 g2 h1 g1 h0 g0*/ \
+ "punpcklwd %%xmm7,%%xmm6\n\t" \
+ /*xmm2 = h7 g7 h6 g6 h5 g5 h4 g4*/ \
+ "punpckhwd %%xmm7,%%xmm2\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm4,%%xmm7\n\t" \
+ /*xmm4 = f3 e3 f2 e2 f1 e1 f0 e0*/ \
+ "punpcklwd %%xmm5,%%xmm4\n\t" \
+ /*xmm7 = f7 e7 f6 e6 f5 e5 f4 e4*/ \
+ "punpckhwd %%xmm5,%%xmm7\n\t" \
+ /*xmm5 is free.*/ \
+ "movdqa %%xmm3,%%xmm5\n\t" \
+ /*xmm3 = b3 a3 b2 a2 b1 a1 b0 a0*/ \
+ "punpcklwd %%xmm1,%%xmm3\n\t" \
+ /*xmm5 = b7 a7 b6 a6 b5 a5 b4 a4*/ \
+ "punpckhwd %%xmm1,%%xmm5\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm7,%%xmm1\n\t" \
+ /*xmm7 = h5 g5 f5 e5 h4 g4 f4 e4*/ \
+ "punpckldq %%xmm2,%%xmm7\n\t" \
+ /*xmm1 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "punpckhdq %%xmm2,%%xmm1\n\t" \
+ /*xmm2 = d7 c7 d6 c6 d5 c5 d4 c4*/ \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm2\n\t" \
+ /*buf[0] = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "movdqa %%xmm1,"OC_MEM_OFFS(0x00,buf)"\n\t" \
+ /*xmm1 is free.*/ \
+ "movdqa %%xmm3,%%xmm1\n\t" \
+ /*xmm3 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
+ "punpckhdq %%xmm0,%%xmm3\n\t" \
+ /*xmm1 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
+ "punpckldq %%xmm0,%%xmm1\n\t" \
+ /*xmm0 is free.*/ \
+ "movdqa %%xmm4,%%xmm0\n\t" \
+ /*xmm4 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
+ "punpckhdq %%xmm6,%%xmm4\n\t" \
+ /*xmm0 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
+ "punpckldq %%xmm6,%%xmm0\n\t" \
+ /*xmm6 is free.*/ \
+ "movdqa %%xmm5,%%xmm6\n\t" \
+ /*xmm5 = d5 c5 b5 a5 d4 c4 b4 a4*/ \
+ "punpckldq %%xmm2,%%xmm5\n\t" \
+ /*xmm6 = d7 c7 b7 a7 d6 c6 b6 a6*/ \
+ "punpckhdq %%xmm2,%%xmm6\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm1,%%xmm2\n\t" \
+ /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
+ "punpckhqdq %%xmm0,%%xmm1\n\t" \
+ /*xmm2 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "punpcklqdq %%xmm0,%%xmm2\n\t" \
+ /*xmm0 = h7 g7 f7 e7 h6 g6 f6 e6*/ \
+ "movdqa "OC_MEM_OFFS(0x00,buf)",%%xmm0\n\t" \
+ /*buf[1] = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "movdqa %%xmm2,"OC_MEM_OFFS(0x10,buf)"\n\t" \
+ /*xmm2 is free.*/ \
+ "movdqa %%xmm3,%%xmm2\n\t" \
+ /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
+ "punpckhqdq %%xmm4,%%xmm3\n\t" \
+ /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
+ "punpcklqdq %%xmm4,%%xmm2\n\t" \
+ /*xmm4 is free.*/ \
+ "movdqa %%xmm5,%%xmm4\n\t" \
+ /*xmm5 = h5 g5 f5 e5 d5 c5 b5 a5*/ \
+ "punpckhqdq %%xmm7,%%xmm5\n\t" \
+ /*xmm4 = h4 g4 f4 e4 d4 c4 b4 a4*/ \
+ "punpcklqdq %%xmm7,%%xmm4\n\t" \
+ /*xmm7 is free.*/ \
+ "movdqa %%xmm6,%%xmm7\n\t" \
+ /*xmm6 = h6 g6 f6 e6 d6 c6 b6 a6*/ \
+ "punpcklqdq %%xmm0,%%xmm6\n\t" \
+ /*xmm7 = h7 g7 f7 e7 d7 c7 b7 a7*/ \
+ "punpckhqdq %%xmm0,%%xmm7\n\t" \
+ /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "movdqa "OC_MEM_OFFS(0x10,buf)",%%xmm0\n\t" \
+
+# endif
+
+/*Transpose 4 values in each of 8 MMX registers into 8 values in the first
+ four SSE registers.
+ No need to be clever here; we have plenty of room.*/
+# define OC_TRANSPOSE_8x4_MMX2SSE \
+ "#OC_TRANSPOSE_8x4_MMX2SSE\n\t" \
+ "movq2dq %%mm0,%%xmm0\n\t" \
+ "movq2dq %%mm1,%%xmm1\n\t" \
+ /*xmmA = b3 a3 b2 a2 b1 a1 b0 a0*/ \
+ "punpcklwd %%xmm1,%%xmm0\n\t" \
+ "movq2dq %%mm2,%%xmm3\n\t" \
+ "movq2dq %%mm3,%%xmm2\n\t" \
+ /*xmmC = d3 c3 d2 c2 d1 c1 d0 c0*/ \
+ "punpcklwd %%xmm2,%%xmm3\n\t" \
+ "movq2dq %%mm4,%%xmm4\n\t" \
+ "movq2dq %%mm5,%%xmm5\n\t" \
+ /*xmmE = f3 e3 f2 e2 f1 e1 f0 e0*/ \
+ "punpcklwd %%xmm5,%%xmm4\n\t" \
+ "movq2dq %%mm6,%%xmm7\n\t" \
+ "movq2dq %%mm7,%%xmm6\n\t" \
+ /*xmmG = h3 g3 h2 g2 h1 g1 h0 g0*/ \
+ "punpcklwd %%xmm6,%%xmm7\n\t" \
+ "movdqa %%xmm0,%%xmm2\n\t" \
+ /*xmm0 = d1 c1 b1 a1 d0 c0 b0 a0*/ \
+ "punpckldq %%xmm3,%%xmm0\n\t" \
+ /*xmm2 = d3 c3 b3 a3 d2 c2 b2 a2*/ \
+ "punpckhdq %%xmm3,%%xmm2\n\t" \
+ "movdqa %%xmm4,%%xmm5\n\t" \
+ /*xmm4 = h1 g1 f1 e1 h0 g0 f0 e0*/ \
+ "punpckldq %%xmm7,%%xmm4\n\t" \
+ /*xmm3 = h3 g3 f3 e3 h2 g2 f2 e2*/ \
+ "punpckhdq %%xmm7,%%xmm5\n\t" \
+ "movdqa %%xmm0,%%xmm1\n\t" \
+ /*xmm0 = h0 g0 f0 e0 d0 c0 b0 a0*/ \
+ "punpcklqdq %%xmm4,%%xmm0\n\t" \
+ /*xmm1 = h1 g1 f1 e1 d1 c1 b1 a1*/ \
+ "punpckhqdq %%xmm4,%%xmm1\n\t" \
+ "movdqa %%xmm2,%%xmm3\n\t" \
+ /*xmm2 = h2 g2 f2 e2 d2 c2 b2 a2*/ \
+ "punpcklqdq %%xmm5,%%xmm2\n\t" \
+ /*xmm3 = h3 g3 f3 e3 d3 c3 b3 a3*/ \
+ "punpckhqdq %%xmm5,%%xmm3\n\t" \
+
+#endif
diff --git a/thirdparty/libtheora/x86/x86cpu.c b/thirdparty/libtheora/x86/x86cpu.c
new file mode 100644
index 0000000000..49fd76d0ac
--- /dev/null
+++ b/thirdparty/libtheora/x86/x86cpu.c
@@ -0,0 +1,182 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ CPU capability detection for x86 processors.
+ Originally written by Rudolf Marek.
+
+ function:
+ last mod: $Id$
+
+ ********************************************************************/
+
+#include "x86cpu.h"
+
+#if !defined(OC_X86_ASM)
+ogg_uint32_t oc_cpu_flags_get(void){
+ return 0;
+}
+#else
+# if defined(__amd64__)||defined(__x86_64__)
+/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
+ compiling with -fPIC.*/
+# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
+ __asm__ __volatile__( \
+ "cpuid\n\t" \
+ :[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
+ :"a"(_op) \
+ :"cc" \
+ )
+# else
+/*On x86-32, not so much.*/
+# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
+ __asm__ __volatile__( \
+ "xchgl %%ebx,%[ebx]\n\t" \
+ "cpuid\n\t" \
+ "xchgl %%ebx,%[ebx]\n\t" \
+ :[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
+ :"a"(_op) \
+ :"cc" \
+ )
+# endif
+
+static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
+ ogg_uint32_t flags;
+ /*If there isn't even MMX, give up.*/
+ if(!(_edx&0x00800000))return 0;
+ flags=OC_CPU_X86_MMX;
+ if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
+ if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
+ if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
+ if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
+ if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
+ if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
+ return flags;
+}
+
+static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
+ ogg_uint32_t flags;
+ /*If there isn't even MMX, give up.*/
+ if(!(_edx&0x00800000))return 0;
+ flags=OC_CPU_X86_MMX;
+ if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
+ if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
+ if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
+ if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
+ if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
+ return flags;
+}
+
+ogg_uint32_t oc_cpu_flags_get(void){
+ ogg_uint32_t flags;
+ ogg_uint32_t eax;
+ ogg_uint32_t ebx;
+ ogg_uint32_t ecx;
+ ogg_uint32_t edx;
+# if !defined(__amd64__)&&!defined(__x86_64__)
+ /*Not all x86-32 chips support cpuid, so we have to check.*/
+ __asm__ __volatile__(
+ "pushfl\n\t"
+ "pushfl\n\t"
+ "popl %[a]\n\t"
+ "movl %[a],%[b]\n\t"
+ "xorl $0x200000,%[a]\n\t"
+ "pushl %[a]\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %[a]\n\t"
+ "popfl\n\t"
+ :[a]"=r"(eax),[b]"=r"(ebx)
+ :
+ :"cc"
+ );
+ /*No cpuid.*/
+ if(eax==ebx)return 0;
+# endif
+ cpuid(0,eax,ebx,ecx,edx);
+ /* l e t n I e n i u n e G*/
+ if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
+ /* 6 8 x M T e n i u n e G*/
+ ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
+ int family;
+ int model;
+ /*Intel, Transmeta (tested with Crusoe TM5800):*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags=oc_parse_intel_flags(edx,ecx);
+ family=(eax>>8)&0xF;
+ model=(eax>>4)&0xF;
+ /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
+ unit, so don't use it.*/
+ if(family==6&&(model==9||model==13||model==14)){
+ flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
+ }
+ }
+ /* D M A c i t n e h t u A*/
+ else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
+ /* C S N y b e d o e G*/
+ ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){
+ /*AMD, Geode:*/
+ cpuid(0x80000000,eax,ebx,ecx,edx);
+ if(eax<0x80000001)flags=0;
+ else{
+ cpuid(0x80000001,eax,ebx,ecx,edx);
+ flags=oc_parse_amd_flags(edx,ecx);
+ }
+ /*Also check for SSE.*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags|=oc_parse_intel_flags(edx,ecx);
+ }
+ /*Technically some VIA chips can be configured in the BIOS to return any
+ string here the user wants.
+ There is a special detection method that can be used to identify such
+ processors, but in my opinion, if the user really wants to change it, they
+ deserve what they get.*/
+ /* s l u a H r u a t n e C*/
+ else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
+ /*VIA:*/
+ /*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
+ chips (thanks to the engineers from Centaur Technology who provided it).
+ These chips support Intel-like cpuid info.
+ The C3-2 (Nehemiah) cores appear to, as well.*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags=oc_parse_intel_flags(edx,ecx);
+ if(eax>=0x80000001){
+ /*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
+ We need to check this even if the Intel test succeeds to pick up 3DNow!
+ support on these processors.
+ Unlike actual AMD processors, we cannot _rely_ on this info, since
+ some cores (e.g., the 693 stepping of the Nehemiah) claim to support
+ this function, yet return edx=0, despite the Intel test indicating
+ MMX support.
+ Therefore the features detected here are strictly added to those
+ detected by the Intel test.*/
+ /*TODO: How about earlier chips?*/
+ cpuid(0x80000001,eax,ebx,ecx,edx);
+ /*Note: As of the C7, this function returns Intel-style extended feature
+ flags, not AMD-style.
+ Currently, this only defines bits 11, 20, and 29 (0x20100800), which
+ do not conflict with any of the AMD flags we inspect.
+ For the remaining bits, Intel tells us, "Do not count on their value",
+ but VIA assures us that they will all be zero (at least on the C7 and
+ Isaiah chips).
+ In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
+ (0xC0C00000) for something else, we will have to add code to detect
+ the model to decide when it is appropriate to inspect them.*/
+ flags|=oc_parse_amd_flags(edx,ecx);
+ }
+ }
+ else{
+ /*Implement me.*/
+ flags=0;
+ }
+ return flags;
+}
+#endif
diff --git a/thirdparty/libtheora/cpu.h b/thirdparty/libtheora/x86/x86cpu.h
index a43c957a39..e0192d52e2 100644
--- a/thirdparty/libtheora/cpu.h
+++ b/thirdparty/libtheora/x86/x86cpu.h
@@ -10,13 +10,13 @@
* *
********************************************************************
function:
- last mod: $Id: cpu.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
-#if !defined(_x86_cpu_H)
-# define _x86_cpu_H (1)
-#include "internal.h"
+#if !defined(_x86_x86cpu_H)
+# define _x86_x86cpu_H (1)
+#include "../internal.h"
#define OC_CPU_X86_MMX (1<<0)
#define OC_CPU_X86_3DNOW (1<<1)
@@ -31,4 +31,6 @@
#define OC_CPU_X86_SSE4A (1<<10)
#define OC_CPU_X86_SSE5 (1<<11)
+ogg_uint32_t oc_cpu_flags_get(void);
+
#endif
diff --git a/thirdparty/libtheora/x86/x86enc.c b/thirdparty/libtheora/x86/x86enc.c
index 43b7be3ea3..ffa9c14a42 100644
--- a/thirdparty/libtheora/x86/x86enc.c
+++ b/thirdparty/libtheora/x86/x86enc.c
@@ -18,32 +18,46 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc){
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc){
ogg_uint32_t cpu_flags;
- cpu_flags=oc_cpu_flags_get();
- oc_enc_vtable_init_c(_enc);
+ cpu_flags=_enc->state.cpu_flags;
+ oc_enc_accel_init_c(_enc);
+# if defined(OC_ENC_USE_VTABLE)
if(cpu_flags&OC_CPU_X86_MMX){
_enc->opt_vtable.frag_sub=oc_enc_frag_sub_mmx;
_enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_mmx;
_enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
- _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmx;
}
if(cpu_flags&OC_CPU_X86_MMXEXT){
_enc->opt_vtable.frag_sad=oc_enc_frag_sad_mmxext;
_enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_mmxext;
_enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_mmxext;
- _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_mmxext;
- _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_mmxext;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_mmxext;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_mmxext;
_enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_mmxext;
_enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_mmxext;
+ _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmxext;
}
if(cpu_flags&OC_CPU_X86_SSE2){
-# if defined(OC_X86_64_ASM)
- /*_enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_x86_64sse2;*/
+# if defined(OC_X86_64_ASM)
+ _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_x86_64sse2;
+# endif
+ _enc->opt_vtable.frag_ssd=oc_enc_frag_ssd_sse2;
+ _enc->opt_vtable.frag_border_ssd=oc_enc_frag_border_ssd_sse2;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_sse2;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_sse2;
+ _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_sse2;
+ _enc->opt_vtable.enquant_table_init=oc_enc_enquant_table_init_x86;
+ _enc->opt_vtable.enquant_table_fixup=oc_enc_enquant_table_fixup_x86;
+ _enc->opt_vtable.quantize=oc_enc_quantize_sse2;
+# else
+ (void) cpu_flags;
# endif
+ _enc->opt_data.enquant_table_size=128*sizeof(ogg_uint16_t);
+ _enc->opt_data.enquant_table_alignment=16;
+# if defined(OC_ENC_USE_VTABLE)
}
+# endif
}
#endif
diff --git a/thirdparty/libtheora/x86/x86enc.h b/thirdparty/libtheora/x86/x86enc.h
index 06c3908bcd..c258247d67 100644
--- a/thirdparty/libtheora/x86/x86enc.h
+++ b/thirdparty/libtheora/x86/x86enc.h
@@ -17,11 +17,62 @@
#if !defined(_x86_x86enc_H)
# define _x86_x86enc_H (1)
-# include "../encint.h"
# include "x86int.h"
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc);
+# if defined(OC_X86_ASM)
+# define oc_enc_accel_init oc_enc_accel_init_x86
+# if defined(OC_X86_64_ASM)
+/*x86-64 guarantees SIMD support up through at least SSE2.
+ If the best routine we have available only needs SSE2 (which at the moment
+ covers all of them), then we can avoid runtime detection and the indirect
+ call.*/
+# define oc_enc_frag_sub(_enc,_diff,_x,_y,_stride) \
+ oc_enc_frag_sub_mmx(_diff,_x,_y,_stride)
+# define oc_enc_frag_sub_128(_enc,_diff,_x,_stride) \
+ oc_enc_frag_sub_128_mmx(_diff,_x,_stride)
+# define oc_enc_frag_sad(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_sad_mmxext(_src,_ref,_ystride)
+# define oc_enc_frag_sad_thresh(_enc,_src,_ref,_ystride,_thresh) \
+ oc_enc_frag_sad_thresh_mmxext(_src,_ref,_ystride,_thresh)
+# define oc_enc_frag_sad2_thresh(_enc,_src,_ref1,_ref2,_ystride,_thresh) \
+ oc_enc_frag_sad2_thresh_mmxext(_src,_ref1,_ref2,_ystride,_thresh)
+# define oc_enc_frag_satd(_enc,_dc,_src,_ref,_ystride) \
+ oc_enc_frag_satd_sse2(_dc,_src,_ref,_ystride)
+# define oc_enc_frag_satd2(_enc,_dc,_src,_ref1,_ref2,_ystride) \
+ oc_enc_frag_satd2_sse2(_dc,_src,_ref1,_ref2,_ystride)
+# define oc_enc_frag_intra_satd(_enc,_dc,_src,_ystride) \
+ oc_enc_frag_intra_satd_sse2(_dc,_src,_ystride)
+# define oc_enc_frag_ssd(_enc,_src,_ref,_ystride) \
+ oc_enc_frag_ssd_sse2(_src,_ref,_ystride)
+# define oc_enc_frag_border_ssd(_enc,_src,_ref,_ystride,_mask) \
+ oc_enc_frag_border_ssd_sse2(_src,_ref,_ystride,_mask)
+# define oc_enc_frag_copy2(_enc,_dst,_src1,_src2,_ystride) \
+ oc_int_frag_copy2_mmxext(_dst,_ystride,_src1,_src2,_ystride)
+# define oc_enc_enquant_table_init(_enc,_enquant,_dequant) \
+ oc_enc_enquant_table_init_x86(_enquant,_dequant)
+# define oc_enc_enquant_table_fixup(_enc,_enquant,_nqis) \
+ oc_enc_enquant_table_fixup_x86(_enquant,_nqis)
+# define oc_enc_quantize(_enc,_qdct,_dct,_dequant,_enquant) \
+ oc_enc_quantize_sse2(_qdct,_dct,_dequant,_enquant)
+# define oc_enc_frag_recon_intra(_enc,_dst,_ystride,_residue) \
+ oc_frag_recon_intra_mmx(_dst,_ystride,_residue)
+# define oc_enc_frag_recon_inter(_enc,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_mmx(_dst,_src,_ystride,_residue)
+# define oc_enc_fdct8x8(_enc,_y,_x) \
+ oc_enc_fdct8x8_x86_64sse2(_y,_x)
+# else
+# define OC_ENC_USE_VTABLE (1)
+# endif
+# endif
+
+# include "../encint.h"
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc);
+
+void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64],
+ const unsigned char *_x,const unsigned char *_y,int _stride);
+void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64],
+ const unsigned char *_x,int _stride);
unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
@@ -29,19 +80,35 @@ unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,int _ystride);
-void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64],
- const unsigned char *_x,const unsigned char *_y,int _stride);
-void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64],
- const unsigned char *_x,int _stride);
+unsigned oc_enc_frag_satd_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd2_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_satd2_sse2(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_intra_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_intra_satd_sse2(int *_dc,
+ const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_border_ssd_sse2(const unsigned char *_src,
+ const unsigned char *_ref,int _ystride,ogg_int64_t _mask);
+void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
+ const unsigned char *_src1,const unsigned char *_src2,int _src_ystride);
void oc_enc_frag_copy2_mmxext(unsigned char *_dst,
const unsigned char *_src1,const unsigned char *_src2,int _ystride);
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+void oc_enc_enquant_table_init_x86(void *_enquant,
+ const ogg_uint16_t _dequant[64]);
+void oc_enc_enquant_table_fixup_x86(void *_enquant[3][3][2],int _nqis);
+int oc_enc_quantize_sse2(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant);
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+
+# if defined(OC_X86_64_ASM)
void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+# endif
#endif
diff --git a/thirdparty/libtheora/x86/x86enquant.c b/thirdparty/libtheora/x86/x86enquant.c
new file mode 100644
index 0000000000..39477ecc21
--- /dev/null
+++ b/thirdparty/libtheora/x86/x86enquant.c
@@ -0,0 +1,149 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: mmxstate.c 17247 2010-05-28 05:35:32Z tterribe $
+
+ ********************************************************************/
+
+#include "x86enc.h"
+
+#if defined(OC_X86_ASM)
+
+
+
+/*The default enquant table is not quite suitable for SIMD purposes.
+ First, the m and l parameters need to be separated so that an entire row full
+ of m's or l's can be loaded at a time.
+ Second, x86 SIMD has no element-wise arithmetic right-shift, so we have to
+ emulate one with a multiply.
+ Therefore we translate the shift count into a scale factor.*/
+void oc_enc_enquant_table_init_x86(void *_enquant,
+ const ogg_uint16_t _dequant[64]){
+ ogg_int16_t *m;
+ ogg_int16_t *l;
+ int zzi;
+ m=(ogg_int16_t *)_enquant;
+ l=m+64;
+ for(zzi=0;zzi<64;zzi++){
+ oc_iquant q;
+ oc_iquant_init(&q,_dequant[zzi]);
+ m[zzi]=q.m;
+ /*q.l must be at least 2 for this to work; fortunately, once all the scale
+ factors are baked in, the minimum quantizer is much larger than that.*/
+ l[zzi]=1<<16-q.l;
+ }
+}
+
+void oc_enc_enquant_table_fixup_x86(void *_enquant[3][3][2],int _nqis){
+ int pli;
+ int qii;
+ int qti;
+ for(pli=0;pli<3;pli++)for(qii=1;qii<_nqis;qii++)for(qti=0;qti<2;qti++){
+ ((ogg_int16_t *)_enquant[pli][qii][qti])[0]=
+ ((ogg_int16_t *)_enquant[pli][0][qti])[0];
+ ((ogg_int16_t *)_enquant[pli][qii][qti])[64]=
+ ((ogg_int16_t *)_enquant[pli][0][qti])[64];
+ }
+}
+
+int oc_enc_quantize_sse2(ogg_int16_t _qdct[64],const ogg_int16_t _dct[64],
+ const ogg_uint16_t _dequant[64],const void *_enquant){
+ ptrdiff_t r;
+ __asm__ __volatile__(
+ "xor %[r],%[r]\n\t"
+ /*Loop through two rows at a time.*/
+ ".p2align 4\n\t"
+ "0:\n\t"
+ /*Load the first two rows of the data and the quant matrices.*/
+ "movdqa 0x00(%[dct],%[r]),%%xmm0\n\t"
+ "movdqa 0x10(%[dct],%[r]),%%xmm1\n\t"
+ "movdqa 0x00(%[dq],%[r]),%%xmm2\n\t"
+ "movdqa 0x10(%[dq],%[r]),%%xmm3\n\t"
+ "movdqa 0x00(%[q],%[r]),%%xmm4\n\t"
+ "movdqa 0x10(%[q],%[r]),%%xmm5\n\t"
+ /*Double the input and propagate its sign to the rounding factor.
+ Using SSSE3's psignw would help here, but we need the mask later anyway.*/
+ "movdqa %%xmm0,%%xmm6\n\t"
+ "psraw $15,%%xmm0\n\t"
+ "movdqa %%xmm1,%%xmm7\n\t"
+ "paddw %%xmm6,%%xmm6\n\t"
+ "psraw $15,%%xmm1\n\t"
+ "paddw %%xmm7,%%xmm7\n\t"
+ "paddw %%xmm0,%%xmm2\n\t"
+ "paddw %%xmm1,%%xmm3\n\t"
+ "pxor %%xmm0,%%xmm2\n\t"
+ "pxor %%xmm1,%%xmm3\n\t"
+ /*Add the rounding factor and perform the first multiply.*/
+ "paddw %%xmm2,%%xmm6\n\t"
+ "paddw %%xmm3,%%xmm7\n\t"
+ "pmulhw %%xmm6,%%xmm4\n\t"
+ "pmulhw %%xmm7,%%xmm5\n\t"
+ "movdqa 0x80(%[q],%[r]),%%xmm2\n\t"
+ "movdqa 0x90(%[q],%[r]),%%xmm3\n\t"
+ "paddw %%xmm4,%%xmm6\n\t"
+ "paddw %%xmm5,%%xmm7\n\t"
+ /*Emulate an element-wise right-shift via a second multiply.*/
+ "pmulhw %%xmm2,%%xmm6\n\t"
+ "pmulhw %%xmm3,%%xmm7\n\t"
+ "add $32,%[r]\n\t"
+ "cmp $96,%[r]\n\t"
+ /*Correct for the sign.*/
+ "psubw %%xmm0,%%xmm6\n\t"
+ "psubw %%xmm1,%%xmm7\n\t"
+ /*Save the result.*/
+ "movdqa %%xmm6,-0x20(%[qdct],%[r])\n\t"
+ "movdqa %%xmm7,-0x10(%[qdct],%[r])\n\t"
+ "jle 0b\n\t"
+ /*Now find the location of the last non-zero value.*/
+ "movdqa 0x50(%[qdct]),%%xmm5\n\t"
+ "movdqa 0x40(%[qdct]),%%xmm4\n\t"
+ "packsswb %%xmm7,%%xmm6\n\t"
+ "packsswb %%xmm5,%%xmm4\n\t"
+ "pxor %%xmm0,%%xmm0\n\t"
+ "mov $-1,%k[dq]\n\t"
+ "pcmpeqb %%xmm0,%%xmm6\n\t"
+ "pcmpeqb %%xmm0,%%xmm4\n\t"
+ "pmovmskb %%xmm6,%k[q]\n\t"
+ "pmovmskb %%xmm4,%k[r]\n\t"
+ "shl $16,%k[q]\n\t"
+ "or %k[r],%k[q]\n\t"
+ "mov $32,%[r]\n\t"
+ /*We have to use xor here instead of not in order to set the flags.*/
+ "xor %k[dq],%k[q]\n\t"
+ "jnz 1f\n\t"
+ "movdqa 0x30(%[qdct]),%%xmm7\n\t"
+ "movdqa 0x20(%[qdct]),%%xmm6\n\t"
+ "movdqa 0x10(%[qdct]),%%xmm5\n\t"
+ "movdqa 0x00(%[qdct]),%%xmm4\n\t"
+ "packsswb %%xmm7,%%xmm6\n\t"
+ "packsswb %%xmm5,%%xmm4\n\t"
+ "pcmpeqb %%xmm0,%%xmm6\n\t"
+ "pcmpeqb %%xmm0,%%xmm4\n\t"
+ "pmovmskb %%xmm6,%k[q]\n\t"
+ "pmovmskb %%xmm4,%k[r]\n\t"
+ "shl $16,%k[q]\n\t"
+ "or %k[r],%k[q]\n\t"
+ "xor %[r],%[r]\n\t"
+ "not %k[q]\n\t"
+ "or $1,%k[q]\n\t"
+ "1:\n\t"
+ "bsr %k[q],%k[q]\n\t"
+ "add %k[q],%k[r]\n\t"
+ :[r]"=&a"(r),[q]"+r"(_enquant),[dq]"+r"(_dequant)
+ :[dct]"r"(_dct),[qdct]"r"(_qdct)
+ :"cc","memory"
+ );
+ return (int)r;
+}
+
+#endif
diff --git a/thirdparty/libtheora/x86/x86int.h b/thirdparty/libtheora/x86/x86int.h
index ede724f5aa..ceb2dbb0ec 100644
--- a/thirdparty/libtheora/x86/x86int.h
+++ b/thirdparty/libtheora/x86/x86int.h
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: x86int.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,24 +19,104 @@
# define _x86_x86int_H (1)
# include "../internal.h"
-void oc_state_vtable_init_x86(oc_theora_state *_state);
+# if defined(OC_X86_ASM)
+# define oc_state_accel_init oc_state_accel_init_x86
+# if defined(OC_X86_64_ASM)
+/*x86-64 guarantees SIMD support up through at least SSE2.
+ If the best routine we have available only needs SSE2 (which at the moment
+ covers all of them), then we can avoid runtime detection and the indirect
+ call.*/
+# define oc_frag_copy(_state,_dst,_src,_ystride) \
+ oc_frag_copy_mmx(_dst,_src,_ystride)
+# define oc_frag_copy_list(_state,_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs) \
+ oc_frag_copy_list_mmx(_dst_frame,_src_frame,_ystride, \
+ _fragis,_nfragis,_frag_buf_offs)
+# define oc_frag_recon_intra(_state,_dst,_ystride,_residue) \
+ oc_frag_recon_intra_mmx(_dst,_ystride,_residue)
+# define oc_frag_recon_inter(_state,_dst,_src,_ystride,_residue) \
+ oc_frag_recon_inter_mmx(_dst,_src,_ystride,_residue)
+# define oc_frag_recon_inter2(_state,_dst,_src1,_src2,_ystride,_residue) \
+ oc_frag_recon_inter2_mmx(_dst,_src1,_src2,_ystride,_residue)
+# define oc_idct8x8(_state,_y,_x,_last_zzi) \
+ oc_idct8x8_sse2(_y,_x,_last_zzi)
+# define oc_state_frag_recon oc_state_frag_recon_mmx
+# define oc_loop_filter_init(_state,_bv,_flimit) \
+ oc_loop_filter_init_mmxext(_bv,_flimit)
+# define oc_state_loop_filter_frag_rows oc_state_loop_filter_frag_rows_mmxext
+# define oc_restore_fpu(_state) \
+ oc_restore_fpu_mmx()
+# else
+# define OC_STATE_USE_VTABLE (1)
+# endif
+# endif
+
+# include "../state.h"
+# include "x86cpu.h"
+
+/*Converts the expression in the argument to a string.*/
+#define OC_M2STR(_s) #_s
+
+/*Memory operands do not always include an offset.
+ To avoid warnings, we force an offset with %H (which adds 8).*/
+# if __GNUC_PREREQ(4,0)
+# define OC_MEM_OFFS(_offs,_name) \
+ OC_M2STR(_offs-8+%H[_name])
+# endif
+/*If your gcc version does't support %H, then you get to suffer the warnings.
+ Note that Apple's gas breaks on things like _offs+(%esp): it throws away the
+ whole offset, instead of substituting in 0 for the missing operand to +.*/
+# if !defined(OC_MEM_OFFS)
+# define OC_MEM_OFFS(_offs,_name) \
+ OC_M2STR(_offs+%[_name])
+# endif
+
+/*Declare an array operand with an exact size.
+ This tells gcc we're going to clobber this memory region, without having to
+ clobber all of "memory" and lets us access local buffers directly using the
+ stack pointer, without allocating a separate register to point to them.*/
+#define OC_ARRAY_OPERAND(_type,_ptr,_size) \
+ (*({ \
+ struct{_type array_value__[(_size)];} *array_addr__=(void *)(_ptr); \
+ array_addr__; \
+ }))
+
+/*Declare an array operand with an exact size.
+ This tells gcc we're going to clobber this memory region, without having to
+ clobber all of "memory" and lets us access local buffers directly using the
+ stack pointer, without allocating a separate register to point to them.*/
+#define OC_CONST_ARRAY_OPERAND(_type,_ptr,_size) \
+ (*({ \
+ const struct{_type array_value__[(_size)];} *array_addr__= \
+ (const void *)(_ptr); \
+ array_addr__; \
+ }))
+
+extern const unsigned short __attribute__((aligned(16))) OC_IDCT_CONSTS[64];
+
+void oc_state_accel_init_x86(oc_theora_state *_state);
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride);
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue);
void oc_frag_recon_inter_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride,const ogg_int16_t *_residue);
void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue);
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi);
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
+void oc_idct8x8_sse2(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit);
+void oc_loop_filter_init_mmxext(signed char _bv[256],int _flimit);
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+void oc_state_loop_filter_frag_rows_mmxext(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
void oc_restore_fpu_mmx(void);
#endif
diff --git a/thirdparty/libtheora/x86/x86state.c b/thirdparty/libtheora/x86/x86state.c
index a786bec284..9f8bceb534 100644
--- a/thirdparty/libtheora/x86/x86state.c
+++ b/thirdparty/libtheora/x86/x86state.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: x86state.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,8 +19,7 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
+#if defined(OC_STATE_USE_VTABLE)
/*This table has been modified from OC_FZIG_ZAG by baking a 4x4 transpose into
each quadrant of the destination.*/
static const unsigned char OC_FZIG_ZAG_MMX[128]={
@@ -39,24 +38,60 @@ static const unsigned char OC_FZIG_ZAG_MMX[128]={
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64
+};
+#endif
+
+/*This table has been modified from OC_FZIG_ZAG by baking an 8x8 transpose into
+ the destination.*/
+static const unsigned char OC_FZIG_ZAG_SSE2[128]={
+ 0, 8, 1, 2, 9,16,24,17,
+ 10, 3, 4,11,18,25,32,40,
+ 33,26,19,12, 5, 6,13,20,
+ 27,34,41,48,56,49,42,35,
+ 28,21,14, 7,15,22,29,36,
+ 43,50,57,58,51,44,37,30,
+ 23,31,38,45,52,59,60,53,
+ 46,39,47,54,61,62,55,63,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64
};
-void oc_state_vtable_init_x86(oc_theora_state *_state){
+void oc_state_accel_init_x86(oc_theora_state *_state){
+ oc_state_accel_init_c(_state);
_state->cpu_flags=oc_cpu_flags_get();
+# if defined(OC_STATE_USE_VTABLE)
if(_state->cpu_flags&OC_CPU_X86_MMX){
_state->opt_vtable.frag_copy=oc_frag_copy_mmx;
+ _state->opt_vtable.frag_copy_list=oc_frag_copy_list_mmx;
_state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
_state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_mmx;
_state->opt_vtable.idct8x8=oc_idct8x8_mmx;
_state->opt_vtable.state_frag_recon=oc_state_frag_recon_mmx;
- _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_mmx;
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_mmx;
_state->opt_vtable.state_loop_filter_frag_rows=
oc_state_loop_filter_frag_rows_mmx;
_state->opt_vtable.restore_fpu=oc_restore_fpu_mmx;
_state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_MMX;
}
- else oc_state_vtable_init_c(_state);
+ if(_state->cpu_flags&OC_CPU_X86_MMXEXT){
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_mmxext;
+ _state->opt_vtable.state_loop_filter_frag_rows=
+ oc_state_loop_filter_frag_rows_mmxext;
+ }
+ if(_state->cpu_flags&OC_CPU_X86_SSE2){
+ _state->opt_vtable.idct8x8=oc_idct8x8_sse2;
+# endif
+ _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_SSE2;
+# if defined(OC_STATE_USE_VTABLE)
+ }
+# endif
}
#endif
diff --git a/thirdparty/libtheora/x86/x86zigzag.h b/thirdparty/libtheora/x86/x86zigzag.h
new file mode 100644
index 0000000000..fb21e0bb43
--- /dev/null
+++ b/thirdparty/libtheora/x86/x86zigzag.h
@@ -0,0 +1,244 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: sse2trans.h 15675 2009-02-06 09:43:27Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_x86zigzag_H)
+# define _x86_x86zigzag_H (1)
+# include "x86enc.h"
+
+
+/*Converts DCT coefficients from transposed order into zig-zag scan order and
+ stores them in %[y].
+ This relies on two macros to load the contents of each row:
+ OC_ZZ_LOAD_ROW_LO(row,"reg") and OC_ZZ_LOAD_ROW_HI(row,"reg"), which load
+ the first four and second four entries of each row into the specified
+ register, respectively.
+ OC_ZZ_LOAD_ROW_LO must be called before OC_ZZ_LOAD_ROW_HI for the same row
+ (because when the rows are already in SSE2 registers, loading the high half
+ destructively modifies the register).
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 8 1 2 9 16 24 17 B
+ C 10 3 4 11 18 25 32 40 E
+ F 33 26 19 12 5 6 13 20 D
+ G 27 34 41 48 56 49 42 35 I
+ L 28 21 14 7 15 22 29 36 M
+ H 43 50 57 58 51 44 37 30 O
+ N 23 31 38 45 52 59 60 53 J
+ P 46 39 47 54 61 62 55 63 K
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_TRANSPOSE_ZIG_ZAG_MMXEXT \
+ OC_ZZ_LOAD_ROW_LO(0,"%%mm0") /*mm0=03 02 01 00*/ \
+ OC_ZZ_LOAD_ROW_LO(1,"%%mm1") /*mm1=11 10 09 08*/ \
+ OC_ZZ_LOAD_ROW_LO(2,"%%mm2") /*mm2=19 18 17 16*/ \
+ OC_ZZ_LOAD_ROW_LO(3,"%%mm3") /*mm3=27 26 25 24*/ \
+ OC_ZZ_LOAD_ROW_HI(0,"%%mm4") /*mm4=07 06 05 04*/ \
+ OC_ZZ_LOAD_ROW_HI(1,"%%mm5") /*mm5=15 14 13 12*/ \
+ OC_ZZ_LOAD_ROW_HI(2,"%%mm6") /*mm6=23 22 21 20*/ \
+ "movq %%mm0,%%mm7\n\t" /*mm7=03 02 01 00*/ \
+ "punpckhdq %%mm1,%%mm0\n\t" /*mm0=11 10 03 02*/ \
+ "pshufw $0x39,%%mm4,%%mm4\n\t" /*mm4=04 07 06 05*/ \
+ "punpcklwd %%mm0,%%mm1\n\t" /*mm1=03 09 02 08*/ \
+ "pshufw $0x39,%%mm5,%%mm5\n\t" /*mm5=12 15 14 13*/ \
+ "punpcklwd %%mm1,%%mm7\n\t" /*mm7=02 01 08 00 *A*/ \
+ "movq %%mm7,0x00(%[y])\n\t" \
+ "punpckhwd %%mm4,%%mm1\n\t" /*mm1=04 03 07 09*/ \
+ "movq %%mm2,%%mm7\n\t" /*mm7=19 18 17 16*/ \
+ "punpckhdq %%mm1,%%mm0\n\t" /*mm0=04 03 11 10*/ \
+ "punpckhwd %%mm5,%%mm7\n\t" /*mm7=12 19 15 18*/ \
+ "punpcklwd %%mm3,%%mm1\n\t" /*mm1=25 07 24 09*/ \
+ "punpcklwd %%mm6,%%mm5\n\t" /*mm5=21 14 20 13*/ \
+ "punpcklwd %%mm2,%%mm1\n\t" /*mm1=17 24 16 09 *B*/ \
+ OC_ZZ_LOAD_ROW_LO(4,"%%mm2") /*mm2=35 34 33 32*/ \
+ "movq %%mm1,0x08(%[y])\n\t" \
+ OC_ZZ_LOAD_ROW_LO(5,"%%mm1") /*mm1=43 42 41 40*/ \
+ "pshufw $0x78,%%mm0,%%mm0\n\t" /*mm0=11 04 03 10 *C*/ \
+ "movq %%mm0,0x10(%[y])\n\t" \
+ "punpckhdq %%mm4,%%mm6\n\t" /*mm6=?? 07 23 22*/ \
+ "punpckldq %%mm5,%%mm4\n\t" /*mm4=20 13 06 05 *D*/ \
+ "movq %%mm4,0x28(%[y])\n\t" \
+ "psrlq $16,%%mm3\n\t" /*mm3=.. 27 26 25*/ \
+ "pshufw $0x0E,%%mm2,%%mm0\n\t" /*mm0=?? ?? 35 34*/ \
+ "movq %%mm7,%%mm4\n\t" /*mm4=12 19 15 18*/ \
+ "punpcklwd %%mm3,%%mm2\n\t" /*mm2=26 33 25 32*/ \
+ "punpcklwd %%mm1,%%mm4\n\t" /*mm4=41 15 40 18*/ \
+ "punpckhwd %%mm1,%%mm3\n\t" /*mm3=43 .. 42 27*/ \
+ "punpckldq %%mm2,%%mm4\n\t" /*mm4=25 32 40 18*/ \
+ "punpcklwd %%mm0,%%mm3\n\t" /*mm3=35 42 34 27*/ \
+ OC_ZZ_LOAD_ROW_LO(6,"%%mm0") /*mm0=51 50 49 48*/ \
+ "pshufw $0x6C,%%mm4,%%mm4\n\t" /*mm4=40 32 25 18 *E*/ \
+ "movq %%mm4,0x18(%[y])\n\t" \
+ OC_ZZ_LOAD_ROW_LO(7,"%%mm4") /*mm4=59 58 57 56*/ \
+ "punpckhdq %%mm7,%%mm2\n\t" /*mm2=12 19 26 33 *F*/ \
+ "movq %%mm2,0x20(%[y])\n\t" \
+ "pshufw $0xD0,%%mm1,%%mm1\n\t" /*mm1=43 41 ?? ??*/ \
+ "pshufw $0x87,%%mm0,%%mm0\n\t" /*mm0=50 48 49 51*/ \
+ "movq %%mm3,%%mm2\n\t" /*mm2=35 42 34 27*/ \
+ "punpckhwd %%mm0,%%mm1\n\t" /*mm1=50 43 48 41*/ \
+ "pshufw $0x93,%%mm4,%%mm4\n\t" /*mm4=58 57 56 59*/ \
+ "punpckldq %%mm1,%%mm3\n\t" /*mm3=48 41 34 27 *G*/ \
+ "movq %%mm3,0x30(%[y])\n\t" \
+ "punpckhdq %%mm4,%%mm1\n\t" /*mm1=58 57 50 43 *H*/ \
+ "movq %%mm1,0x50(%[y])\n\t" \
+ OC_ZZ_LOAD_ROW_HI(7,"%%mm1") /*mm1=63 62 61 60*/ \
+ "punpcklwd %%mm0,%%mm4\n\t" /*mm4=49 56 51 59*/ \
+ OC_ZZ_LOAD_ROW_HI(6,"%%mm0") /*mm0=55 54 53 52*/ \
+ "psllq $16,%%mm6\n\t" /*mm6=07 23 22 ..*/ \
+ "movq %%mm4,%%mm3\n\t" /*mm3=49 56 51 59*/ \
+ "punpckhdq %%mm2,%%mm4\n\t" /*mm4=35 42 49 56 *I*/ \
+ OC_ZZ_LOAD_ROW_HI(3,"%%mm2") /*mm2=31 30 29 28*/ \
+ "movq %%mm4,0x38(%[y])\n\t" \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=61 51 60 59*/ \
+ "punpcklwd %%mm6,%%mm7\n\t" /*mm7=22 15 .. ??*/ \
+ "movq %%mm3,%%mm4\n\t" /*mm4=61 51 60 59*/ \
+ "punpcklwd %%mm0,%%mm3\n\t" /*mm3=53 60 52 59*/ \
+ "punpckhwd %%mm0,%%mm4\n\t" /*mm4=55 61 54 51*/ \
+ OC_ZZ_LOAD_ROW_HI(4,"%%mm0") /*mm0=39 38 37 36*/ \
+ "pshufw $0xE1,%%mm3,%%mm3\n\t" /*mm3=53 60 59 52 *J*/ \
+ "movq %%mm3,0x68(%[y])\n\t" \
+ "movq %%mm4,%%mm3\n\t" /*mm3=?? ?? 54 51*/ \
+ "pshufw $0x39,%%mm2,%%mm2\n\t" /*mm2=28 31 30 29*/ \
+ "punpckhwd %%mm1,%%mm4\n\t" /*mm4=63 55 62 61 *K*/ \
+ OC_ZZ_LOAD_ROW_HI(5,"%%mm1") /*mm1=47 46 45 44*/ \
+ "movq %%mm4,0x78(%[y])\n\t" \
+ "punpckhwd %%mm2,%%mm6\n\t" /*mm6=28 07 31 23*/ \
+ "punpcklwd %%mm0,%%mm2\n\t" /*mm2=37 30 36 29*/ \
+ "punpckhdq %%mm6,%%mm5\n\t" /*mm5=28 07 21 14*/ \
+ "pshufw $0x4B,%%mm2,%%mm2\n\t" /*mm2=36 29 30 37*/ \
+ "pshufw $0x87,%%mm5,%%mm5\n\t" /*mm5=07 14 21 28 *L*/ \
+ "movq %%mm5,0x40(%[y])\n\t" \
+ "punpckhdq %%mm2,%%mm7\n\t" /*mm7=36 29 22 15 *M*/ \
+ "movq %%mm7,0x48(%[y])\n\t" \
+ "pshufw $0x9C,%%mm1,%%mm1\n\t" /*mm1=46 45 47 44*/ \
+ "punpckhwd %%mm1,%%mm0\n\t" /*mm0=46 39 45 38*/ \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=47 54 44 51*/ \
+ "punpckldq %%mm0,%%mm6\n\t" /*mm6=45 38 31 23 *N*/ \
+ "movq %%mm6,0x60(%[y])\n\t" \
+ "punpckhdq %%mm3,%%mm0\n\t" /*mm0=47 54 46 39*/ \
+ "punpckldq %%mm2,%%mm3\n\t" /*mm3=30 37 44 51 *O*/ \
+ "movq %%mm3,0x58(%[y])\n\t" \
+ "pshufw $0xB1,%%mm0,%%mm0\n\t" /*mm0=54 47 39 46 *P*/ \
+ "movq %%mm0,0x70(%[y])\n\t" \
+
+/*Converts DCT coefficients in %[dct] from natural order into zig-zag scan
+ order and stores them in %[qdct].
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 1 8 16 9 2 3 10 B
+ C 17 24 32 25 18 11 4 5 D
+ E 12 19 26 33 40 48 41 34 I
+ H 27 20 13 6 7 14 21 28 G
+ K 35 42 49 56 57 50 43 36 J
+ F 29 22 15 23 30 37 44 51 M
+ P 58 59 52 45 38 31 39 46 L
+ N 53 60 61 54 47 55 62 63 O
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_ZIG_ZAG_MMXEXT \
+ "movq 0x00(%[dct]),%%mm0\n\t" /*mm0=03 02 01 00*/ \
+ "movq 0x08(%[dct]),%%mm1\n\t" /*mm1=07 06 05 04*/ \
+ "movq 0x10(%[dct]),%%mm2\n\t" /*mm2=11 10 09 08*/ \
+ "movq 0x20(%[dct]),%%mm3\n\t" /*mm3=19 18 17 16*/ \
+ "movq 0x30(%[dct]),%%mm4\n\t" /*mm4=27 26 25 24*/ \
+ "movq 0x40(%[dct]),%%mm5\n\t" /*mm5=35 34 33 32*/ \
+ "movq %%mm2,%%mm7\n\t" /*mm7=11 10 09 08*/ \
+ "punpcklwd %%mm3,%%mm2\n\t" /*mm2=17 09 16 08*/ \
+ "movq %%mm0,%%mm6\n\t" /*mm6=03 02 01 00*/ \
+ "punpckldq %%mm2,%%mm0\n\t" /*mm0=16 08 01 00 *A*/ \
+ "movq %%mm0,0x00(%[qdct])\n\t" \
+ "movq 0x18(%[dct]),%%mm0\n\t" /*mm0=15 14 13 12*/ \
+ "punpckhdq %%mm6,%%mm6\n\t" /*mm6=03 02 03 02*/ \
+ "psrlq $16,%%mm7\n\t" /*mm7=.. 11 10 09*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=10 09 03 02*/ \
+ "punpckhwd %%mm7,%%mm3\n\t" /*mm3=.. 19 11 18*/ \
+ "pshufw $0xD2,%%mm6,%%mm6\n\t" /*mm6=10 03 02 09 *B*/ \
+ "movq %%mm6,0x08(%[qdct])\n\t" \
+ "psrlq $48,%%mm2\n\t" /*mm2=.. .. .. 17*/ \
+ "movq %%mm1,%%mm6\n\t" /*mm6=07 06 05 04*/ \
+ "punpcklwd %%mm5,%%mm2\n\t" /*mm2=33 .. 32 17*/ \
+ "movq %%mm3,%%mm7\n\t" /*mm7=.. 19 11 18*/ \
+ "punpckldq %%mm1,%%mm3\n\t" /*mm3=05 04 11 18 *C*/ \
+ "por %%mm2,%%mm7\n\t" /*mm7=33 19 ?? ??*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=25 32 24 17 *D**/ \
+ "movq %%mm2,0x10(%[qdct])\n\t" \
+ "movq %%mm3,0x18(%[qdct])\n\t" \
+ "movq 0x28(%[dct]),%%mm2\n\t" /*mm2=23 22 21 20*/ \
+ "movq 0x38(%[dct]),%%mm1\n\t" /*mm1=31 30 29 28*/ \
+ "pshufw $0x9C,%%mm0,%%mm3\n\t" /*mm3=14 13 15 12*/ \
+ "punpckhdq %%mm7,%%mm7\n\t" /*mm7=33 19 33 19*/ \
+ "punpckhwd %%mm3,%%mm6\n\t" /*mm6=14 07 13 06*/ \
+ "punpckldq %%mm0,%%mm0\n\t" /*mm0=13 12 13 12*/ \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=29 15 28 12*/ \
+ "punpckhwd %%mm4,%%mm0\n\t" /*mm0=27 13 26 12*/ \
+ "pshufw $0xB4,%%mm3,%%mm3\n\t" /*mm3=15 29 28 12*/ \
+ "psrlq $48,%%mm4\n\t" /*mm4=.. .. .. 27*/ \
+ "punpcklwd %%mm7,%%mm0\n\t" /*mm0=33 26 19 12 *E*/ \
+ "punpcklwd %%mm1,%%mm4\n\t" /*mm4=29 .. 28 27*/ \
+ "punpckhwd %%mm2,%%mm3\n\t" /*mm3=23 15 22 29 *F*/ \
+ "movq %%mm0,0x20(%[qdct])\n\t" \
+ "movq %%mm3,0x50(%[qdct])\n\t" \
+ "movq 0x60(%[dct]),%%mm3\n\t" /*mm3=51 50 49 48*/ \
+ "movq 0x70(%[dct]),%%mm7\n\t" /*mm7=59 58 57 56*/ \
+ "movq 0x50(%[dct]),%%mm0\n\t" /*mm0=43 42 41 40*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=28 21 27 20*/ \
+ "psrlq $32,%%mm5\n\t" /*mm5=.. .. 35 34*/ \
+ "movq %%mm2,%%mm4\n\t" /*mm4=28 21 27 20*/ \
+ "punpckldq %%mm6,%%mm2\n\t" /*mm2=13 06 27 20*/ \
+ "punpckhdq %%mm4,%%mm6\n\t" /*mm6=28 21 14 07 *G*/ \
+ "movq %%mm3,%%mm4\n\t" /*mm4=51 50 49 48*/ \
+ "pshufw $0xB1,%%mm2,%%mm2\n\t" /*mm2=06 13 20 27 *H*/ \
+ "movq %%mm2,0x30(%[qdct])\n\t" \
+ "movq %%mm6,0x38(%[qdct])\n\t" \
+ "movq 0x48(%[dct]),%%mm2\n\t" /*mm2=39 38 37 36*/ \
+ "punpcklwd %%mm5,%%mm4\n\t" /*mm4=35 49 34 48*/ \
+ "movq 0x58(%[dct]),%%mm5\n\t" /*mm5=47 46 45 44*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=57 56 14 07*/ \
+ "psrlq $32,%%mm3\n\t" /*mm3=.. .. 51 50*/ \
+ "punpckhwd %%mm0,%%mm6\n\t" /*mm6=43 57 42 56*/ \
+ "punpcklwd %%mm4,%%mm0\n\t" /*mm0=34 41 48 40 *I*/ \
+ "pshufw $0x4E,%%mm6,%%mm6\n\t" /*mm6=42 56 43 57*/ \
+ "movq %%mm0,0x28(%[qdct])\n\t" \
+ "punpcklwd %%mm2,%%mm3\n\t" /*mm3=37 51 36 50*/ \
+ "punpckhwd %%mm6,%%mm4\n\t" /*mm4=42 35 56 49*/ \
+ "punpcklwd %%mm3,%%mm6\n\t" /*mm6=36 43 50 57 *J*/ \
+ "pshufw $0x4E,%%mm4,%%mm4\n\t" /*mm4=56 49 42 35 *K*/ \
+ "movq %%mm4,0x40(%[qdct])\n\t" \
+ "movq %%mm6,0x48(%[qdct])\n\t" \
+ "movq 0x68(%[dct]),%%mm6\n\t" /*mm6=55 54 53 52*/ \
+ "movq 0x78(%[dct]),%%mm0\n\t" /*mm0=63 62 61 60*/ \
+ "psrlq $32,%%mm1\n\t" /*mm1=.. .. 31 30*/ \
+ "pshufw $0xD8,%%mm5,%%mm5\n\t" /*mm5=47 45 46 44*/ \
+ "pshufw $0x0B,%%mm3,%%mm3\n\t" /*mm3=50 50 51 37*/ \
+ "punpcklwd %%mm5,%%mm1\n\t" /*mm1=46 31 44 30*/ \
+ "pshufw $0xC9,%%mm6,%%mm6\n\t" /*mm6=55 52 54 53*/ \
+ "punpckhwd %%mm1,%%mm2\n\t" /*mm2=46 39 31 38 *L*/ \
+ "punpcklwd %%mm3,%%mm1\n\t" /*mm1=51 44 37 30 *M*/ \
+ "movq %%mm2,0x68(%[qdct])\n\t" \
+ "movq %%mm1,0x58(%[qdct])\n\t" \
+ "punpckhwd %%mm6,%%mm5\n\t" /*mm5=55 47 52 45*/ \
+ "punpckldq %%mm0,%%mm6\n\t" /*mm6=61 60 54 53*/ \
+ "pshufw $0x10,%%mm5,%%mm4\n\t" /*mm4=45 52 45 45*/ \
+ "pshufw $0x78,%%mm6,%%mm6\n\t" /*mm6=53 60 61 54 *N*/ \
+ "punpckhdq %%mm0,%%mm5\n\t" /*mm5=63 62 55 47 *O*/ \
+ "punpckhdq %%mm4,%%mm7\n\t" /*mm7=45 52 59 58 *P*/ \
+ "movq %%mm6,0x70(%[qdct])\n\t" \
+ "movq %%mm5,0x78(%[qdct])\n\t" \
+ "movq %%mm7,0x60(%[qdct])\n\t" \
+
+#endif
diff --git a/thirdparty/libtheora/x86_vc/mmxencfrag.c b/thirdparty/libtheora/x86_vc/mmxencfrag.c
index 94f1d06513..a6be819135 100644
--- a/thirdparty/libtheora/x86_vc/mmxencfrag.c
+++ b/thirdparty/libtheora/x86_vc/mmxencfrag.c
@@ -266,7 +266,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
/*Performs the first two stages of an 8-point 1-D Hadamard transform.
The transform is performed in place, except that outputs 0-3 are swapped with
outputs 4-7.
- Outputs 2, 3, 6 and 7 from the second stage are negated (which allows us to
+ Outputs 2, 3, 6, and 7 from the second stage are negated (which allows us to
perform this stage in place with no temporary registers).*/
#define OC_HADAMARD_AB_8x4 __asm{ \
/*Stage A: \
@@ -299,7 +299,7 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
}
/*Performs the last stage of an 8-point 1-D Hadamard transform in place.
- Ouputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
+ Outputs 1, 3, 5, and 7 are negated (which allows us to perform this stage in
place with no temporary registers).*/
#define OC_HADAMARD_C_8x4 __asm{ \
/*Stage C:*/ \
@@ -468,12 +468,14 @@ unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
mm7 = d3 c3 b3 a3*/ \
}
-static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
- int _src_ystride,const unsigned char *_ref,int _ref_ystride,unsigned _thresh){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret1;
- unsigned ret2;
+static unsigned oc_int_frag_satd_mmxext(int *_dc,
+ const unsigned char *_src,int _src_ystride,
+ const unsigned char *_ref,int _ref_ystride){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ unsigned ret;
+ unsigned ret2;
+ int dc;
bufp=buf;
__asm{
#define SRC esi
@@ -481,8 +483,10 @@ static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
#define SRC_YSTRIDE ecx
#define REF_YSTRIDE edx
#define BUF edi
-#define RET eax
-#define RET2 edx
+#define RET edx
+#define RET2 ecx
+#define DC eax
+#define DC_WORD ax
mov SRC,_src
mov SRC_YSTRIDE,_src_ystride
mov REF,_ref
@@ -508,14 +512,18 @@ static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
movq mm2,[0x20+BUF]
movq mm3,[0x30+BUF]
movq mm0,[0x00+BUF]
- OC_HADAMARD_ABS_ACCUM_8x4(0x28,0x38)
+ /*We split out the stages here so we can save the DC coefficient in the
+ middle.*/
+ OC_HADAMARD_AB_8x4
+ OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
+ movd DC,mm1
+ OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
for the factor of two we dropped + 3 for the vertical accumulation).
Now we finally have to promote things to dwords.
We break this part out of OC_HADAMARD_ABS_ACCUM_8x4 to hide the long
latency of pmaddwd by starting the next series of loads now.*/
- mov RET2,_thresh
pmaddwd mm0,mm7
movq mm1,[0x50+BUF]
movq mm5,[0x58+BUF]
@@ -525,29 +533,28 @@ static unsigned oc_int_frag_satd_thresh_mmxext(const unsigned char *_src,
movq mm6,[0x68+BUF]
paddd mm4,mm0
movq mm3,[0x70+BUF]
- movd RET,mm4
+ movd RET2,mm4
movq mm7,[0x78+BUF]
- /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
- added to them, and a factor of two removed; correct the final sum here.*/
- lea RET,[RET+RET-32]
movq mm0,[0x40+BUF]
- cmp RET,RET2
movq mm4,[0x48+BUF]
- jae at_end
OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
pmaddwd mm0,mm7
- /*There isn't much to stick in here to hide the latency this time, but the
- alternative to pmaddwd is movq->punpcklwd->punpckhwd->paddd, whose
- latency is even worse.*/
- sub RET,32
+ /*Subtract abs(dc) from 2*ret2.*/
+ movsx DC,DC_WORD
+ cdq
+ lea RET2,[RET+RET2*2]
movq mm4,mm0
punpckhdq mm0,mm0
+ xor RET,DC
paddd mm4,mm0
- movd RET2,mm4
- lea RET,[RET+RET2*2]
- align 16
-at_end:
- mov ret1,RET
+ /*The sums produced by OC_HADAMARD_ABS_ACCUM_8x4 each have an extra 4
+ added to them, a factor of two removed, and the DC value included;
+ correct the final sum here.*/
+ sub RET2,RET
+ movd RET,mm4
+ lea RET,[RET2+RET*2-64]
+ mov ret,RET
+ mov dc,DC
#undef SRC
#undef REF
#undef SRC_YSTRIDE
@@ -555,18 +562,21 @@ at_end:
#undef BUF
#undef RET
#undef RET2
+#undef DC
+#undef DC_WORD
}
- return ret1;
+ *_dc=dc;
+ return ret;
}
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh){
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,_ref,_ystride,_thresh);
+unsigned oc_enc_frag_satd_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride){
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,_ref,_ystride);
}
/*Our internal implementation of frag_copy2 takes an extra stride parameter so
- we can share code with oc_enc_frag_satd2_thresh_mmxext().*/
+ we can share code with oc_enc_frag_satd2_mmxext().*/
static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
const unsigned char *_src1,const unsigned char *_src2,int _src_ystride){
__asm{
@@ -694,30 +704,31 @@ static void oc_int_frag_copy2_mmxext(unsigned char *_dst,int _dst_ystride,
}
}
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh){
+unsigned oc_enc_frag_satd2_mmxext(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride){
OC_ALIGN8(unsigned char ref[64]);
oc_int_frag_copy2_mmxext(ref,8,_ref1,_ref2,_ystride);
- return oc_int_frag_satd_thresh_mmxext(_src,_ystride,ref,8,_thresh);
+ return oc_int_frag_satd_mmxext(_dc,_src,_ystride,ref,8);
}
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
+unsigned oc_enc_frag_intra_satd_mmxext(int *_dc,const unsigned char *_src,
int _ystride){
- OC_ALIGN8(ogg_int16_t buf[64]);
- ogg_int16_t *bufp;
- unsigned ret1;
- unsigned ret2;
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ unsigned ret1;
+ unsigned ret2;
+ int dc;
bufp=buf;
__asm{
#define SRC eax
#define SRC4 esi
#define BUF edi
-#define RET eax
-#define RET_WORD ax
-#define RET2 ecx
#define YSTRIDE edx
#define YSTRIDE3 ecx
+#define RET eax
+#define RET2 ecx
+#define DC edx
+#define DC_WORD dx
mov SRC,_src
mov BUF,bufp
mov YSTRIDE,_ystride
@@ -749,7 +760,7 @@ unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
middle.*/
OC_HADAMARD_AB_8x4
OC_HADAMARD_C_ABS_ACCUM_A_8x4(0x28,0x38)
- movd RET,mm1
+ movd DC,mm1
OC_HADAMARD_C_ABS_ACCUM_B_8x4(0x28,0x38)
/*Up to this point, everything fit in 16 bits (8 input + 1 for the
difference + 2*3 for the two 8-point 1-D Hadamards - 1 for the abs - 1
@@ -767,31 +778,34 @@ unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,
movq mm3,[0x70+BUF]
paddd mm4,mm0
movq mm7,[0x78+BUF]
- movd RET2,mm4
+ movd RET,mm4
movq mm0,[0x40+BUF]
movq mm4,[0x48+BUF]
OC_HADAMARD_ABS_ACCUM_8x4(0x68,0x78)
pmaddwd mm0,mm7
/*We assume that the DC coefficient is always positive (which is true,
because the input to the INTRA transform was not a difference).*/
- movzx RET,RET_WORD
- add RET2,RET2
- sub RET2,RET
+ movzx DC,DC_WORD
+ add RET,RET
+ sub RET,DC
movq mm4,mm0
punpckhdq mm0,mm0
paddd mm4,mm0
- movd RET,mm4
- lea RET,[-64+RET2+RET*2]
+ movd RET2,mm4
+ lea RET,[-64+RET+RET2*2]
+ mov [dc],DC
mov [ret1],RET
#undef SRC
#undef SRC4
#undef BUF
-#undef RET
-#undef RET_WORD
-#undef RET2
#undef YSTRIDE
#undef YSTRIDE3
+#undef RET
+#undef RET2
+#undef DC
+#undef DC_WORD
}
+ *_dc=dc;
return ret1;
}
diff --git a/thirdparty/libtheora/x86_vc/mmxfdct.c b/thirdparty/libtheora/x86_vc/mmxfdct.c
index d908ce2413..c9ee530ea2 100644
--- a/thirdparty/libtheora/x86_vc/mmxfdct.c
+++ b/thirdparty/libtheora/x86_vc/mmxfdct.c
@@ -12,6 +12,7 @@
/*MMX fDCT implementation for x86_32*/
/*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/
#include "x86enc.h"
+#include "x86zigzag.h"
#if defined(OC_X86_ASM)
@@ -462,18 +463,22 @@
}
/*MMX implementation of the fDCT.*/
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
- ptrdiff_t a;
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
+ OC_ALIGN8(ogg_int16_t buf[64]);
+ ogg_int16_t *bufp;
+ bufp=buf;
__asm{
+#define X edx
#define Y eax
#define A ecx
-#define X edx
+#define BUF esi
/*Add two extra bits of working precision to improve accuracy; any more and
we could overflow.*/
/*We also add biases to correct for some systematic error that remains in
the full fDCT->iDCT round trip.*/
mov X, _x
mov Y, _y
+ mov BUF, bufp
movq mm0,[0x00+X]
movq mm1,[0x10+X]
movq mm2,[0x20+X]
@@ -591,79 +596,90 @@ void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){
movq mm3,[0x30+Y]
OC_FDCT_STAGE1_8x4
OC_FDCT8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
- OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)
/*mm0={-2}x4*/
- pcmpeqw mm0,mm0
- paddw mm0,mm0
- /*Round the results.*/
- psubw mm1,mm0
- psubw mm2,mm0
- psraw mm1,2
- psubw mm3,mm0
- movq [0x18+Y],mm1
- psraw mm2,2
- psubw mm4,mm0
- movq mm1,[0x08+Y]
- psraw mm3,2
- psubw mm5,mm0
+ pcmpeqw mm2,mm2
+ paddw mm2,mm2
+ /*Round and store the results (no transpose).*/
+ movq mm7,[Y+0x10]
+ psubw mm4,mm2
+ psubw mm6,mm2
psraw mm4,2
- psubw mm6,mm0
- psraw mm5,2
- psubw mm7,mm0
+ psubw mm0,mm2
+ movq [BUF+0x00],mm4
+ movq mm4,[Y+0x30]
psraw mm6,2
- psubw mm1,mm0
+ psubw mm5,mm2
+ movq [BUF+0x20],mm6
+ psraw mm0,2
+ psubw mm3,mm2
+ movq [BUF+0x40],mm0
+ psraw mm5,2
+ psubw mm1,mm2
+ movq [BUF+0x50],mm5
+ psraw mm3,2
+ psubw mm7,mm2
+ movq [BUF+0x60],mm3
+ psraw mm1,2
+ psubw mm4,mm2
+ movq [BUF+0x70],mm1
psraw mm7,2
+ movq [BUF+0x10],mm7
+ psraw mm4,2
+ movq [BUF+0x30],mm4
+ /*Load the next block.*/
movq mm0,[0x40+Y]
- psraw mm1,2
- movq [0x30+Y],mm7
movq mm7,[0x78+Y]
- movq [0x08+Y],mm1
movq mm1,[0x50+Y]
- movq [0x20+Y],mm6
movq mm6,[0x68+Y]
- movq [0x28+Y],mm2
movq mm2,[0x60+Y]
- movq [0x10+Y],mm5
movq mm5,[0x58+Y]
- movq [0x38+Y],mm3
movq mm3,[0x70+Y]
- movq [0x00+Y],mm4
movq mm4,[0x48+Y]
OC_FDCT_STAGE1_8x4
OC_FDCT8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
- OC_TRANSPOSE8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)
/*mm0={-2}x4*/
- pcmpeqw mm0,mm0
- paddw mm0,mm0
- /*Round the results.*/
- psubw mm1,mm0
- psubw mm2,mm0
- psraw mm1,2
- psubw mm3,mm0
- movq [0x58+Y],mm1
- psraw mm2,2
- psubw mm4,mm0
- movq mm1,[0x48+Y]
- psraw mm3,2
- psubw mm5,mm0
- movq [0x68+Y],mm2
+ pcmpeqw mm2,mm2
+ paddw mm2,mm2
+ /*Round and store the results (no transpose).*/
+ movq mm7,[Y+0x50]
+ psubw mm4,mm2
+ psubw mm6,mm2
psraw mm4,2
- psubw mm6,mm0
- movq [0x78+Y],mm3
- psraw mm5,2
- psubw mm7,mm0
- movq [0x40+Y],mm4
+ psubw mm0,mm2
+ movq [BUF+0x08],mm4
+ movq mm4,[Y+0x70]
psraw mm6,2
- psubw mm1,mm0
- movq [0x50+Y],mm5
- psraw mm7,2
- movq [0x60+Y],mm6
+ psubw mm5,mm2
+ movq [BUF+0x28],mm6
+ psraw mm0,2
+ psubw mm3,mm2
+ movq [BUF+0x48],mm0
+ psraw mm5,2
+ psubw mm1,mm2
+ movq [BUF+0x58],mm5
+ psraw mm3,2
+ psubw mm7,mm2
+ movq [BUF+0x68],mm3
psraw mm1,2
- movq [0x70+Y],mm7
- movq [0x48+Y],mm1
+ psubw mm4,mm2
+ movq [BUF+0x78],mm1
+ psraw mm7,2
+ movq [BUF+0x18],mm7
+ psraw mm4,2
+ movq [BUF+0x38],mm4
+#define OC_ZZ_LOAD_ROW_LO(_row,_reg) \
+ __asm movq _reg,[BUF+16*(_row)] \
+
+#define OC_ZZ_LOAD_ROW_HI(_row,_reg) \
+ __asm movq _reg,[BUF+16*(_row)+8] \
+
+ OC_TRANSPOSE_ZIG_ZAG_MMXEXT
+#undef OC_ZZ_LOAD_ROW_LO
+#undef OC_ZZ_LOAD_ROW_HI
+#undef X
#undef Y
#undef A
-#undef X
+#undef BUF
}
}
diff --git a/thirdparty/libtheora/x86_vc/mmxfrag.c b/thirdparty/libtheora/x86_vc/mmxfrag.c
index 4eb2084dc6..248312ff90 100644
--- a/thirdparty/libtheora/x86_vc/mmxfrag.c
+++ b/thirdparty/libtheora/x86_vc/mmxfrag.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxfrag.c 16578 2009-09-25 19:50:48Z cristianadam $
+ last mod: $Id$
********************************************************************/
@@ -22,12 +22,63 @@
The iteration each instruction belongs to is marked in the comments as #i.*/
#include <stddef.h>
#include "x86int.h"
-#include "mmxfrag.h"
#if defined(OC_X86_ASM)
/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
between rows.*/
+# define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
+ do{ \
+ const unsigned char *src; \
+ unsigned char *dst; \
+ src=(_src); \
+ dst=(_dst); \
+ __asm mov SRC,src \
+ __asm mov DST,dst \
+ __asm mov YSTRIDE,_ystride \
+ /*src+0*ystride*/ \
+ __asm movq mm0,[SRC] \
+ /*src+1*ystride*/ \
+ __asm movq mm1,[SRC+YSTRIDE] \
+ /*ystride3=ystride*3*/ \
+ __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \
+ /*src+2*ystride*/ \
+ __asm movq mm2,[SRC+YSTRIDE*2] \
+ /*src+3*ystride*/ \
+ __asm movq mm3,[SRC+YSTRIDE3] \
+ /*dst+0*ystride*/ \
+ __asm movq [DST],mm0 \
+ /*dst+1*ystride*/ \
+ __asm movq [DST+YSTRIDE],mm1 \
+ /*Pointer to next 4.*/ \
+ __asm lea SRC,[SRC+YSTRIDE*4] \
+ /*dst+2*ystride*/ \
+ __asm movq [DST+YSTRIDE*2],mm2 \
+ /*dst+3*ystride*/ \
+ __asm movq [DST+YSTRIDE3],mm3 \
+ /*Pointer to next 4.*/ \
+ __asm lea DST,[DST+YSTRIDE*4] \
+ /*src+0*ystride*/ \
+ __asm movq mm0,[SRC] \
+ /*src+1*ystride*/ \
+ __asm movq mm1,[SRC+YSTRIDE] \
+ /*src+2*ystride*/ \
+ __asm movq mm2,[SRC+YSTRIDE*2] \
+ /*src+3*ystride*/ \
+ __asm movq mm3,[SRC+YSTRIDE3] \
+ /*dst+0*ystride*/ \
+ __asm movq [DST],mm0 \
+ /*dst+1*ystride*/ \
+ __asm movq [DST+YSTRIDE],mm1 \
+ /*dst+2*ystride*/ \
+ __asm movq [DST+YSTRIDE*2],mm2 \
+ /*dst+3*ystride*/ \
+ __asm movq [DST+YSTRIDE3],mm3 \
+ } \
+ while(0)
+
+/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
+ between rows.*/
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride){
#define SRC edx
@@ -41,6 +92,34 @@ void oc_frag_copy_mmx(unsigned char *_dst,
#undef YSTRIDE3
}
+/*Copies the fragments specified by the lists of fragment indices from one
+ frame to another.
+ _dst_frame: The reference frame to copy to.
+ _src_frame: The reference frame to copy from.
+ _ystride: The row stride of the reference frames.
+ _fragis: A pointer to a list of fragment indices.
+ _nfragis: The number of fragment indices to copy.
+ _frag_buf_offs: The offsets of fragments in the reference frames.*/
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs){
+ ptrdiff_t fragii;
+ for(fragii=0;fragii<_nfragis;fragii++){
+ ptrdiff_t frag_buf_off;
+ frag_buf_off=_frag_buf_offs[_fragis[fragii]];
+#define SRC edx
+#define DST eax
+#define YSTRIDE ecx
+#define YSTRIDE3 edi
+ OC_FRAG_COPY_MMX(_dst_frame+frag_buf_off,
+ _src_frame+frag_buf_off,_ystride);
+#undef SRC
+#undef DST
+#undef YSTRIDE
+#undef YSTRIDE3
+ }
+}
+
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue){
__asm{
diff --git a/thirdparty/libtheora/x86_vc/mmxfrag.h b/thirdparty/libtheora/x86_vc/mmxfrag.h
deleted file mode 100644
index 45ee93e777..0000000000
--- a/thirdparty/libtheora/x86_vc/mmxfrag.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#if !defined(_x86_vc_mmxfrag_H)
-# define _x86_vc_mmxfrag_H (1)
-# include <stddef.h>
-# include "x86int.h"
-
-#if defined(OC_X86_ASM)
-
-/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
- between rows.*/
-#define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
- do{ \
- const unsigned char *src; \
- unsigned char *dst; \
- src=(_src); \
- dst=(_dst); \
- __asm mov SRC,src \
- __asm mov DST,dst \
- __asm mov YSTRIDE,_ystride \
- /*src+0*ystride*/ \
- __asm movq mm0,[SRC] \
- /*src+1*ystride*/ \
- __asm movq mm1,[SRC+YSTRIDE] \
- /*ystride3=ystride*3*/ \
- __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \
- /*src+2*ystride*/ \
- __asm movq mm2,[SRC+YSTRIDE*2] \
- /*src+3*ystride*/ \
- __asm movq mm3,[SRC+YSTRIDE3] \
- /*dst+0*ystride*/ \
- __asm movq [DST],mm0 \
- /*dst+1*ystride*/ \
- __asm movq [DST+YSTRIDE],mm1 \
- /*Pointer to next 4.*/ \
- __asm lea SRC,[SRC+YSTRIDE*4] \
- /*dst+2*ystride*/ \
- __asm movq [DST+YSTRIDE*2],mm2 \
- /*dst+3*ystride*/ \
- __asm movq [DST+YSTRIDE3],mm3 \
- /*Pointer to next 4.*/ \
- __asm lea DST,[DST+YSTRIDE*4] \
- /*src+0*ystride*/ \
- __asm movq mm0,[SRC] \
- /*src+1*ystride*/ \
- __asm movq mm1,[SRC+YSTRIDE] \
- /*src+2*ystride*/ \
- __asm movq mm2,[SRC+YSTRIDE*2] \
- /*src+3*ystride*/ \
- __asm movq mm3,[SRC+YSTRIDE3] \
- /*dst+0*ystride*/ \
- __asm movq [DST],mm0 \
- /*dst+1*ystride*/ \
- __asm movq [DST+YSTRIDE],mm1 \
- /*dst+2*ystride*/ \
- __asm movq [DST+YSTRIDE*2],mm2 \
- /*dst+3*ystride*/ \
- __asm movq [DST+YSTRIDE3],mm3 \
- } \
- while(0)
-
-# endif
-#endif
diff --git a/thirdparty/libtheora/x86_vc/mmxidct.c b/thirdparty/libtheora/x86_vc/mmxidct.c
index 8f5ff6803c..55e00aedcf 100644
--- a/thirdparty/libtheora/x86_vc/mmxidct.c
+++ b/thirdparty/libtheora/x86_vc/mmxidct.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxidct.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -24,15 +24,15 @@
/*These are offsets into the table of constants below.*/
/*7 rows of cosines, in order: pi/16 * (1 ... 7).*/
-#define OC_COSINE_OFFSET (0)
+#define OC_COSINE_OFFSET (8)
/*A row of 8's.*/
-#define OC_EIGHT_OFFSET (56)
+#define OC_EIGHT_OFFSET (0)
/*A table of constants used by the MMX routines.*/
-static const __declspec(align(16))ogg_uint16_t
- OC_IDCT_CONSTS[(7+1)*4]={
+static const OC_ALIGN16(ogg_uint16_t) OC_IDCT_CONSTS[(1+7)*4]={
+ 8, 8, 8, 8,
(ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
(ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
(ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
@@ -46,28 +46,27 @@ static const __declspec(align(16))ogg_uint16_t
(ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
(ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
(ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
- 8, 8, 8, 8
+ (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1
};
/*38 cycles*/
-#define OC_IDCT_BEGIN __asm{ \
- __asm movq mm2,OC_I(3) \
+#define OC_IDCT_BEGIN(_y,_x) __asm{ \
+ __asm movq mm2,OC_I(3,_x) \
__asm movq mm6,OC_C(3) \
__asm movq mm4,mm2 \
- __asm movq mm7,OC_J(5) \
+ __asm movq mm7,OC_J(5,_x) \
__asm pmulhw mm4,mm6 \
__asm movq mm1,OC_C(5) \
__asm pmulhw mm6,mm7 \
__asm movq mm5,mm1 \
__asm pmulhw mm1,mm2 \
- __asm movq mm3,OC_I(1) \
+ __asm movq mm3,OC_I(1,_x) \
__asm pmulhw mm5,mm7 \
__asm movq mm0,OC_C(1) \
__asm paddw mm4,mm2 \
__asm paddw mm6,mm7 \
__asm paddw mm2,mm1 \
- __asm movq mm1,OC_J(7) \
+ __asm movq mm1,OC_J(7,_x) \
__asm paddw mm7,mm5 \
__asm movq mm5,mm0 \
__asm pmulhw mm0,mm3 \
@@ -77,13 +76,13 @@ static const __declspec(align(16))ogg_uint16_t
__asm psubw mm6,mm2 \
__asm paddw mm0,mm3 \
__asm pmulhw mm3,mm7 \
- __asm movq mm2,OC_I(2) \
+ __asm movq mm2,OC_I(2,_x) \
__asm pmulhw mm7,mm1 \
__asm paddw mm5,mm1 \
__asm movq mm1,mm2 \
__asm pmulhw mm2,OC_C(2) \
__asm psubw mm3,mm5 \
- __asm movq mm5,OC_J(6) \
+ __asm movq mm5,OC_J(6,_x) \
__asm paddw mm0,mm7 \
__asm movq mm7,mm5 \
__asm psubw mm0,mm4 \
@@ -97,18 +96,18 @@ static const __declspec(align(16))ogg_uint16_t
__asm paddw mm6,mm6 \
__asm pmulhw mm7,OC_C(6) \
__asm paddw mm6,mm3 \
- __asm movq OC_I(1),mm4 \
+ __asm movq OC_I(1,_y),mm4 \
__asm psubw mm1,mm5 \
__asm movq mm4,OC_C(4) \
__asm movq mm5,mm3 \
__asm pmulhw mm3,mm4 \
__asm paddw mm7,mm2 \
- __asm movq OC_I(2),mm6 \
+ __asm movq OC_I(2,_y),mm6 \
__asm movq mm2,mm0 \
- __asm movq mm6,OC_I(0) \
+ __asm movq mm6,OC_I(0,_x) \
__asm pmulhw mm0,mm4 \
__asm paddw mm5,mm3 \
- __asm movq mm3,OC_J(4) \
+ __asm movq mm3,OC_J(4,_x) \
__asm psubw mm5,mm1 \
__asm paddw mm2,mm0 \
__asm psubw mm6,mm3 \
@@ -122,17 +121,17 @@ static const __declspec(align(16))ogg_uint16_t
__asm paddw mm6,mm0 \
__asm psubw mm6,mm2 \
__asm paddw mm2,mm2 \
- __asm movq mm0,OC_I(1) \
+ __asm movq mm0,OC_I(1,_y) \
__asm paddw mm2,mm6 \
__asm paddw mm4,mm3 \
__asm psubw mm2,mm1 \
}
/*38+8=46 cycles.*/
-#define OC_ROW_IDCT __asm{ \
- OC_IDCT_BEGIN \
+#define OC_ROW_IDCT(_y,_x) __asm{ \
+ OC_IDCT_BEGIN(_y,_x) \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r4=E'=E-G*/ \
__asm psubw mm4,mm7 \
/*r1=H'+H'*/ \
@@ -157,7 +156,7 @@ static const __declspec(align(16))ogg_uint16_t
__asm psubw mm7,mm0 \
__asm paddw mm0,mm0 \
/*Save R1.*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r0=R0=G.+C.*/ \
__asm paddw mm0,mm7 \
}
@@ -190,10 +189,10 @@ static const __declspec(align(16))ogg_uint16_t
Since r1 is free at entry, we calculate the Js first.*/
/*19 cycles.*/
-#define OC_TRANSPOSE __asm{ \
+#define OC_TRANSPOSE(_y) __asm{ \
__asm movq mm1,mm4 \
__asm punpcklwd mm4,mm5 \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
__asm punpckhwd mm1,mm5 \
__asm movq mm0,mm6 \
__asm punpcklwd mm6,mm7 \
@@ -201,17 +200,17 @@ static const __declspec(align(16))ogg_uint16_t
__asm punpckldq mm4,mm6 \
__asm punpckhdq mm5,mm6 \
__asm movq mm6,mm1 \
- __asm movq OC_J(4),mm4 \
+ __asm movq OC_J(4,_y),mm4 \
__asm punpckhwd mm0,mm7 \
- __asm movq OC_J(5),mm5 \
+ __asm movq OC_J(5,_y),mm5 \
__asm punpckhdq mm6,mm0 \
- __asm movq mm4,OC_I(0) \
+ __asm movq mm4,OC_I(0,_y) \
__asm punpckldq mm1,mm0 \
- __asm movq mm5,OC_I(1) \
+ __asm movq mm5,OC_I(1,_y) \
__asm movq mm0,mm4 \
- __asm movq OC_J(7),mm6 \
+ __asm movq OC_J(7,_y),mm6 \
__asm punpcklwd mm0,mm5 \
- __asm movq OC_J(6),mm1 \
+ __asm movq OC_J(6,_y),mm1 \
__asm punpckhwd mm4,mm5 \
__asm movq mm5,mm2 \
__asm punpcklwd mm2,mm3 \
@@ -219,18 +218,18 @@ static const __declspec(align(16))ogg_uint16_t
__asm punpckldq mm0,mm2 \
__asm punpckhdq mm1,mm2 \
__asm movq mm2,mm4 \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
__asm punpckhwd mm5,mm3 \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
__asm punpckhdq mm4,mm5 \
__asm punpckldq mm2,mm5 \
- __asm movq OC_I(3),mm4 \
- __asm movq OC_I(2),mm2 \
+ __asm movq OC_I(3,_y),mm4 \
+ __asm movq OC_I(2,_y),mm2 \
}
/*38+19=57 cycles.*/
-#define OC_COLUMN_IDCT __asm{ \
- OC_IDCT_BEGIN \
+#define OC_COLUMN_IDCT(_y) __asm{ \
+ OC_IDCT_BEGIN(_y,_y) \
__asm paddw mm2,OC_8 \
/*r1=H'+H'*/ \
__asm paddw mm1,mm1 \
@@ -243,15 +242,15 @@ static const __declspec(align(16))ogg_uint16_t
/*r1=NR1*/ \
__asm psraw mm1,4 \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r7=G+G*/ \
__asm paddw mm7,mm7 \
/*Store NR2 at I(2).*/ \
- __asm movq OC_I(2),mm2 \
+ __asm movq OC_I(2,_y),mm2 \
/*r7=G'=E+G*/ \
__asm paddw mm7,mm4 \
/*Store NR1 at I(1).*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r4=R4=E'-D'*/ \
__asm psubw mm4,mm3 \
__asm paddw mm4,OC_8 \
@@ -273,11 +272,11 @@ static const __declspec(align(16))ogg_uint16_t
/*r6=NR6*/ \
__asm psraw mm6,4 \
/*Store NR4 at J(4).*/ \
- __asm movq OC_J(4),mm4 \
+ __asm movq OC_J(4,_y),mm4 \
/*r5=NR5*/ \
__asm psraw mm5,4 \
/*Store NR3 at I(3).*/ \
- __asm movq OC_I(3),mm3 \
+ __asm movq OC_I(3,_y),mm3 \
/*r7=R7=G'-C'*/ \
__asm psubw mm7,mm0 \
__asm paddw mm7,OC_8 \
@@ -288,71 +287,89 @@ static const __declspec(align(16))ogg_uint16_t
/*r7=NR7*/ \
__asm psraw mm7,4 \
/*Store NR6 at J(6).*/ \
- __asm movq OC_J(6),mm6 \
+ __asm movq OC_J(6,_y),mm6 \
/*r0=NR0*/ \
__asm psraw mm0,4 \
/*Store NR5 at J(5).*/ \
- __asm movq OC_J(5),mm5 \
+ __asm movq OC_J(5,_y),mm5 \
/*Store NR7 at J(7).*/ \
- __asm movq OC_J(7),mm7 \
+ __asm movq OC_J(7,_y),mm7 \
/*Store NR0 at I(0).*/ \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
}
#define OC_MID(_m,_i) [CONSTS+_m+(_i)*8]
#define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1)
#define OC_8 OC_MID(OC_EIGHT_OFFSET,0)
-static void oc_idct8x8_slow(ogg_int16_t _y[64]){
+static void oc_idct8x8_slow(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ int i;
/*This routine accepts an 8x8 matrix, but in partially transposed form.
Every 4x4 block is transposed.*/
__asm{
#define CONSTS eax
#define Y edx
+#define X ecx
mov CONSTS,offset OC_IDCT_CONSTS
mov Y,_y
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) [Y+(_k-4)*16+8]
- OC_ROW_IDCT
- OC_TRANSPOSE
+ mov X,_x
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
+ OC_ROW_IDCT(Y,X)
+ OC_TRANSPOSE(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+(_k*16)+64]
-#define OC_J(_k) [Y+(_k-4)*16+72]
- OC_ROW_IDCT
- OC_TRANSPOSE
+#define OC_I(_k,_y) [(_y)+(_k)*16+64]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+72]
+ OC_ROW_IDCT(Y,X)
+ OC_TRANSPOSE(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16+8]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT
+#define OC_I(_k,_y) [(_y)+(_k)*16+8]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(Y)
#undef OC_I
#undef OC_J
#undef CONSTS
#undef Y
+#undef X
+ }
+ __asm pxor mm0,mm0;
+ for(i=0;i<4;i++){
+ ogg_int16_t *x;
+ x=_x+16*i;
+#define X ecx
+ __asm{
+ mov X,x
+ movq [X+0x00],mm0
+ movq [X+0x08],mm0
+ movq [X+0x10],mm0
+ movq [X+0x18],mm0
+ }
+#undef X
}
}
/*25 cycles.*/
-#define OC_IDCT_BEGIN_10 __asm{ \
- __asm movq mm2,OC_I(3) \
+#define OC_IDCT_BEGIN_10(_y,_x) __asm{ \
+ __asm movq mm2,OC_I(3,_x) \
__asm nop \
__asm movq mm6,OC_C(3) \
__asm movq mm4,mm2 \
__asm movq mm1,OC_C(5) \
__asm pmulhw mm4,mm6 \
- __asm movq mm3,OC_I(1) \
+ __asm movq mm3,OC_I(1,_x) \
__asm pmulhw mm1,mm2 \
__asm movq mm0,OC_C(1) \
__asm paddw mm4,mm2 \
__asm pxor mm6,mm6 \
__asm paddw mm2,mm1 \
- __asm movq mm5,OC_I(2) \
+ __asm movq mm5,OC_I(2,_x) \
__asm pmulhw mm0,mm3 \
__asm movq mm1,mm5 \
__asm paddw mm0,mm3 \
@@ -360,43 +377,43 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
__asm psubw mm6,mm2 \
__asm pmulhw mm5,OC_C(2) \
__asm psubw mm0,mm4 \
- __asm movq mm7,OC_I(2) \
+ __asm movq mm7,OC_I(2,_x) \
__asm paddw mm4,mm4 \
__asm paddw mm7,mm5 \
__asm paddw mm4,mm0 \
__asm pmulhw mm1,OC_C(6) \
__asm psubw mm3,mm6 \
- __asm movq OC_I(1),mm4 \
+ __asm movq OC_I(1,_y),mm4 \
__asm paddw mm6,mm6 \
__asm movq mm4,OC_C(4) \
__asm paddw mm6,mm3 \
__asm movq mm5,mm3 \
__asm pmulhw mm3,mm4 \
- __asm movq OC_I(2),mm6 \
+ __asm movq OC_I(2,_y),mm6 \
__asm movq mm2,mm0 \
- __asm movq mm6,OC_I(0) \
+ __asm movq mm6,OC_I(0,_x) \
__asm pmulhw mm0,mm4 \
__asm paddw mm5,mm3 \
__asm paddw mm2,mm0 \
__asm psubw mm5,mm1 \
__asm pmulhw mm6,mm4 \
- __asm paddw mm6,OC_I(0) \
+ __asm paddw mm6,OC_I(0,_x) \
__asm paddw mm1,mm1 \
__asm movq mm4,mm6 \
__asm paddw mm1,mm5 \
__asm psubw mm6,mm2 \
__asm paddw mm2,mm2 \
- __asm movq mm0,OC_I(1) \
+ __asm movq mm0,OC_I(1,_y) \
__asm paddw mm2,mm6 \
__asm psubw mm2,mm1 \
__asm nop \
}
/*25+8=33 cycles.*/
-#define OC_ROW_IDCT_10 __asm{ \
- OC_IDCT_BEGIN_10 \
+#define OC_ROW_IDCT_10(_y,_x) __asm{ \
+ OC_IDCT_BEGIN_10(_y,_x) \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r4=E'=E-G*/ \
__asm psubw mm4,mm7 \
/*r1=H'+H'*/ \
@@ -421,14 +438,14 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
__asm psubw mm7,mm0 \
__asm paddw mm0,mm0 \
/*Save R1.*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r0=R0=G'+C'*/ \
__asm paddw mm0,mm7 \
}
/*25+19=44 cycles'*/
-#define OC_COLUMN_IDCT_10 __asm{ \
- OC_IDCT_BEGIN_10 \
+#define OC_COLUMN_IDCT_10(_y) __asm{ \
+ OC_IDCT_BEGIN_10(_y,_y) \
__asm paddw mm2,OC_8 \
/*r1=H'+H'*/ \
__asm paddw mm1,mm1 \
@@ -441,15 +458,15 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r1=NR1*/ \
__asm psraw mm1,4 \
/*r3=D'*/ \
- __asm movq mm3,OC_I(2) \
+ __asm movq mm3,OC_I(2,_y) \
/*r7=G+G*/ \
__asm paddw mm7,mm7 \
/*Store NR2 at I(2).*/ \
- __asm movq OC_I(2),mm2 \
+ __asm movq OC_I(2,_y),mm2 \
/*r7=G'=E+G*/ \
__asm paddw mm7,mm4 \
/*Store NR1 at I(1).*/ \
- __asm movq OC_I(1),mm1 \
+ __asm movq OC_I(1,_y),mm1 \
/*r4=R4=E'-D'*/ \
__asm psubw mm4,mm3 \
__asm paddw mm4,OC_8 \
@@ -471,11 +488,11 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r6=NR6*/ \
__asm psraw mm6,4 \
/*Store NR4 at J(4).*/ \
- __asm movq OC_J(4),mm4 \
+ __asm movq OC_J(4,_y),mm4 \
/*r5=NR5*/ \
__asm psraw mm5,4 \
/*Store NR3 at I(3).*/ \
- __asm movq OC_I(3),mm3 \
+ __asm movq OC_I(3,_y),mm3 \
/*r7=R7=G'-C'*/ \
__asm psubw mm7,mm0 \
__asm paddw mm7,OC_8 \
@@ -486,50 +503,63 @@ static void oc_idct8x8_slow(ogg_int16_t _y[64]){
/*r7=NR7*/ \
__asm psraw mm7,4 \
/*Store NR6 at J(6).*/ \
- __asm movq OC_J(6),mm6 \
+ __asm movq OC_J(6,_y),mm6 \
/*r0=NR0*/ \
__asm psraw mm0,4 \
/*Store NR5 at J(5).*/ \
- __asm movq OC_J(5),mm5 \
+ __asm movq OC_J(5,_y),mm5 \
/*Store NR7 at J(7).*/ \
- __asm movq OC_J(7),mm7 \
+ __asm movq OC_J(7,_y),mm7 \
/*Store NR0 at I(0).*/ \
- __asm movq OC_I(0),mm0 \
+ __asm movq OC_I(0,_y),mm0 \
}
-static void oc_idct8x8_10(ogg_int16_t _y[64]){
+static void oc_idct8x8_10(ogg_int16_t _y[64],ogg_int16_t _x[64]){
__asm{
#define CONSTS eax
#define Y edx
+#define X ecx
mov CONSTS,offset OC_IDCT_CONSTS
mov Y,_y
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) [Y+(_k-4)*16+8]
+ mov X,_x
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
/*Done with dequant, descramble, and partial transpose.
Now do the iDCT itself.*/
- OC_ROW_IDCT_10
- OC_TRANSPOSE
+ OC_ROW_IDCT_10(Y,X)
+ OC_TRANSPOSE(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(Y)
#undef OC_I
#undef OC_J
-#define OC_I(_k) [Y+_k*16+8]
-#define OC_J(_k) OC_I(_k)
- OC_COLUMN_IDCT_10
+#define OC_I(_k,_y) [(_y)+(_k)*16+8]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(Y)
#undef OC_I
#undef OC_J
#undef CONSTS
#undef Y
+#undef X
+ }
+#define X ecx
+ __asm{
+ pxor mm0,mm0;
+ mov X,_x
+ movq [X+0x00],mm0
+ movq [X+0x10],mm0
+ movq [X+0x20],mm0
+ movq [X+0x30],mm0
}
+#undef X
}
/*Performs an inverse 8x8 Type-II DCT transform.
The input is assumed to be scaled by a factor of 4 relative to orthonormal
version of the transform.*/
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
/*_last_zzi is subtly different from an actual count of the number of
coefficients we decoded for this block.
It contains the value of zzi BEFORE the final token in the block was
@@ -555,8 +585,8 @@ void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi){
gets.
Needless to say we inherited this approach from VP3.*/
/*Perform the iDCT.*/
- if(_last_zzi<10)oc_idct8x8_10(_y);
- else oc_idct8x8_slow(_y);
+ if(_last_zzi<=10)oc_idct8x8_10(_y,_x);
+ else oc_idct8x8_slow(_y,_x);
}
#endif
diff --git a/thirdparty/libtheora/x86_vc/mmxstate.c b/thirdparty/libtheora/x86_vc/mmxstate.c
index 73bd1981cf..f532ee1b6f 100644
--- a/thirdparty/libtheora/x86_vc/mmxstate.c
+++ b/thirdparty/libtheora/x86_vc/mmxstate.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: mmxstate.c 16584 2009-09-26 19:35:55Z tterribe $
+ last mod: $Id$
********************************************************************/
@@ -19,17 +19,16 @@
Originally written by Rudolf Marek.*/
#include <string.h>
#include "x86int.h"
-#include "mmxfrag.h"
#include "mmxloop.h"
#if defined(OC_X86_ASM)
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){
unsigned char *dst;
ptrdiff_t frag_buf_off;
int ystride;
- int mb_mode;
+ int refi;
/*Apply the inverse transform.*/
/*Special case only having a DC component.*/
if(_last_zzi<2){
@@ -45,6 +44,7 @@ void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
#define P ecx
mov Y,_dct_coeffs
movzx P,p
+ lea Y,[Y+128]
/*mm0=0000 0000 0000 AAAA*/
movd mm0,P
/*mm0=0000 0000 AAAA AAAA*/
@@ -74,65 +74,32 @@ void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
else{
/*Dequantize the DC coefficient.*/
_dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
- oc_idct8x8_mmx(_dct_coeffs,_last_zzi);
+ oc_idct8x8_mmx(_dct_coeffs+64,_dct_coeffs,_last_zzi);
}
/*Fill in the target buffer.*/
frag_buf_off=_state->frag_buf_offs[_fragi];
- mb_mode=_state->frags[_fragi].mb_mode;
+ refi=_state->frags[_fragi].refi;
ystride=_state->ref_ystride[_pli];
- dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off;
- if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs);
+ dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off;
+ if(refi==OC_FRAME_SELF)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs+64);
else{
const unsigned char *ref;
int mvoffsets[2];
- ref=
- _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]
- +frag_buf_off;
+ ref=_state->ref_frame_data[refi]+frag_buf_off;
if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
- _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){
+ _state->frag_mvs[_fragi])>1){
oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,
- _dct_coeffs);
+ _dct_coeffs+64);
}
- else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs);
+ else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs+64);
}
}
/*We copy these entire function to inline the actual MMX routines so that we
use only a single indirect call.*/
-/*Copies the fragments specified by the lists of fragment indices from one
- frame to another.
- _fragis: A pointer to a list of fragment indices.
- _nfragis: The number of fragment indices to copy.
- _dst_frame: The reference frame to copy to.
- _src_frame: The reference frame to copy from.
- _pli: The color plane the fragments lie in.*/
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli){
- const ptrdiff_t *frag_buf_offs;
- const unsigned char *src_frame_data;
- unsigned char *dst_frame_data;
- ptrdiff_t fragii;
- int ystride;
- dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
- src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
- ystride=_state->ref_ystride[_pli];
- frag_buf_offs=_state->frag_buf_offs;
- for(fragii=0;fragii<_nfragis;fragii++){
- ptrdiff_t frag_buf_off;
- frag_buf_off=frag_buf_offs[_fragis[fragii]];
-#define SRC edx
-#define DST eax
-#define YSTRIDE ecx
-#define YSTRIDE3 edi
- OC_FRAG_COPY_MMX(dst_frame_data+frag_buf_off,
- src_frame_data+frag_buf_off,ystride);
-#undef SRC
-#undef DST
-#undef YSTRIDE
-#undef YSTRIDE3
- }
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit){
+ memset(_bv,~(_flimit<<1),8);
}
/*Apply the loop filter to a given set of fragment rows in the given plane.
@@ -144,8 +111,7 @@ void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
_fragy0: The Y coordinate of the first fragment row to filter.
_fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
- OC_ALIGN8(unsigned char ll[8]);
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
const oc_fragment_plane *fplane;
const oc_fragment *frags;
const ptrdiff_t *frag_buf_offs;
@@ -156,13 +122,12 @@ void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
ptrdiff_t fragi0_end;
int ystride;
int nhfrags;
- memset(ll,_state->loop_filter_limits[_state->qis[0]],sizeof(ll));
fplane=_state->fplanes+_pli;
nhfrags=fplane->nhfrags;
fragi_top=fplane->froffset;
fragi_bot=fragi_top+fplane->nfrags;
fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
- fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags;
+ fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags;
ystride=_state->ref_ystride[_pli];
frags=_state->frags;
frag_buf_offs=_state->frag_buf_offs;
@@ -187,13 +152,13 @@ void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
#define LL edx
#define D esi
#define D_WORD si
- if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,ll);
- if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,ll);
+ if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,_bv);
+ if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,_bv);
if(fragi+1<fragi_end&&!frags[fragi+1].coded){
- OC_LOOP_FILTER_H_MMX(ref+8,ystride,ll);
+ OC_LOOP_FILTER_H_MMX(ref+8,ystride,_bv);
}
if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
- OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,ll);
+ OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,_bv);
}
#undef PIX
#undef YSTRIDE3
diff --git a/thirdparty/libtheora/cpu.c b/thirdparty/libtheora/x86_vc/x86cpu.c
index a863aad7f3..6a1d8d850c 100644
--- a/thirdparty/libtheora/cpu.c
+++ b/thirdparty/libtheora/x86_vc/x86cpu.c
@@ -14,41 +14,17 @@
Originally written by Rudolf Marek.
function:
- last mod: $Id: cpu.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
-#include "cpu.h"
+#include "x86cpu.h"
#if !defined(OC_X86_ASM)
-static ogg_uint32_t oc_cpu_flags_get(void){
+ogg_uint32_t oc_cpu_flags_get(void){
return 0;
}
#else
-# if !defined(_MSC_VER)
-# if defined(__amd64__)||defined(__x86_64__)
-/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
- compiling with -fPIC.*/
-# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
- __asm__ __volatile__( \
- "cpuid\n\t" \
- :[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
- :"a"(_op) \
- :"cc" \
- )
-# else
-/*On x86-32, not so much.*/
-# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
- __asm__ __volatile__( \
- "xchgl %%ebx,%[ebx]\n\t" \
- "cpuid\n\t" \
- "xchgl %%ebx,%[ebx]\n\t" \
- :[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
- :"a"(_op) \
- :"cc" \
- )
-# endif
-# else
/*Why does MSVC need this complicated rigamarole?
At this point I honestly do not care.*/
@@ -95,7 +71,6 @@ static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){
mov [ecx],ebx
}
}
-# endif
static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
@@ -124,7 +99,7 @@ static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
return flags;
}
-static ogg_uint32_t oc_cpu_flags_get(void){
+ogg_uint32_t oc_cpu_flags_get(void){
ogg_uint32_t flags;
ogg_uint32_t eax;
ogg_uint32_t ebx;
@@ -132,25 +107,7 @@ static ogg_uint32_t oc_cpu_flags_get(void){
ogg_uint32_t edx;
# if !defined(__amd64__)&&!defined(__x86_64__)
/*Not all x86-32 chips support cpuid, so we have to check.*/
-# if !defined(_MSC_VER)
- __asm__ __volatile__(
- "pushfl\n\t"
- "pushfl\n\t"
- "popl %[a]\n\t"
- "movl %[a],%[b]\n\t"
- "xorl $0x200000,%[a]\n\t"
- "pushl %[a]\n\t"
- "popfl\n\t"
- "pushfl\n\t"
- "popl %[a]\n\t"
- "popfl\n\t"
- :[a]"=r"(eax),[b]"=r"(ebx)
- :
- :"cc"
- );
-# else
oc_detect_cpuid_helper(&eax,&ebx);
-# endif
/*No cpuid.*/
if(eax==ebx)return 0;
# endif
@@ -159,9 +116,18 @@ static ogg_uint32_t oc_cpu_flags_get(void){
if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
/* 6 8 x M T e n i u n e G*/
ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
+ int family;
+ int model;
/*Intel, Transmeta (tested with Crusoe TM5800):*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
+ family=(eax>>8)&0xF;
+ model=(eax>>4)&0xF;
+ /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
+ unit, so don't use it.*/
+ if(family==6&&(model==9||model==13||model==14)){
+ flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
+ }
}
/* D M A c i t n e h t u A*/
else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
diff --git a/thirdparty/libtheora/x86_vc/x86cpu.h b/thirdparty/libtheora/x86_vc/x86cpu.h
new file mode 100644
index 0000000000..eea261d448
--- /dev/null
+++ b/thirdparty/libtheora/x86_vc/x86cpu.h
@@ -0,0 +1,36 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+ function:
+ last mod: $Id$
+
+ ********************************************************************/
+
+#if !defined(_x86_vc_x86cpu_H)
+# define _x86_vc_x86cpu_H (1)
+#include "../internal.h"
+
+#define OC_CPU_X86_MMX (1<<0)
+#define OC_CPU_X86_3DNOW (1<<1)
+#define OC_CPU_X86_3DNOWEXT (1<<2)
+#define OC_CPU_X86_MMXEXT (1<<3)
+#define OC_CPU_X86_SSE (1<<4)
+#define OC_CPU_X86_SSE2 (1<<5)
+#define OC_CPU_X86_PNI (1<<6)
+#define OC_CPU_X86_SSSE3 (1<<7)
+#define OC_CPU_X86_SSE4_1 (1<<8)
+#define OC_CPU_X86_SSE4_2 (1<<9)
+#define OC_CPU_X86_SSE4A (1<<10)
+#define OC_CPU_X86_SSE5 (1<<11)
+
+ogg_uint32_t oc_cpu_flags_get(void);
+
+#endif
diff --git a/thirdparty/libtheora/x86_vc/x86enc.c b/thirdparty/libtheora/x86_vc/x86enc.c
index e1960e1f0b..e9d59e85e3 100644
--- a/thirdparty/libtheora/x86_vc/x86enc.c
+++ b/thirdparty/libtheora/x86_vc/x86enc.c
@@ -18,27 +18,25 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc){
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc){
ogg_uint32_t cpu_flags;
- cpu_flags=oc_cpu_flags_get();
- oc_enc_vtable_init_c(_enc);
+ cpu_flags=_enc->state.cpu_flags;
+ oc_enc_accel_init_c(_enc);
if(cpu_flags&OC_CPU_X86_MMX){
_enc->opt_vtable.frag_sub=oc_enc_frag_sub_mmx;
_enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_mmx;
_enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
- _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmx;
}
if(cpu_flags&OC_CPU_X86_MMXEXT){
_enc->opt_vtable.frag_sad=oc_enc_frag_sad_mmxext;
_enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_mmxext;
_enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_mmxext;
- _enc->opt_vtable.frag_satd_thresh=oc_enc_frag_satd_thresh_mmxext;
- _enc->opt_vtable.frag_satd2_thresh=oc_enc_frag_satd2_thresh_mmxext;
+ _enc->opt_vtable.frag_satd=oc_enc_frag_satd_mmxext;
+ _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_mmxext;
_enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_mmxext;
_enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_mmxext;
+ _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_mmxext;
}
if(cpu_flags&OC_CPU_X86_SSE2){
# if defined(OC_X86_64_ASM)
diff --git a/thirdparty/libtheora/x86_vc/x86enc.h b/thirdparty/libtheora/x86_vc/x86enc.h
index 581484641f..885406a54d 100644
--- a/thirdparty/libtheora/x86_vc/x86enc.h
+++ b/thirdparty/libtheora/x86_vc/x86enc.h
@@ -17,10 +17,14 @@
#if !defined(_x86_vc_x86enc_H)
# define _x86_vc_x86enc_H (1)
-# include "../encint.h"
# include "x86int.h"
+# if defined(OC_X86_ASM)
+# define oc_enc_accel_init oc_enc_accel_init_x86
+# define OC_ENC_USE_VTABLE (1)
+# endif
+# include "../encint.h"
-void oc_enc_vtable_init_x86(oc_enc_ctx *_enc);
+void oc_enc_accel_init_x86(oc_enc_ctx *_enc);
unsigned oc_enc_frag_sad_mmxext(const unsigned char *_src,
const unsigned char *_ref,int _ystride);
@@ -29,19 +33,19 @@ unsigned oc_enc_frag_sad_thresh_mmxext(const unsigned char *_src,
unsigned oc_enc_frag_sad2_thresh_mmxext(const unsigned char *_src,
const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
unsigned _thresh);
-unsigned oc_enc_frag_satd_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref,int _ystride,unsigned _thresh);
-unsigned oc_enc_frag_satd2_thresh_mmxext(const unsigned char *_src,
- const unsigned char *_ref1,const unsigned char *_ref2,int _ystride,
- unsigned _thresh);
-unsigned oc_enc_frag_intra_satd_mmxext(const unsigned char *_src,int _ystride);
+unsigned oc_enc_frag_satd_mmxext(unsigned *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd2_mmxext(unsigned *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_intra_satd_mmxext(unsigned *_dc,
+ const unsigned char *_src,int _ystride);
void oc_enc_frag_sub_mmx(ogg_int16_t _diff[64],
const unsigned char *_x,const unsigned char *_y,int _stride);
void oc_enc_frag_sub_128_mmx(ogg_int16_t _diff[64],
const unsigned char *_x,int _stride);
void oc_enc_frag_copy2_mmxext(unsigned char *_dst,
const unsigned char *_src1,const unsigned char *_src2,int _ystride);
-void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
+void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
void oc_enc_fdct8x8_x86_64sse2(ogg_int16_t _y[64],const ogg_int16_t _x[64]);
#endif
diff --git a/thirdparty/libtheora/x86_vc/x86int.h b/thirdparty/libtheora/x86_vc/x86int.h
index 4cca485311..318a09dca0 100644
--- a/thirdparty/libtheora/x86_vc/x86int.h
+++ b/thirdparty/libtheora/x86_vc/x86int.h
@@ -11,32 +11,39 @@
********************************************************************
function:
- last mod: $Id: x86int.h 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
#if !defined(_x86_vc_x86int_H)
# define _x86_vc_x86int_H (1)
# include "../internal.h"
+# if defined(OC_X86_ASM)
+# define oc_state_accel_init oc_state_accel_init_x86
+# define OC_STATE_USE_VTABLE (1)
+# endif
+# include "../state.h"
+# include "x86cpu.h"
-void oc_state_vtable_init_x86(oc_theora_state *_state);
+void oc_state_accel_init_x86(oc_theora_state *_state);
void oc_frag_copy_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride);
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
const ogg_int16_t *_residue);
void oc_frag_recon_inter_mmx(unsigned char *_dst,
const unsigned char *_src,int _ystride,const ogg_int16_t *_residue);
void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue);
-void oc_idct8x8_mmx(ogg_int16_t _y[64],int _last_zzi);
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
- int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant);
-void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
- const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
- int _dst_frame,int _src_frame,int _pli);
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit);
void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
- int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
void oc_restore_fpu_mmx(void);
#endif
diff --git a/thirdparty/libtheora/x86_vc/x86state.c b/thirdparty/libtheora/x86_vc/x86state.c
index a786bec284..fa3a0d42fc 100644
--- a/thirdparty/libtheora/x86_vc/x86state.c
+++ b/thirdparty/libtheora/x86_vc/x86state.c
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: x86state.c 16503 2009-08-22 18:14:02Z giles $
+ last mod: $Id$
********************************************************************/
@@ -19,8 +19,6 @@
#if defined(OC_X86_ASM)
-#include "../cpu.c"
-
/*This table has been modified from OC_FZIG_ZAG by baking a 4x4 transpose into
each quadrant of the destination.*/
static const unsigned char OC_FZIG_ZAG_MMX[128]={
@@ -42,21 +40,22 @@ static const unsigned char OC_FZIG_ZAG_MMX[128]={
64,64,64,64,64,64,64,64,
};
-void oc_state_vtable_init_x86(oc_theora_state *_state){
+void oc_state_accel_init_x86(oc_theora_state *_state){
_state->cpu_flags=oc_cpu_flags_get();
if(_state->cpu_flags&OC_CPU_X86_MMX){
_state->opt_vtable.frag_copy=oc_frag_copy_mmx;
+ _state->opt_vtable.frag_copy_list=oc_frag_copy_list_mmx;
_state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
_state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
_state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_mmx;
_state->opt_vtable.idct8x8=oc_idct8x8_mmx;
_state->opt_vtable.state_frag_recon=oc_state_frag_recon_mmx;
- _state->opt_vtable.state_frag_copy_list=oc_state_frag_copy_list_mmx;
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_mmx;
_state->opt_vtable.state_loop_filter_frag_rows=
oc_state_loop_filter_frag_rows_mmx;
_state->opt_vtable.restore_fpu=oc_restore_fpu_mmx;
_state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_MMX;
}
- else oc_state_vtable_init_c(_state);
+ else oc_state_accel_init_c(_state);
}
#endif
diff --git a/thirdparty/libtheora/x86_vc/x86zigzag.h b/thirdparty/libtheora/x86_vc/x86zigzag.h
new file mode 100644
index 0000000000..26f5ed2ea5
--- /dev/null
+++ b/thirdparty/libtheora/x86_vc/x86zigzag.h
@@ -0,0 +1,244 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: sse2trans.h 15675 2009-02-06 09:43:27Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_vc_x86zigzag_H)
+# define _x86_vc_x86zigzag_H (1)
+# include "x86enc.h"
+
+
+/*Converts DCT coefficients from transposed order into zig-zag scan order and
+ stores them in Y.
+ This relies on two macros to load the contents of each row:
+ OC_ZZ_LOAD_ROW_LO(row,reg) and OC_ZZ_LOAD_ROW_HI(row,reg), which load the
+ first four and second four entries of each row into the specified register,
+ respectively.
+ OC_ZZ_LOAD_ROW_LO must be called before OC_ZZ_LOAD_ROW_HI for the same row
+ (because when the rows are already in SSE2 registers, loading the high half
+ destructively modifies the register).
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 8 1 2 9 16 24 17 B
+ C 10 3 4 11 18 25 32 40 E
+ F 33 26 19 12 5 6 13 20 D
+ G 27 34 41 48 56 49 42 35 I
+ L 28 21 14 7 15 22 29 36 M
+ H 43 50 57 58 51 44 37 30 O
+ N 23 31 38 45 52 59 60 53 J
+ P 46 39 47 54 61 62 55 63 K
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_TRANSPOSE_ZIG_ZAG_MMXEXT \
+ OC_ZZ_LOAD_ROW_LO(0,mm0) /*mm0=03 02 01 00*/ \
+ OC_ZZ_LOAD_ROW_LO(1,mm1) /*mm1=11 10 09 08*/ \
+ OC_ZZ_LOAD_ROW_LO(2,mm2) /*mm2=19 18 17 16*/ \
+ OC_ZZ_LOAD_ROW_LO(3,mm3) /*mm3=27 26 25 24*/ \
+ OC_ZZ_LOAD_ROW_HI(0,mm4) /*mm4=07 06 05 04*/ \
+ OC_ZZ_LOAD_ROW_HI(1,mm5) /*mm5=15 14 13 12*/ \
+ OC_ZZ_LOAD_ROW_HI(2,mm6) /*mm6=23 22 21 20*/ \
+ __asm movq mm7,mm0 /*mm7=03 02 01 00*/ \
+ __asm punpckhdq mm0,mm1 /*mm0=11 10 03 02*/ \
+ __asm pshufw mm4,mm4,0x39 /*mm4=04 07 06 05*/ \
+ __asm punpcklwd mm1,mm0 /*mm1=03 09 02 08*/ \
+ __asm pshufw mm5,mm5,0x39 /*mm5=12 15 14 13*/ \
+ __asm punpcklwd mm7,mm1 /*mm7=02 01 08 00 *A*/ \
+ __asm movq [Y+0x00],mm7 \
+ __asm punpckhwd mm1,mm4 /*mm1=04 03 07 09*/ \
+ __asm movq mm7,mm2 /*mm7=19 18 17 16*/ \
+ __asm punpckhdq mm0,mm1 /*mm0=04 03 11 10*/ \
+ __asm punpckhwd mm7,mm5 /*mm7=12 19 15 18*/ \
+ __asm punpcklwd mm1,mm3 /*mm1=25 07 24 09*/ \
+ __asm punpcklwd mm5,mm6 /*mm5=21 14 20 13*/ \
+ __asm punpcklwd mm1,mm2 /*mm1=17 24 16 09 *B*/ \
+ OC_ZZ_LOAD_ROW_LO(4,mm2) /*mm2=35 34 33 32*/ \
+ __asm movq [Y+0x08],mm1 \
+ OC_ZZ_LOAD_ROW_LO(5,mm1) /*mm1=43 42 41 40*/ \
+ __asm pshufw mm0,mm0,0x78 /*mm0=11 04 03 10 *C*/ \
+ __asm movq [Y+0x10],mm0 \
+ __asm punpckhdq mm6,mm4 /*mm6=?? 07 23 22*/ \
+ __asm punpckldq mm4,mm5 /*mm4=20 13 06 05 *D*/ \
+ __asm movq [Y+0x28],mm4 \
+ __asm psrlq mm3,16 /*mm3=.. 27 26 25*/ \
+ __asm pshufw mm0,mm2,0x0E /*mm0=?? ?? 35 34*/ \
+ __asm movq mm4,mm7 /*mm4=12 19 15 18*/ \
+ __asm punpcklwd mm2,mm3 /*mm2=26 33 25 32*/ \
+ __asm punpcklwd mm4,mm1 /*mm4=41 15 40 18*/ \
+ __asm punpckhwd mm3,mm1 /*mm3=43 .. 42 27*/ \
+ __asm punpckldq mm4,mm2 /*mm4=25 32 40 18*/ \
+ __asm punpcklwd mm3,mm0 /*mm3=35 42 34 27*/ \
+ OC_ZZ_LOAD_ROW_LO(6,mm0) /*mm0=51 50 49 48*/ \
+ __asm pshufw mm4,mm4,0x6C /*mm4=40 32 25 18 *E*/ \
+ __asm movq [Y+0x18],mm4 \
+ OC_ZZ_LOAD_ROW_LO(7,mm4) /*mm4=59 58 57 56*/ \
+ __asm punpckhdq mm2,mm7 /*mm2=12 19 26 33 *F*/ \
+ __asm movq [Y+0x20],mm2 \
+ __asm pshufw mm1,mm1,0xD0 /*mm1=43 41 ?? ??*/ \
+ __asm pshufw mm0,mm0,0x87 /*mm0=50 48 49 51*/ \
+ __asm movq mm2,mm3 /*mm2=35 42 34 27*/ \
+ __asm punpckhwd mm1,mm0 /*mm1=50 43 48 41*/ \
+ __asm pshufw mm4,mm4,0x93 /*mm4=58 57 56 59*/ \
+ __asm punpckldq mm3,mm1 /*mm3=48 41 34 27 *G*/ \
+ __asm movq [Y+0x30],mm3 \
+ __asm punpckhdq mm1,mm4 /*mm1=58 57 50 43 *H*/ \
+ __asm movq [Y+0x50],mm1 \
+ OC_ZZ_LOAD_ROW_HI(7,mm1) /*mm1=63 62 61 60*/ \
+ __asm punpcklwd mm4,mm0 /*mm4=49 56 51 59*/ \
+ OC_ZZ_LOAD_ROW_HI(6,mm0) /*mm0=55 54 53 52*/ \
+ __asm psllq mm6,16 /*mm6=07 23 22 ..*/ \
+ __asm movq mm3,mm4 /*mm3=49 56 51 59*/ \
+ __asm punpckhdq mm4,mm2 /*mm4=35 42 49 56 *I*/ \
+ OC_ZZ_LOAD_ROW_HI(3,mm2) /*mm2=31 30 29 28*/ \
+ __asm movq [Y+0x38],mm4 \
+ __asm punpcklwd mm3,mm1 /*mm3=61 51 60 59*/ \
+ __asm punpcklwd mm7,mm6 /*mm7=22 15 .. ??*/ \
+ __asm movq mm4,mm3 /*mm4=61 51 60 59*/ \
+ __asm punpcklwd mm3,mm0 /*mm3=53 60 52 59*/ \
+ __asm punpckhwd mm4,mm0 /*mm4=55 61 54 51*/ \
+ OC_ZZ_LOAD_ROW_HI(4,mm0) /*mm0=39 38 37 36*/ \
+ __asm pshufw mm3,mm3,0xE1 /*mm3=53 60 59 52 *J*/ \
+ __asm movq [Y+0x68],mm3 \
+ __asm movq mm3,mm4 /*mm3=?? ?? 54 51*/ \
+ __asm pshufw mm2,mm2,0x39 /*mm2=28 31 30 29*/ \
+ __asm punpckhwd mm4,mm1 /*mm4=63 55 62 61 *K*/ \
+ OC_ZZ_LOAD_ROW_HI(5,mm1) /*mm1=47 46 45 44*/ \
+ __asm movq [Y+0x78],mm4 \
+ __asm punpckhwd mm6,mm2 /*mm6=28 07 31 23*/ \
+ __asm punpcklwd mm2,mm0 /*mm2=37 30 36 29*/ \
+ __asm punpckhdq mm5,mm6 /*mm5=28 07 21 14*/ \
+ __asm pshufw mm2,mm2,0x4B /*mm2=36 29 30 37*/ \
+ __asm pshufw mm5,mm5,0x87 /*mm5=07 14 21 28 *L*/ \
+ __asm movq [Y+0x40],mm5 \
+ __asm punpckhdq mm7,mm2 /*mm7=36 29 22 15 *M*/ \
+ __asm movq [Y+0x48],mm7 \
+ __asm pshufw mm1,mm1,0x9C /*mm1=46 45 47 44*/ \
+ __asm punpckhwd mm0,mm1 /*mm0=46 39 45 38*/ \
+ __asm punpcklwd mm3,mm1 /*mm3=47 54 44 51*/ \
+ __asm punpckldq mm6,mm0 /*mm6=45 38 31 23 *N*/ \
+ __asm movq [Y+0x60],mm6 \
+ __asm punpckhdq mm0,mm3 /*mm0=47 54 46 39*/ \
+ __asm punpckldq mm3,mm2 /*mm3=30 37 44 51 *O*/ \
+ __asm movq [Y+0x58],mm3 \
+ __asm pshufw mm0,mm0,0xB1 /*mm0=54 47 39 46 *P*/ \
+ __asm movq [Y+0x70],mm0 \
+
+/*Converts DCT coefficients in %[dct] from natural order into zig-zag scan
+ order and stores them in %[qdct].
+ The index of each output element in the original 64-element array should wind
+ up in the following 8x8 matrix (the letters indicate the order we compute
+ each 4-tuple below):
+ A 0 1 8 16 9 2 3 10 B
+ C 17 24 32 25 18 11 4 5 D
+ E 12 19 26 33 40 48 41 34 I
+ H 27 20 13 6 7 14 21 28 G
+ K 35 42 49 56 57 50 43 36 J
+ F 29 22 15 23 30 37 44 51 M
+ P 58 59 52 45 38 31 39 46 L
+ N 53 60 61 54 47 55 62 63 O
+ The order of the coefficients within each tuple is reversed in the comments
+ below to reflect the usual MSB to LSB notation.*/
+#define OC_ZIG_ZAG_MMXEXT \
+ "movq 0x00(%[dct]),%%mm0\n\t" /*mm0=03 02 01 00*/ \
+ "movq 0x08(%[dct]),%%mm1\n\t" /*mm1=07 06 05 04*/ \
+ "movq 0x10(%[dct]),%%mm2\n\t" /*mm2=11 10 09 08*/ \
+ "movq 0x20(%[dct]),%%mm3\n\t" /*mm3=19 18 17 16*/ \
+ "movq 0x30(%[dct]),%%mm4\n\t" /*mm4=27 26 25 24*/ \
+ "movq 0x40(%[dct]),%%mm5\n\t" /*mm5=35 34 33 32*/ \
+ "movq %%mm2,%%mm7\n\t" /*mm7=11 10 09 08*/ \
+ "punpcklwd %%mm3,%%mm2\n\t" /*mm2=17 09 16 08*/ \
+ "movq %%mm0,%%mm6\n\t" /*mm6=03 02 01 00*/ \
+ "punpckldq %%mm2,%%mm0\n\t" /*mm0=16 08 01 00 *A*/ \
+ "movq %%mm0,0x00(%[qdct])\n\t" \
+ "movq 0x18(%[dct]),%%mm0\n\t" /*mm0=15 14 13 12*/ \
+ "punpckhdq %%mm6,%%mm6\n\t" /*mm6=03 02 03 02*/ \
+ "psrlq $16,%%mm7\n\t" /*mm7=.. 11 10 09*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=10 09 03 02*/ \
+ "punpckhwd %%mm7,%%mm3\n\t" /*mm3=.. 19 11 18*/ \
+ "pshufw $0xD2,%%mm6,%%mm6\n\t" /*mm6=10 03 02 09 *B*/ \
+ "movq %%mm6,0x08(%[qdct])\n\t" \
+ "psrlq $48,%%mm2\n\t" /*mm2=.. .. .. 17*/ \
+ "movq %%mm1,%%mm6\n\t" /*mm6=07 06 05 04*/ \
+ "punpcklwd %%mm5,%%mm2\n\t" /*mm2=33 .. 32 17*/ \
+ "movq %%mm3,%%mm7\n\t" /*mm7=.. 19 11 18*/ \
+ "punpckldq %%mm1,%%mm3\n\t" /*mm3=05 04 11 18 *C*/ \
+ "por %%mm2,%%mm7\n\t" /*mm7=33 19 ?? ??*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=25 32 24 17 *D**/ \
+ "movq %%mm2,0x10(%[qdct])\n\t" \
+ "movq %%mm3,0x18(%[qdct])\n\t" \
+ "movq 0x28(%[dct]),%%mm2\n\t" /*mm2=23 22 21 20*/ \
+ "movq 0x38(%[dct]),%%mm1\n\t" /*mm1=31 30 29 28*/ \
+ "pshufw $0x9C,%%mm0,%%mm3\n\t" /*mm3=14 13 15 12*/ \
+ "punpckhdq %%mm7,%%mm7\n\t" /*mm7=33 19 33 19*/ \
+ "punpckhwd %%mm3,%%mm6\n\t" /*mm6=14 07 13 06*/ \
+ "punpckldq %%mm0,%%mm0\n\t" /*mm0=13 12 13 12*/ \
+ "punpcklwd %%mm1,%%mm3\n\t" /*mm3=29 15 28 12*/ \
+ "punpckhwd %%mm4,%%mm0\n\t" /*mm0=27 13 26 12*/ \
+ "pshufw $0xB4,%%mm3,%%mm3\n\t" /*mm3=15 29 28 12*/ \
+ "psrlq $48,%%mm4\n\t" /*mm4=.. .. .. 27*/ \
+ "punpcklwd %%mm7,%%mm0\n\t" /*mm0=33 26 19 12 *E*/ \
+ "punpcklwd %%mm1,%%mm4\n\t" /*mm4=29 .. 28 27*/ \
+ "punpckhwd %%mm2,%%mm3\n\t" /*mm3=23 15 22 29 *F*/ \
+ "movq %%mm0,0x20(%[qdct])\n\t" \
+ "movq %%mm3,0x50(%[qdct])\n\t" \
+ "movq 0x60(%[dct]),%%mm3\n\t" /*mm3=51 50 49 48*/ \
+ "movq 0x70(%[dct]),%%mm7\n\t" /*mm7=59 58 57 56*/ \
+ "movq 0x50(%[dct]),%%mm0\n\t" /*mm0=43 42 41 40*/ \
+ "punpcklwd %%mm4,%%mm2\n\t" /*mm2=28 21 27 20*/ \
+ "psrlq $32,%%mm5\n\t" /*mm5=.. .. 35 34*/ \
+ "movq %%mm2,%%mm4\n\t" /*mm4=28 21 27 20*/ \
+ "punpckldq %%mm6,%%mm2\n\t" /*mm2=13 06 27 20*/ \
+ "punpckhdq %%mm4,%%mm6\n\t" /*mm6=28 21 14 07 *G*/ \
+ "movq %%mm3,%%mm4\n\t" /*mm4=51 50 49 48*/ \
+ "pshufw $0xB1,%%mm2,%%mm2\n\t" /*mm2=06 13 20 27 *H*/ \
+ "movq %%mm2,0x30(%[qdct])\n\t" \
+ "movq %%mm6,0x38(%[qdct])\n\t" \
+ "movq 0x48(%[dct]),%%mm2\n\t" /*mm2=39 38 37 36*/ \
+ "punpcklwd %%mm5,%%mm4\n\t" /*mm4=35 49 34 48*/ \
+ "movq 0x58(%[dct]),%%mm5\n\t" /*mm5=47 46 45 44*/ \
+ "punpckldq %%mm7,%%mm6\n\t" /*mm6=57 56 14 07*/ \
+ "psrlq $32,%%mm3\n\t" /*mm3=.. .. 51 50*/ \
+ "punpckhwd %%mm0,%%mm6\n\t" /*mm6=43 57 42 56*/ \
+ "punpcklwd %%mm4,%%mm0\n\t" /*mm0=34 41 48 40 *I*/ \
+ "pshufw $0x4E,%%mm6,%%mm6\n\t" /*mm6=42 56 43 57*/ \
+ "movq %%mm0,0x28(%[qdct])\n\t" \
+ "punpcklwd %%mm2,%%mm3\n\t" /*mm3=37 51 36 50*/ \
+ "punpckhwd %%mm6,%%mm4\n\t" /*mm4=42 35 56 49*/ \
+ "punpcklwd %%mm3,%%mm6\n\t" /*mm6=36 43 50 57 *J*/ \
+ "pshufw $0x4E,%%mm4,%%mm4\n\t" /*mm4=56 49 42 35 *K*/ \
+ "movq %%mm4,0x40(%[qdct])\n\t" \
+ "movq %%mm6,0x48(%[qdct])\n\t" \
+ "movq 0x68(%[dct]),%%mm6\n\t" /*mm6=55 54 53 52*/ \
+ "movq 0x78(%[dct]),%%mm0\n\t" /*mm0=63 62 61 60*/ \
+ "psrlq $32,%%mm1\n\t" /*mm1=.. .. 31 30*/ \
+ "pshufw $0xD8,%%mm5,%%mm5\n\t" /*mm5=47 45 46 44*/ \
+ "pshufw $0x0B,%%mm3,%%mm3\n\t" /*mm3=50 50 51 37*/ \
+ "punpcklwd %%mm5,%%mm1\n\t" /*mm1=46 31 44 30*/ \
+ "pshufw $0xC9,%%mm6,%%mm6\n\t" /*mm6=55 52 54 53*/ \
+ "punpckhwd %%mm1,%%mm2\n\t" /*mm2=46 39 31 38 *L*/ \
+ "punpcklwd %%mm3,%%mm1\n\t" /*mm1=51 44 37 30 *M*/ \
+ "movq %%mm2,0x68(%[qdct])\n\t" \
+ "movq %%mm1,0x58(%[qdct])\n\t" \
+ "punpckhwd %%mm6,%%mm5\n\t" /*mm5=55 47 52 45*/ \
+ "punpckldq %%mm0,%%mm6\n\t" /*mm6=61 60 54 53*/ \
+ "pshufw $0x10,%%mm5,%%mm4\n\t" /*mm4=45 52 45 45*/ \
+ "pshufw $0x78,%%mm6,%%mm6\n\t" /*mm6=53 60 61 54 *N*/ \
+ "punpckhdq %%mm0,%%mm5\n\t" /*mm5=63 62 55 47 *O*/ \
+ "punpckhdq %%mm4,%%mm7\n\t" /*mm7=45 52 59 58 *P*/ \
+ "movq %%mm6,0x70(%[qdct])\n\t" \
+ "movq %%mm5,0x78(%[qdct])\n\t" \
+ "movq %%mm7,0x60(%[qdct])\n\t" \
+
+#endif