diff options
Diffstat (limited to 'drivers')
30 files changed, 570 insertions, 330 deletions
diff --git a/drivers/alsa/asound-so_wrap.c b/drivers/alsa/asound-so_wrap.c index 6f9c5408d5..ffe24d4313 100644 --- a/drivers/alsa/asound-so_wrap.c +++ b/drivers/alsa/asound-so_wrap.c @@ -1,7 +1,7 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:26:13 -// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/alsa/asoundlib.h --sys-include "thirdparty/linuxbsd_headers/alsa/asoundlib.h" --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header ./drivers/alsa/asound-so_wrap.h --output-implementation ./drivers/alsa/asound-so_wrap.c +// generated by generate-wrapper.py 0.3 on 2023-01-12 10:26:13 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/alsa/asoundlib.h --sys-include "thirdparty/linuxbsd_headers/alsa/asoundlib.h" --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header ./drivers/alsa/asound-so_wrap.h --output-implementation ./drivers/alsa/asound-so_wrap.c // #include <stdint.h> diff --git a/drivers/alsa/asound-so_wrap.h b/drivers/alsa/asound-so_wrap.h index ab54f4e8cf..8d12d15ba8 100644 --- a/drivers/alsa/asound-so_wrap.h +++ b/drivers/alsa/asound-so_wrap.h @@ -2,8 +2,8 @@ #define DYLIBLOAD_WRAPPER_ASOUND // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:26:13 -// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/alsa/asoundlib.h --sys-include "thirdparty/linuxbsd_headers/alsa/asoundlib.h" --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header ./drivers/alsa/asound-so_wrap.h --output-implementation ./drivers/alsa/asound-so_wrap.c +// generated by generate-wrapper.py 0.3 on 2023-01-12 10:26:13 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/alsa/asoundlib.h --sys-include "thirdparty/linuxbsd_headers/alsa/asoundlib.h" --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header ./drivers/alsa/asound-so_wrap.h --output-implementation ./drivers/alsa/asound-so_wrap.c // #include <stdint.h> diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index 219529d2f6..c454da8e23 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -44,10 +44,10 @@ OSStatus AudioDriverCoreAudio::input_device_address_cb(AudioObjectID inObjectID, void *inClientData) { AudioDriverCoreAudio *driver = static_cast<AudioDriverCoreAudio *>(inClientData); - // If our selected device is the Default call set_device to update the + // If our selected input device is the Default, call set_input_device to update the // kAudioOutputUnitProperty_CurrentDevice property - if (driver->capture_device_name == "Default") { - driver->capture_set_device("Default"); + if (driver->input_device_name == "Default") { + driver->set_input_device("Default"); } return noErr; @@ -58,10 +58,10 @@ OSStatus AudioDriverCoreAudio::output_device_address_cb(AudioObjectID inObjectID void *inClientData) { AudioDriverCoreAudio *driver = static_cast<AudioDriverCoreAudio *>(inClientData); - // If our selected device is the Default call set_device to update the + // If our selected output device is the Default call set_output_device to update the // kAudioOutputUnitProperty_CurrentDevice property - if (driver->device_name == "Default") { - driver->set_device("Default"); + if (driver->output_device_name == "Default") { + driver->set_output_device("Default"); } return noErr; @@ -283,7 +283,7 @@ void AudioDriverCoreAudio::unlock() { } bool AudioDriverCoreAudio::try_lock() { - return mutex.try_lock() == OK; + return mutex.try_lock(); } void AudioDriverCoreAudio::finish() { @@ -495,7 +495,7 @@ Error AudioDriverCoreAudio::capture_stop() { #ifdef MACOS_ENABLED -PackedStringArray AudioDriverCoreAudio::_get_device_list(bool capture) { +PackedStringArray AudioDriverCoreAudio::_get_device_list(bool input) { PackedStringArray list; list.push_back("Default"); @@ -514,7 +514,7 @@ PackedStringArray AudioDriverCoreAudio::_get_device_list(bool capture) { UInt32 deviceCount = size / sizeof(AudioDeviceID); for (UInt32 i = 0; i < deviceCount; i++) { - prop.mScope = capture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + prop.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size); @@ -555,10 +555,10 @@ PackedStringArray AudioDriverCoreAudio::_get_device_list(bool capture) { return list; } -void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { +void AudioDriverCoreAudio::_set_device(const String &output_device, bool input) { AudioDeviceID deviceId; bool found = false; - if (device != "Default") { + if (output_device != "Default") { AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDevices; @@ -573,7 +573,7 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { UInt32 deviceCount = size / sizeof(AudioDeviceID); for (UInt32 i = 0; i < deviceCount && !found; i++) { - prop.mScope = capture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + prop.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size); @@ -602,7 +602,7 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { ERR_FAIL_NULL_MSG(buffer, "Out of memory."); if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) { String name = String::utf8(buffer) + " (" + itos(audioDevices[i]) + ")"; - if (name == device) { + if (name == output_device) { deviceId = audioDevices[i]; found = true; } @@ -618,7 +618,7 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { if (!found) { // If we haven't found the desired device get the system default one UInt32 size = sizeof(AudioDeviceID); - UInt32 elem = capture ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice; + UInt32 elem = input ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice; AudioObjectPropertyAddress property = { elem, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, nullptr, &size, &deviceId); @@ -628,10 +628,10 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } if (found) { - OSStatus result = AudioUnitSetProperty(capture ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); + OSStatus result = AudioUnitSetProperty(input ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); ERR_FAIL_COND(result != noErr); - if (capture) { + if (input) { // Reset audio input to keep synchronization. input_position = 0; input_size = 0; @@ -639,34 +639,34 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } } -PackedStringArray AudioDriverCoreAudio::get_device_list() { +PackedStringArray AudioDriverCoreAudio::get_output_device_list() { return _get_device_list(); } -String AudioDriverCoreAudio::get_device() { - return device_name; +String AudioDriverCoreAudio::get_output_device() { + return output_device_name; } -void AudioDriverCoreAudio::set_device(String device) { - device_name = device; +void AudioDriverCoreAudio::set_output_device(String output_device) { + output_device_name = output_device; if (active) { - _set_device(device_name); + _set_device(output_device_name); } } -void AudioDriverCoreAudio::capture_set_device(const String &p_name) { - capture_device_name = p_name; +void AudioDriverCoreAudio::set_input_device(const String &p_name) { + input_device_name = p_name; if (active) { - _set_device(capture_device_name, true); + _set_device(input_device_name, true); } } -PackedStringArray AudioDriverCoreAudio::capture_get_device_list() { +PackedStringArray AudioDriverCoreAudio::get_input_device_list() { return _get_device_list(true); } -String AudioDriverCoreAudio::capture_get_device() { - return capture_device_name; +String AudioDriverCoreAudio::get_input_device() { + return input_device_name; } #endif diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index 675265757b..2b192e630e 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -47,8 +47,8 @@ class AudioDriverCoreAudio : public AudioDriver { bool active = false; Mutex mutex; - String device_name = "Default"; - String capture_device_name = "Default"; + String output_device_name = "Default"; + String input_device_name = "Default"; int mix_rate = 0; unsigned int channels = 2; @@ -60,7 +60,7 @@ class AudioDriverCoreAudio : public AudioDriver { #ifdef MACOS_ENABLED PackedStringArray _get_device_list(bool capture = false); - void _set_device(const String &device, bool capture = false); + void _set_device(const String &output_device, bool capture = false); static OSStatus input_device_address_cb(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, @@ -107,13 +107,13 @@ public: void stop(); #ifdef MACOS_ENABLED - virtual PackedStringArray get_device_list(); - virtual String get_device(); - virtual void set_device(String device); + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(String output_device); - virtual PackedStringArray capture_get_device_list(); - virtual void capture_set_device(const String &p_name); - virtual String capture_get_device(); + virtual PackedStringArray get_input_device_list(); + virtual void set_input_device(const String &p_name); + virtual String get_input_device(); #endif AudioDriverCoreAudio(); diff --git a/drivers/gles3/environment/fog.cpp b/drivers/gles3/environment/fog.cpp index 87470b454b..6083c4da46 100644 --- a/drivers/gles3/environment/fog.cpp +++ b/drivers/gles3/environment/fog.cpp @@ -49,7 +49,7 @@ void Fog::fog_volume_free(RID p_rid) { void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { } -void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { +void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) { } void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) { diff --git a/drivers/gles3/environment/fog.h b/drivers/gles3/environment/fog.h index 99f2e27c44..7dc0265917 100644 --- a/drivers/gles3/environment/fog.h +++ b/drivers/gles3/environment/fog.h @@ -49,7 +49,7 @@ public: virtual void fog_volume_free(RID p_rid) override; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override; virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override; diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 89b1c1889e..7f381b3f3e 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -113,16 +113,19 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ // Clear out any state that may have been left from the 3D pass. reset_canvas(); - if (state.canvas_instance_data_buffers[state.current_buffer].fence != GLsync()) { + if (state.canvas_instance_data_buffers[state.current_data_buffer_index].fence != GLsync()) { GLint syncStatus; - glGetSynciv(state.canvas_instance_data_buffers[state.current_buffer].fence, GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus); + glGetSynciv(state.canvas_instance_data_buffers[state.current_data_buffer_index].fence, GL_SYNC_STATUS, sizeof(GLint), nullptr, &syncStatus); if (syncStatus == GL_UNSIGNALED) { // If older than 2 frames, wait for sync OpenGL can have up to 3 frames in flight, any more and we need to sync anyway. - if (state.canvas_instance_data_buffers[state.current_buffer].last_frame_used < RSG::rasterizer->get_frame_number() - 2) { + if (state.canvas_instance_data_buffers[state.current_data_buffer_index].last_frame_used < RSG::rasterizer->get_frame_number() - 2) { #ifndef WEB_ENABLED // On web, we do nothing as the glSubBufferData will force a sync anyway and WebGL does not like waiting. - glClientWaitSync(state.canvas_instance_data_buffers[state.current_buffer].fence, 0, 100000000); // wait for up to 100ms + glClientWaitSync(state.canvas_instance_data_buffers[state.current_data_buffer_index].fence, 0, 100000000); // wait for up to 100ms #endif + state.canvas_instance_data_buffers[state.current_data_buffer_index].last_frame_used = RSG::rasterizer->get_frame_number(); + glDeleteSync(state.canvas_instance_data_buffers[state.current_data_buffer_index].fence); + state.canvas_instance_data_buffers[state.current_data_buffer_index].fence = GLsync(); } else { // Used in last frame or frame before that. OpenGL can get up to two frames behind, so these buffers may still be in use // Allocate a new buffer and use that. @@ -130,9 +133,9 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ } } else { // Already finished all rendering commands, we can use it. - state.canvas_instance_data_buffers[state.current_buffer].last_frame_used = RSG::rasterizer->get_frame_number(); - glDeleteSync(state.canvas_instance_data_buffers[state.current_buffer].fence); - state.canvas_instance_data_buffers[state.current_buffer].fence = GLsync(); + state.canvas_instance_data_buffers[state.current_data_buffer_index].last_frame_used = RSG::rasterizer->get_frame_number(); + glDeleteSync(state.canvas_instance_data_buffers[state.current_data_buffer_index].fence); + state.canvas_instance_data_buffers[state.current_data_buffer_index].fence = GLsync(); } } @@ -279,7 +282,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ } if (light_count > 0) { - glBindBufferBase(GL_UNIFORM_BUFFER, LIGHT_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer].light_ubo); + glBindBufferBase(GL_UNIFORM_BUFFER, LIGHT_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_data_buffer_index].light_ubo); #ifdef WEB_ENABLED glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightUniform) * light_count, state.light_uniforms); @@ -361,7 +364,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5); - glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer].state_ubo); + glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_data_buffer_index].state_ubo); glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW); GLuint global_buffer = material_storage->global_shader_parameters_get_uniform_buffer(); @@ -395,7 +398,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ Item *ci = p_item_list; Item *canvas_group_owner = nullptr; - uint32_t starting_index = 0; + state.last_item_index = 0; while (ci) { if (ci->copy_back_buffer && canvas_group_owner == nullptr) { @@ -440,6 +443,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c); if (cm->mesh_instance.is_valid()) { mesh_storage->mesh_instance_check_for_update(cm->mesh_instance); + mesh_storage->mesh_instance_set_canvas_item_transform(cm->mesh_instance, canvas_transform_inverse * ci->final_transform); update_skeletons = true; } } @@ -454,7 +458,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ update_skeletons = false; } // Canvas group begins here, render until before this item - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used); item_count = 0; if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) { @@ -485,7 +489,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ mesh_storage->update_mesh_instances(); update_skeletons = false; } - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used, true); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, true); item_count = 0; if (ci->canvas_group->blur_mipmaps) { @@ -504,7 +508,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ } //render anything pending, including clearing if no items - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used); item_count = 0; texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps); @@ -530,7 +534,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ mesh_storage->update_mesh_instances(); update_skeletons = false; } - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, r_sdf_used); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used); //then reset item_count = 0; } @@ -542,14 +546,15 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ RenderingServerDefault::redraw_request(); } - state.canvas_instance_data_buffers[state.current_buffer].fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + state.canvas_instance_data_buffers[state.current_data_buffer_index].fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); // Clear out state used in 2D pass reset_canvas(); - state.current_buffer = (state.current_buffer + 1) % state.canvas_instance_data_buffers.size(); + state.current_data_buffer_index = (state.current_data_buffer_index + 1) % state.canvas_instance_data_buffers.size(); + state.current_instance_buffer_index = 0; } -void RasterizerCanvasGLES3::_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 &r_sdf_used, bool p_to_backbuffer) { +void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); canvas_begin(p_to_render_target, p_to_backbuffer); @@ -565,17 +570,17 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou // Record Batches. // First item always forms its own batch. bool batch_broken = false; - _new_batch(batch_broken, index); + _new_batch(batch_broken); // Override the start position and index as we want to start from where we finished off last time. - state.canvas_instance_batches[state.current_batch_index].start = r_last_index; + state.canvas_instance_batches[state.current_batch_index].start = state.last_item_index; index = 0; for (int i = 0; i < p_item_count; i++) { Item *ci = items[i]; if (ci->final_clip_owner != state.canvas_instance_batches[state.current_batch_index].clip) { - _new_batch(batch_broken, index); + _new_batch(batch_broken); state.canvas_instance_batches[state.current_batch_index].clip = ci->final_clip_owner; current_clip = ci->final_clip_owner; } @@ -599,7 +604,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou GLES3::CanvasShaderData *shader_data_cache = nullptr; if (material != state.canvas_instance_batches[state.current_batch_index].material) { - _new_batch(batch_broken, index); + _new_batch(batch_broken); GLES3::CanvasMaterialData *material_data = nullptr; if (material.is_valid()) { @@ -629,12 +634,12 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } // Copy over all data needed for rendering. - glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer); + glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[state.current_instance_buffer_index]); #ifdef WEB_ENABLED - glBufferSubData(GL_ARRAY_BUFFER, r_last_index * sizeof(InstanceData), sizeof(InstanceData) * index, state.instance_data_array); + glBufferSubData(GL_ARRAY_BUFFER, state.last_item_index * sizeof(InstanceData), sizeof(InstanceData) * index, state.instance_data_array); #else // On Desktop and mobile we map the memory without synchronizing for maximum speed. - void *buffer = glMapBufferRange(GL_ARRAY_BUFFER, r_last_index * sizeof(InstanceData), index * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + void *buffer = glMapBufferRange(GL_ARRAY_BUFFER, state.last_item_index * sizeof(InstanceData), index * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); memcpy(buffer, state.instance_data_array, index * sizeof(InstanceData)); glUnmapBuffer(GL_ARRAY_BUFFER); #endif @@ -757,14 +762,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou state.current_batch_index = 0; state.canvas_instance_batches.clear(); - r_last_index += index; + state.last_item_index += index; } void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used) { 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) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].filter = texture_filter; } @@ -772,7 +777,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? state.default_repeat : p_item->texture_repeat; if (texture_repeat != state.canvas_instance_batches[state.current_batch_index].repeat) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].repeat = texture_repeat; } @@ -816,7 +821,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend bool lights_disabled = light_count == 0 && !state.using_directional_lights; if (lights_disabled != state.canvas_instance_batches[state.current_batch_index].lights_disabled) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].lights_disabled = lights_disabled; } @@ -853,18 +858,19 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config - Color blend_color; + Color blend_color = base_color; + GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode; if (c->type == Item::Command::TYPE_RECT) { const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c); if (rect->flags & CANVAS_RECT_LCD) { - p_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_LCD; + blend_mode = GLES3::CanvasShaderData::BLEND_MODE_LCD; blend_color = rect->modulate * base_color; } } - if (p_blend_mode != state.canvas_instance_batches[state.current_batch_index].blend_mode || blend_color != state.canvas_instance_batches[state.current_batch_index].blend_color) { - _new_batch(r_batch_broken, r_index); - state.canvas_instance_batches[state.current_batch_index].blend_mode = p_blend_mode; + if (blend_mode != state.canvas_instance_batches[state.current_batch_index].blend_mode || blend_color != state.canvas_instance_batches[state.current_batch_index].blend_color) { + _new_batch(r_batch_broken); + state.canvas_instance_batches[state.current_batch_index].blend_mode = blend_mode; state.canvas_instance_batches[state.current_batch_index].blend_color = blend_color; } @@ -873,12 +879,12 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c); if (rect->flags & CANVAS_RECT_TILE && state.canvas_instance_batches[state.current_batch_index].repeat != RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; } if (rect->texture != state.canvas_instance_batches[state.current_batch_index].tex || state.canvas_instance_batches[state.current_batch_index].command_type != Item::Command::TYPE_RECT) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].tex = rect->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_RECT; state.canvas_instance_batches[state.current_batch_index].command = c; @@ -968,7 +974,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend const Item::CommandNinePatch *np = static_cast<const Item::CommandNinePatch *>(c); if (np->texture != state.canvas_instance_batches[state.current_batch_index].tex || state.canvas_instance_batches[state.current_batch_index].command_type != Item::Command::TYPE_NINEPATCH) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].tex = np->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_NINEPATCH; state.canvas_instance_batches[state.current_batch_index].command = c; @@ -1033,7 +1039,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c); // Polygon's can't be batched, so always create a new batch - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].tex = polygon->texture; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_POLYGON; @@ -1060,7 +1066,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c); if (primitive->point_count != state.canvas_instance_batches[state.current_batch_index].primitive_points || state.canvas_instance_batches[state.current_batch_index].command_type != Item::Command::TYPE_PRIMITIVE) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); state.canvas_instance_batches[state.current_batch_index].tex = primitive->texture; state.canvas_instance_batches[state.current_batch_index].primitive_points = primitive->point_count; state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_PRIMITIVE; @@ -1085,10 +1091,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend if (primitive->point_count == 4) { // Reset base data. _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world); - state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0; - state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0; - - state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config + _prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size); for (uint32_t j = 0; j < 3; j++) { int offset = j == 0 ? 0 : 1; @@ -1110,7 +1113,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { // Mesh's can't be batched, so always create a new batch - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); Color modulate(1, 1, 1, 1); state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES; @@ -1182,7 +1185,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend const Item::CommandClipIgnore *ci = static_cast<const Item::CommandClipIgnore *>(c); if (current_clip) { if (ci->ignore != reclip) { - _new_batch(r_batch_broken, r_index); + _new_batch(r_batch_broken); if (ci->ignore) { state.canvas_instance_batches[state.current_batch_index].clip = nullptr; reclip = true; @@ -1226,7 +1229,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) { case Item::Command::TYPE_RECT: case Item::Command::TYPE_NINEPATCH: { glBindVertexArray(data.indexed_quad_array); - glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer); + glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[state.canvas_instance_batches[p_index].instance_buffer_index]); uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData); _enable_attributes(range_start, false); @@ -1242,7 +1245,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) { ERR_FAIL_COND(!pb); glBindVertexArray(pb->vertex_array); - glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer); + glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[state.canvas_instance_batches[p_index].instance_buffer_index]); uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData); _enable_attributes(range_start, false); @@ -1266,7 +1269,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) { case Item::Command::TYPE_PRIMITIVE: { glBindVertexArray(data.canvas_quad_array); - glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer); + glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[state.canvas_instance_batches[p_index].instance_buffer_index]); uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData); _enable_attributes(range_start, true); @@ -1369,7 +1372,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) { index_array_gl = mesh_storage->mesh_surface_get_index_buffer(surface, 0); bool use_index_buffer = false; glBindVertexArray(vertex_array_gl); - glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_buffer].buffer); + glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[state.canvas_instance_batches[p_index].instance_buffer_index]); uint32_t range_start = state.canvas_instance_batches[p_index].start * sizeof(InstanceData); _enable_attributes(range_start, false, instance_count); @@ -1426,20 +1429,30 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) { } void RasterizerCanvasGLES3::_add_to_batch(uint32_t &r_index, bool &r_batch_broken) { - if (r_index >= data.max_instances_per_buffer - 1) { - ERR_PRINT_ONCE("Trying to draw too many items. Please increase maximum number of items in the project settings 'rendering/gl_compatibility/item_buffer_size'"); - return; - } - - if (state.canvas_instance_batches[state.current_batch_index].instance_count >= data.max_instances_per_batch) { - _new_batch(r_batch_broken, r_index); - } - state.canvas_instance_batches[state.current_batch_index].instance_count++; r_index++; + if (r_index >= data.max_instances_per_buffer) { + // Copy over all data needed for rendering right away + // then go back to recording item commands. + glBindBuffer(GL_ARRAY_BUFFER, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[state.current_instance_buffer_index]); +#ifdef WEB_ENABLED + glBufferSubData(GL_ARRAY_BUFFER, state.last_item_index * sizeof(InstanceData), sizeof(InstanceData) * r_index, state.instance_data_array); +#else + // On Desktop and mobile we map the memory without synchronizing for maximum speed. + void *buffer = glMapBufferRange(GL_ARRAY_BUFFER, state.last_item_index * sizeof(InstanceData), r_index * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + memcpy(buffer, state.instance_data_array, r_index * sizeof(InstanceData)); + glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + _allocate_instance_buffer(); + r_index = 0; + state.last_item_index = 0; + r_batch_broken = false; // Force a new batch to be created + _new_batch(r_batch_broken); + state.canvas_instance_batches[state.current_batch_index].start = 0; + } } -void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken, uint32_t &r_index) { +void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken) { if (state.canvas_instance_batches.size() == 0) { state.canvas_instance_batches.push_back(Batch()); return; @@ -1455,7 +1468,7 @@ void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken, uint32_t &r_index) Batch new_batch = state.canvas_instance_batches[state.current_batch_index]; new_batch.instance_count = 0; new_batch.start = state.canvas_instance_batches[state.current_batch_index].start + state.canvas_instance_batches[state.current_batch_index].instance_count; - + new_batch.instance_buffer_index = state.current_instance_buffer_index; state.current_batch_index++; state.canvas_instance_batches.push_back(new_batch); } @@ -1486,6 +1499,9 @@ void RasterizerCanvasGLES3::light_set_texture(RID p_rid, RID p_texture) { if (cl->texture == p_texture) { return; } + + ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture)); + if (cl->texture.is_valid()) { texture_storage->texture_remove_from_texture_atlas(cl->texture); } @@ -2432,17 +2448,35 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() { glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[2]); glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), nullptr, GL_STREAM_DRAW); - state.current_buffer = (state.current_buffer + 1); + state.current_data_buffer_index = (state.current_data_buffer_index + 1); DataBuffer db; - db.buffer = new_buffers[0]; + db.instance_buffers.push_back(new_buffers[0]); db.light_ubo = new_buffers[1]; db.state_ubo = new_buffers[2]; db.last_frame_used = RSG::rasterizer->get_frame_number(); - state.canvas_instance_data_buffers.insert(state.current_buffer, db); - state.current_buffer = state.current_buffer % state.canvas_instance_data_buffers.size(); + state.canvas_instance_data_buffers.insert(state.current_data_buffer_index, db); + state.current_data_buffer_index = state.current_data_buffer_index % state.canvas_instance_data_buffers.size(); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_UNIFORM_BUFFER, 0); } +void RasterizerCanvasGLES3::_allocate_instance_buffer() { + state.current_instance_buffer_index++; + + if (int(state.current_instance_buffer_index) < state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.size()) { + // We already allocated another buffer in a previous frame, so we can just use it. + return; + } + + GLuint new_buffer; + glGenBuffers(1, &new_buffer); + + glBindBuffer(GL_ARRAY_BUFFER, new_buffer); + glBufferData(GL_ARRAY_BUFFER, data.max_instance_buffer_size, nullptr, GL_STREAM_DRAW); + + state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(new_buffer); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} void RasterizerCanvasGLES3::set_time(double p_time) { state.time = p_time; @@ -2585,14 +2619,12 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() { int uniform_max_size = config->max_uniform_buffer_size; if (uniform_max_size < 65536) { data.max_lights_per_render = 64; - data.max_instances_per_batch = 128; } else { data.max_lights_per_render = 256; - data.max_instances_per_batch = 2048; } // Reserve 3 Uniform Buffers for instance data Frame N, N+1 and N+2 - data.max_instances_per_buffer = MAX(data.max_instances_per_batch, uint32_t(GLOBAL_GET("rendering/gl_compatibility/item_buffer_size"))); + data.max_instances_per_buffer = uint32_t(GLOBAL_GET("rendering/gl_compatibility/item_buffer_size")); data.max_instance_buffer_size = data.max_instances_per_buffer * sizeof(InstanceData); // 16,384 instances * 128 bytes = 2,097,152 bytes = 2,048 kb state.canvas_instance_data_buffers.resize(3); state.canvas_instance_batches.reserve(200); @@ -2610,7 +2642,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() { glBindBuffer(GL_UNIFORM_BUFFER, new_buffers[2]); glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), nullptr, GL_STREAM_DRAW); DataBuffer db; - db.buffer = new_buffers[0]; + db.instance_buffers.push_back(new_buffers[0]); db.light_ubo = new_buffers[1]; db.state_ubo = new_buffers[2]; db.last_frame_used = 0; @@ -2637,7 +2669,6 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() { String global_defines; global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now global_defines += "#define MAX_LIGHTS " + itos(data.max_lights_per_render) + "\n"; - global_defines += "#define MAX_DRAW_DATA_INSTANCES " + itos(data.max_instances_per_batch) + "\n"; GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.initialize(global_defines, 1); data.canvas_shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_create(); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 916e12057c..1c14d0b466 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -247,7 +247,6 @@ public: uint32_t max_lights_per_render = 256; uint32_t max_lights_per_item = 16; - uint32_t max_instances_per_batch = 512; uint32_t max_instances_per_buffer = 16384; uint32_t max_instance_buffer_size = 16384 * 128; } data; @@ -256,6 +255,7 @@ public: // Position in the UBO measured in bytes uint32_t start = 0; uint32_t instance_count = 0; + uint32_t instance_buffer_index = 0; RID tex; RS::CanvasItemTextureFilter filter = RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; @@ -281,7 +281,7 @@ public: // We track them and ensure that they don't get reused until at least 2 frames have passed // to avoid the GPU stalling to wait for a resource to become available. struct DataBuffer { - GLuint buffer = 0; + Vector<GLuint> instance_buffers; GLuint light_ubo = 0; GLuint state_ubo = 0; uint64_t last_frame_used = -3; @@ -291,9 +291,10 @@ public: struct State { LocalVector<DataBuffer> canvas_instance_data_buffers; LocalVector<Batch> canvas_instance_batches; - uint32_t current_buffer = 0; - uint32_t current_buffer_index = 0; + uint32_t current_data_buffer_index = 0; + uint32_t current_instance_buffer_index = 0; uint32_t current_batch_index = 0; + uint32_t last_item_index = 0; InstanceData *instance_data_array = nullptr; @@ -354,14 +355,14 @@ public: void _prepare_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, Size2 &r_texpixel_size); 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 &r_sdf_used, bool p_to_backbuffer = false); + void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false); void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch, bool &r_sdf_used); void _render_batch(Light *p_lights, uint32_t p_index); 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 _new_batch(bool &r_batch_broken); void _add_to_batch(uint32_t &r_index, bool &r_batch_broken); void _allocate_instance_data_buffer(); - void _align_instance_data_buffer(uint32_t &r_index); + void _allocate_instance_buffer(); void _enable_attributes(uint32_t p_start, bool p_primitive, uint32_t p_rate = 1); void set_time(double p_time); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 9547435607..1a18f35e64 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -145,6 +145,7 @@ void RasterizerSceneGLES3::_geometry_instance_dependency_changed(Dependency::Dep case Dependency::DEPENDENCY_CHANGED_MULTIMESH: case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); + static_cast<GeometryInstanceGLES3 *>(p_tracker->userdata)->data->dirty_dependencies = true; } break; case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_tracker->userdata); @@ -160,6 +161,7 @@ void RasterizerSceneGLES3::_geometry_instance_dependency_changed(Dependency::Dep void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); + static_cast<GeometryInstanceGLES3 *>(p_tracker->userdata)->data->dirty_dependencies = true; } void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { @@ -729,6 +731,11 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons } } + if (p_render_data->view_count > 1) { + glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + if (!sky->radiance) { _invalidate_sky(sky); _update_dirty_skys(); @@ -736,7 +743,7 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons } } -void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier) { +void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); @@ -746,6 +753,11 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; + uint64_t spec_constants = p_use_multiview ? SkyShaderGLES3::USE_MULTIVIEW : 0; + if (p_flip_y) { + spec_constants |= SkyShaderGLES3::USE_INVERTED_Y; + } + RS::EnvironmentBG background = environment_get_background(p_env); if (sky) { @@ -790,16 +802,21 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, sky_transform.invert(); sky_transform = sky_transform * p_transform.basis; - bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); 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); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + 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, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + + if (p_use_multiview) { + glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } glBindVertexArray(sky_globals.screen_triangle_array); glDrawArrays(GL_TRIANGLES, 0, 3); @@ -1973,7 +1990,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED; scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; - _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier); + _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier, p_camera_data->view_count > 1, flip_y); } RENDER_TIMESTAMP("Render 3D Transparent Pass"); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 7977e562c0..ff043d67f6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -83,6 +83,7 @@ enum SkyUniformLocation { SKY_EMPTY, // Unused, put here to avoid conflicts with SCENE_DATA_UNIFORM_LOCATION. SKY_MATERIAL_UNIFORM_LOCATION, SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, + SKY_MULTIVIEW_UNIFORM_LOCATION, }; struct RenderDataGLES3 { @@ -570,7 +571,7 @@ protected: void _update_dirty_skys(); void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier); void _filter_sky_radiance(Sky *p_sky, int p_base_layer); - void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier); + void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y); void _free_sky_data(Sky *p_sky); public: diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 71caf3b8e3..10f42bf22b 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -192,7 +192,7 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant builder.append("#define ViewIndex gl_ViewID_OVR\n"); builder.append("#define MAX_VIEWS 2\n"); builder.append("#else\n"); - builder.append("#define ViewIndex 0\n"); + builder.append("#define ViewIndex uint(0)\n"); builder.append("#define MAX_VIEWS 1\n"); builder.append("#endif\n"); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 52ff70f746..0b389b0478 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -268,9 +268,11 @@ void main() { #ifdef USE_MULTIVIEW mat4 projection_matrix = multiview_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = multiview_data.inv_projection_matrix_view[ViewIndex]; + vec3 eye_offset = multiview_data.eye_offset[ViewIndex].xyz; #else mat4 projection_matrix = scene_data.projection_matrix; mat4 inv_projection_matrix = scene_data.inv_projection_matrix; + vec3 eye_offset = vec3(0.0, 0.0, 0.0); #endif //USE_MULTIVIEW #ifdef USE_INSTANCING @@ -565,9 +567,15 @@ uniform highp samplerCubeShadow positional_shadow; // texunit:-4 #ifdef USE_MULTIVIEW uniform highp sampler2DArray depth_buffer; // texunit:-6 uniform highp sampler2DArray color_buffer; // texunit:-5 +vec3 multiview_uv(vec2 uv) { + return vec3(uv, ViewIndex); +} #else uniform highp sampler2D depth_buffer; // texunit:-6 uniform highp sampler2D color_buffer; // texunit:-5 +vec2 multiview_uv(vec2 uv) { + return uv; +} #endif uniform highp mat4 world_transform; @@ -924,9 +932,15 @@ void main() { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; #ifdef USE_MULTIVIEW - vec3 view = -normalize(vertex_interp - multiview_data.eye_offset[ViewIndex].xyz); + vec3 eye_offset = multiview_data.eye_offset[ViewIndex].xyz; + vec3 view = -normalize(vertex_interp - eye_offset); + mat4 projection_matrix = multiview_data.projection_matrix_view[ViewIndex]; + mat4 inv_projection_matrix = multiview_data.inv_projection_matrix_view[ViewIndex]; #else + vec3 eye_offset = vec3(0.0, 0.0, 0.0); vec3 view = -normalize(vertex_interp); + mat4 projection_matrix = scene_data.projection_matrix; + mat4 inv_projection_matrix = scene_data.inv_projection_matrix; #endif highp mat4 model_matrix = world_transform; vec3 albedo = vec3(1.0); diff --git a/drivers/gles3/shaders/skeleton.glsl b/drivers/gles3/shaders/skeleton.glsl index a1e3c098f4..aad856a5a2 100644 --- a/drivers/gles3/shaders/skeleton.glsl +++ b/drivers/gles3/shaders/skeleton.glsl @@ -87,6 +87,16 @@ uniform highp float blend_weight; uniform lowp float blend_shape_count; #endif +#ifdef USE_SKELETON +uniform mediump vec2 skeleton_transform_x; +uniform mediump vec2 skeleton_transform_y; +uniform mediump vec2 skeleton_transform_offset; + +uniform mediump vec2 inverse_transform_x; +uniform mediump vec2 inverse_transform_y; +uniform mediump vec2 inverse_transform_offset; +#endif + vec2 signNotZero(vec2 v) { return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0))); } @@ -164,10 +174,13 @@ void main() { m += GET_BONE_MATRIX(bones.z, bones_a.z, in_weight_attrib.z); m += GET_BONE_MATRIX(bones.w, bones_a.w, in_weight_attrib.w); + mat4 skeleton_matrix = mat4(vec4(skeleton_transform_x, 0.0, 0.0), vec4(skeleton_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(skeleton_transform_offset, 0.0, 1.0)); + mat4 inverse_matrix = mat4(vec4(inverse_transform_x, 0.0, 0.0), vec4(inverse_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(inverse_transform_offset, 0.0, 1.0)); mat4 bone_matrix = mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); - //reverse order because its transposed - out_vertex = (vec4(out_vertex, 0.0, 1.0) * bone_matrix).xy; + bone_matrix = skeleton_matrix * transpose(bone_matrix) * inverse_matrix; + + out_vertex = (bone_matrix * vec4(out_vertex, 0.0, 1.0)).xy; #endif // USE_SKELETON #else // MODE_2D diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 4c0fe47f6b..e59bca8b07 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -10,6 +10,9 @@ mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PA #[specializations] +USE_MULTIVIEW = false +USE_INVERTED_Y = true + #[vertex] layout(location = 0) in vec2 vertex_attrib; @@ -19,7 +22,11 @@ out vec2 uv_interp; void main() { uv_interp = vertex_attrib; +#ifdef USE_INVERTED_Y gl_Position = vec4(uv_interp, 1.0, 1.0); +#else + gl_Position = vec4(uv_interp.x, uv_interp.y * -1.0, 1.0, 1.0); +#endif } /* clang-format off */ @@ -37,6 +44,9 @@ uniform samplerCube radiance; //texunit:-1 #ifdef USE_CUBEMAP_PASS uniform samplerCube half_res; //texunit:-2 uniform samplerCube quarter_res; //texunit:-3 +#elif defined(USE_MULTIVIEW) +uniform sampler2DArray half_res; //texunit:-2 +uniform sampler2DArray quarter_res; //texunit:-3 #else uniform sampler2D half_res; //texunit:-2 uniform sampler2D quarter_res; //texunit:-3 @@ -102,6 +112,15 @@ uniform float fog_density; uniform float z_far; uniform uint directional_light_count; +#ifdef USE_MULTIVIEW +layout(std140) uniform MultiviewData { // ubo:5 + highp mat4 projection_matrix_view[MAX_VIEWS]; + highp mat4 inv_projection_matrix_view[MAX_VIEWS]; + highp vec4 eye_offset[MAX_VIEWS]; +} +multiview_data; +#endif + layout(location = 0) out vec4 frag_color; #ifdef USE_DEBANDING @@ -115,9 +134,20 @@ vec3 interleaved_gradient_noise(vec2 pos) { void main() { vec3 cube_normal; +#ifdef USE_MULTIVIEW + // In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject. + vec4 unproject = vec4(uv_interp.x, uv_interp.y, 1.0, 1.0); + vec4 unprojected = multiview_data.inv_projection_matrix_view[ViewIndex] * unproject; + cube_normal = unprojected.xyz / unprojected.w; + cube_normal += multiview_data.eye_offset[ViewIndex].xyz; +#else cube_normal.z = -1.0; cube_normal.x = (uv_interp.x + projection.x) / projection.y; cube_normal.y = (-uv_interp.y - projection.z) / projection.w; +#endif +#ifndef USE_INVERTED_Y + cube_normal.y *= -1.0; +#endif cube_normal = mat3(orientation) * cube_normal; cube_normal = normalize(cube_normal); @@ -146,12 +176,20 @@ void main() { #endif #else #ifdef USES_HALF_RES_COLOR +#ifdef USE_MULTIVIEW + half_res_color = textureLod(sampler2DArray(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0); +#else half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); #endif +#endif #ifdef USES_QUARTER_RES_COLOR +#ifdef USE_MULTIVIEW + quarter_res_color = textureLod(sampler2DArray(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0); +#else quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); #endif #endif +#endif { diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index d1a83e6851..77a4553c76 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -65,6 +65,10 @@ Config::Config() { } bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc"); + astc_supported = extensions.has("GL_KHR_texture_compression_astc") || extensions.has("GL_OES_texture_compression_astc") || extensions.has("GL_KHR_texture_compression_astc_ldr") || extensions.has("GL_KHR_texture_compression_astc_hdr"); + astc_hdr_supported = extensions.has("GL_KHR_texture_compression_astc_ldr"); + astc_layered_supported = extensions.has("GL_KHR_texture_compression_astc_sliced_3d"); + #ifdef GLES_OVER_GL float_texture_supported = true; etc2_supported = false; diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index 8399502675..623f0442bd 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -77,6 +77,9 @@ public: bool rgtc_supported = false; bool bptc_supported = false; bool etc2_supported = false; + bool astc_supported = false; + bool astc_hdr_supported = false; + bool astc_layered_supported = false; bool force_vertex_shading = false; diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index a325f79d8c..138498220d 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -403,7 +403,7 @@ void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_ener void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) { } -void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { +void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) { } void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { @@ -436,7 +436,7 @@ uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const { return 0; } -Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const { +Vector3 LightStorage::reflection_probe_get_size(RID p_probe) const { return Vector3(); } diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index 8b2bdaf872..f6f7628a90 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/drivers/gles3/storage/light_storage.h @@ -113,7 +113,7 @@ struct ReflectionProbe { Color ambient_color; float ambient_color_energy = 1.0; float max_distance = 0; - Vector3 extents = Vector3(10, 10, 10); + Vector3 size = Vector3(20, 20, 20); Vector3 origin_offset; bool interior = false; bool box_projection = false; @@ -332,7 +332,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override; virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override; + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) override; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override; virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override; virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override; @@ -345,7 +345,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const override; virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override; virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const override; + virtual Vector3 reflection_probe_get_size(RID p_probe) const override; virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override; virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override; virtual bool reflection_probe_renders_shadows(RID p_probe) const override; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 50e5c868d3..aa8df606cf 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1546,6 +1546,8 @@ MaterialStorage::MaterialStorage() { actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n"; + actions.global_buffer_array_variable = "global_shader_uniforms"; + shaders.compiler_canvas.initialize(actions); } @@ -1635,8 +1637,9 @@ MaterialStorage::MaterialStorage() { actions.renames["NODE_POSITION_VIEW"] = "(model_matrix * scene_data.view_matrix)[3].xyz"; actions.renames["VIEW_INDEX"] = "ViewIndex"; - actions.renames["VIEW_MONO_LEFT"] = "0"; - actions.renames["VIEW_RIGHT"] = "1"; + actions.renames["VIEW_MONO_LEFT"] = "uint(0)"; + actions.renames["VIEW_RIGHT"] = "uint(1)"; + actions.renames["EYE_OFFSET"] = "eye_offset"; //for light actions.renames["VIEW"] = "view"; @@ -1718,6 +1721,9 @@ MaterialStorage::MaterialStorage() { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; + actions.check_multiview_samplers = true; + actions.global_buffer_array_variable = "global_shader_uniforms"; + shaders.compiler_scene.initialize(actions); } @@ -1773,6 +1779,8 @@ MaterialStorage::MaterialStorage() { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; + actions.global_buffer_array_variable = "global_shader_uniforms"; + shaders.compiler_particles.initialize(actions); } @@ -1826,6 +1834,8 @@ MaterialStorage::MaterialStorage() { actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; + actions.global_buffer_array_variable = "global_shader_uniforms"; + shaders.compiler_sky.initialize(actions); } } diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 71f262af20..5ba0c5a09c 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -997,6 +997,11 @@ void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) { } } +void MeshStorage::mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + mi->canvas_item_transform_2d = p_transform; +} + void MeshStorage::_blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uint32_t p_surface) { glBindBuffer(GL_ARRAY_BUFFER, p_mi->surfaces[p_surface].vertex_buffers[0]); @@ -1163,6 +1168,16 @@ void MeshStorage::update_mesh_instances() { skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::BLEND_SHAPE_COUNT, float(mi->mesh->blend_shape_count), skeleton_shader.shader_version, variant, specialization); if (can_use_skeleton) { + Transform2D transform = mi->canvas_item_transform_2d.affine_inverse() * sk->base_transform_2d; + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::SKELETON_TRANSFORM_X, transform[0], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::SKELETON_TRANSFORM_Y, transform[1], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::SKELETON_TRANSFORM_OFFSET, transform[2], skeleton_shader.shader_version, variant, specialization); + + Transform2D inverse_transform = transform.affine_inverse(); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_X, inverse_transform[0], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_Y, inverse_transform[1], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_OFFSET, inverse_transform[2], skeleton_shader.shader_version, variant, specialization); + // Do last blendshape in the same pass as the Skeleton. _compute_skeleton(mi, sk, i); can_use_skeleton = false; @@ -1201,6 +1216,16 @@ void MeshStorage::update_mesh_instances() { continue; } + Transform2D transform = mi->canvas_item_transform_2d.affine_inverse() * sk->base_transform_2d; + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::SKELETON_TRANSFORM_X, transform[0], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::SKELETON_TRANSFORM_Y, transform[1], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::SKELETON_TRANSFORM_OFFSET, transform[2], skeleton_shader.shader_version, variant, specialization); + + Transform2D inverse_transform = transform.affine_inverse(); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_X, inverse_transform[0], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_Y, inverse_transform[1], skeleton_shader.shader_version, variant, specialization); + skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_OFFSET, inverse_transform[2], skeleton_shader.shader_version, variant, specialization); + glBindVertexArray(mi->mesh->surfaces[i]->skeleton_vertex_array); _compute_skeleton(mi, sk, i); } diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index 2efc57462b..e1c2bc3f63 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -163,6 +163,7 @@ struct MeshInstance { bool weights_dirty = false; SelfList<MeshInstance> weight_update_list; SelfList<MeshInstance> array_update_list; + Transform2D canvas_item_transform_2d; MeshInstance() : weight_update_list(this), array_update_list(this) {} }; @@ -423,6 +424,7 @@ public: virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override; virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override; virtual void mesh_instance_check_for_update(RID p_mesh_instance) override; + virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) override; virtual void update_mesh_instances() override; // TODO: considering hashing versions with multimesh buffer RID. diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 67526bc003..9c9c39cc0e 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -594,6 +594,50 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I } decompress_ra_to_rg = true; } break; + case Image::FORMAT_ASTC_4x4: { + if (config->astc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_4x4_KHR; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ASTC_4x4_HDR: { + if (config->astc_hdr_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_4x4_KHR; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ASTC_8x8: { + if (config->astc_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_8x8_KHR; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; + case Image::FORMAT_ASTC_8x8_HDR: { + if (config->astc_hdr_supported) { + r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_8x8_KHR; + r_gl_format = GL_RGBA; + r_gl_type = GL_UNSIGNED_BYTE; + r_compressed = true; + + } else { + need_decompress = true; + } + } break; default: { ERR_FAIL_V_MSG(Ref<Image>(), "Image Format: " + itos(p_format) + " is not supported by the OpenGL3 Renderer"); } @@ -1503,7 +1547,7 @@ RID TextureStorage::decal_allocate() { void TextureStorage::decal_initialize(RID p_rid) { } -void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) { +void TextureStorage::decal_set_size(RID p_decal, const Vector3 &p_size) { } void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { @@ -1778,6 +1822,10 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { rt->overridden.color = RID(); } else if (rt->color) { glDeleteTextures(1, &rt->color); + if (rt->texture.is_valid()) { + Texture *tex = get_texture(rt->texture); + tex->tex_id = 0; + } } rt->color = 0; diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 9d3f407226..017e74fc4d 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -84,6 +84,36 @@ namespace GLES3 { #define _EXT_COMPRESSED_RGBA8_ETC2_EAC 0x9278 #define _EXT_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define _EXT_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define _EXT_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define _EXT_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define _EXT_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define _EXT_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define _EXT_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define _EXT_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define _EXT_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define _EXT_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define _EXT_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define _EXT_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define _EXT_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define _EXT_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define _EXT_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD + +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define _EXT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD + #define _GL_TEXTURE_EXTERNAL_OES 0x8D65 #define _EXT_TEXTURE_CUBE_MAP_SEAMLESS 0x884F @@ -544,7 +574,7 @@ public: virtual void decal_initialize(RID p_rid) override; virtual void decal_free(RID p_rid) override{}; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override; + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override; virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override; virtual void decal_set_emission_energy(RID p_decal, float p_energy) override; virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override; diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp index e72240c69b..30c3e61ee7 100644 --- a/drivers/gles3/storage/utilities.cpp +++ b/drivers/gles3/storage/utilities.cpp @@ -309,6 +309,9 @@ bool Utilities::has_os_feature(const String &p_feature) const { if (p_feature == "bptc") { return config->bptc_supported; } + if (p_feature == "astc") { + return config->astc_supported; + } if (p_feature == "etc" || p_feature == "etc2") { return config->etc2_supported; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index e14c3c7f7a..f96247a473 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -106,15 +106,15 @@ void AudioDriverPulseAudio::pa_server_info_cb(pa_context *c, const pa_server_inf ERR_FAIL_COND_MSG(!i, "PulseAudio server info is null."); AudioDriverPulseAudio *ad = static_cast<AudioDriverPulseAudio *>(userdata); - ad->capture_default_device = i->default_source_name; - ad->default_device = i->default_sink_name; + ad->default_input_device = i->default_source_name; + ad->default_output_device = i->default_sink_name; ad->pa_status++; } -Error AudioDriverPulseAudio::detect_channels(bool capture) { - pa_channel_map_init_stereo(capture ? &pa_rec_map : &pa_map); +Error AudioDriverPulseAudio::detect_channels(bool input) { + pa_channel_map_init_stereo(input ? &pa_rec_map : &pa_map); - String device = capture ? capture_device_name : device_name; + String device = input ? input_device_name : output_device_name; if (device == "Default") { // Get the default output device name pa_status = 0; @@ -136,7 +136,7 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { char dev[1024]; if (device == "Default") { - strcpy(dev, capture ? capture_default_device.utf8().get_data() : default_device.utf8().get_data()); + strcpy(dev, input ? default_input_device.utf8().get_data() : default_output_device.utf8().get_data()); } else { strcpy(dev, device.utf8().get_data()); } @@ -145,7 +145,7 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { // Now using the device name get the amount of channels pa_status = 0; pa_operation *pa_op; - if (capture) { + if (input) { pa_op = pa_context_get_source_info_by_name(pa_ctx, dev, &AudioDriverPulseAudio::pa_source_info_cb, (void *)this); } else { pa_op = pa_context_get_sink_info_by_name(pa_ctx, dev, &AudioDriverPulseAudio::pa_sink_info_cb, (void *)this); @@ -165,7 +165,7 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { return FAILED; } } else { - if (capture) { + if (input) { ERR_PRINT("pa_context_get_source_info_by_name error"); } else { ERR_PRINT("pa_context_get_sink_info_by_name error"); @@ -175,13 +175,13 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { return OK; } -Error AudioDriverPulseAudio::init_device() { - // If there is a specified device check that it is really present - if (device_name != "Default") { - PackedStringArray list = get_device_list(); - if (list.find(device_name) == -1) { - device_name = "Default"; - new_device = "Default"; +Error AudioDriverPulseAudio::init_output_device() { + // If there is a specified output device, check that it is really present + if (output_device_name != "Default") { + PackedStringArray list = get_output_device_list(); + if (list.find(output_device_name) == -1) { + output_device_name = "Default"; + new_output_device = "Default"; } } @@ -192,7 +192,7 @@ Error AudioDriverPulseAudio::init_device() { Error err = detect_channels(); if (err != OK) { // This most likely means there are no sinks. - ERR_PRINT("PulseAudio: init device failed to detect number of output channels"); + ERR_PRINT("PulseAudio: init_output_device failed to detect number of output channels"); return err; } @@ -256,7 +256,7 @@ Error AudioDriverPulseAudio::init_device() { attr.maxlength = (uint32_t)-1; attr.minreq = (uint32_t)-1; - const char *dev = device_name == "Default" ? nullptr : device_name.utf8().get_data(); + const char *dev = output_device_name == "Default" ? nullptr : output_device_name.utf8().get_data(); pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); int error_code = pa_stream_connect_playback(pa_str, dev, &attr, flags, nullptr, nullptr); ERR_FAIL_COND_V(error_code < 0, ERR_CANT_OPEN); @@ -346,7 +346,7 @@ Error AudioDriverPulseAudio::init() { return ERR_CANT_OPEN; } - init_device(); + init_output_device(); thread.start(AudioDriverPulseAudio::thread_func, this); return OK; @@ -448,18 +448,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { } } - // User selected a new device, finish the current one so we'll init the new device - if (ad->device_name != ad->new_device) { - ad->device_name = ad->new_device; - ad->finish_device(); + // User selected a new output device, finish the current one so we'll init the new output device + if (ad->output_device_name != ad->new_output_device) { + ad->output_device_name = ad->new_output_device; + ad->finish_output_device(); - Error err = ad->init_device(); + Error err = ad->init_output_device(); if (err != OK) { - ERR_PRINT("PulseAudio: init_device error"); - ad->device_name = "Default"; - ad->new_device = "Default"; + ERR_PRINT("PulseAudio: init_output_device error"); + ad->output_device_name = "Default"; + ad->new_output_device = "Default"; - err = ad->init_device(); + err = ad->init_output_device(); if (err != OK) { ad->active.clear(); ad->exit_thread.set(); @@ -471,11 +471,11 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { write_ofs = 0; } - // If we're using the default device check that the current device is still the default - if (ad->device_name == "Default") { + // If we're using the default output device, check that the current output device is still the default + if (ad->output_device_name == "Default") { uint64_t msec = OS::get_singleton()->get_ticks_msec(); if (msec > (default_device_msec + 1000)) { - String old_default_device = ad->default_device; + String old_default_device = ad->default_output_device; default_device_msec = msec; @@ -494,12 +494,12 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { ERR_PRINT("pa_context_get_server_info error: " + String(pa_strerror(pa_context_errno(ad->pa_ctx)))); } - if (old_default_device != ad->default_device) { - ad->finish_device(); + if (old_default_device != ad->default_output_device) { + ad->finish_output_device(); - Error err = ad->init_device(); + Error err = ad->init_output_device(); if (err != OK) { - ERR_PRINT("PulseAudio: init_device error"); + ERR_PRINT("PulseAudio: init_output_device error"); ad->active.clear(); ad->exit_thread.set(); break; @@ -541,18 +541,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { } } - // User selected a new device, finish the current one so we'll init the new device - if (ad->capture_device_name != ad->capture_new_device) { - ad->capture_device_name = ad->capture_new_device; - ad->capture_finish_device(); + // User selected a new input device, finish the current one so we'll init the new input device + if (ad->input_device_name != ad->new_input_device) { + ad->input_device_name = ad->new_input_device; + ad->finish_input_device(); - Error err = ad->capture_init_device(); + Error err = ad->init_input_device(); if (err != OK) { - ERR_PRINT("PulseAudio: capture_init_device error"); - ad->capture_device_name = "Default"; - ad->capture_new_device = "Default"; + ERR_PRINT("PulseAudio: init_input_device error"); + ad->input_device_name = "Default"; + ad->new_input_device = "Default"; - err = ad->capture_init_device(); + err = ad->init_input_device(); if (err != OK) { ad->active.clear(); ad->exit_thread.set(); @@ -596,7 +596,7 @@ void AudioDriverPulseAudio::pa_sinklist_cb(pa_context *c, const pa_sink_info *l, ad->pa_status++; } -PackedStringArray AudioDriverPulseAudio::get_device_list() { +PackedStringArray AudioDriverPulseAudio::get_output_device_list() { pa_devices.clear(); pa_devices.push_back("Default"); @@ -606,7 +606,7 @@ PackedStringArray AudioDriverPulseAudio::get_device_list() { lock(); - // Get the device list + // Get the output device list pa_status = 0; pa_operation *pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, (void *)this); if (pa_op) { @@ -627,13 +627,13 @@ PackedStringArray AudioDriverPulseAudio::get_device_list() { return pa_devices; } -String AudioDriverPulseAudio::get_device() { - return device_name; +String AudioDriverPulseAudio::get_output_device() { + return output_device_name; } -void AudioDriverPulseAudio::set_device(String device) { +void AudioDriverPulseAudio::set_output_device(String output_device) { lock(); - new_device = device; + new_output_device = output_device; unlock(); } @@ -645,7 +645,7 @@ void AudioDriverPulseAudio::unlock() { mutex.unlock(); } -void AudioDriverPulseAudio::finish_device() { +void AudioDriverPulseAudio::finish_output_device() { if (pa_str) { pa_stream_disconnect(pa_str); pa_stream_unref(pa_str); @@ -661,7 +661,7 @@ void AudioDriverPulseAudio::finish() { exit_thread.set(); thread.wait_to_finish(); - finish_device(); + finish_output_device(); if (pa_ctx) { pa_context_disconnect(pa_ctx); @@ -675,13 +675,13 @@ void AudioDriverPulseAudio::finish() { } } -Error AudioDriverPulseAudio::capture_init_device() { - // If there is a specified device check that it is really present - if (capture_device_name != "Default") { - PackedStringArray list = capture_get_device_list(); - if (list.find(capture_device_name) == -1) { - capture_device_name = "Default"; - capture_new_device = "Default"; +Error AudioDriverPulseAudio::init_input_device() { + // If there is a specified input device, check that it is really present + if (input_device_name != "Default") { + PackedStringArray list = get_input_device_list(); + if (list.find(input_device_name) == -1) { + input_device_name = "Default"; + new_input_device = "Default"; } } @@ -718,7 +718,7 @@ Error AudioDriverPulseAudio::capture_init_device() { ERR_FAIL_V(ERR_CANT_OPEN); } - const char *dev = capture_device_name == "Default" ? nullptr : capture_device_name.utf8().get_data(); + const char *dev = input_device_name == "Default" ? nullptr : input_device_name.utf8().get_data(); pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); int error_code = pa_stream_connect_record(pa_rec_str, dev, &attr, flags); if (error_code < 0) { @@ -734,7 +734,7 @@ Error AudioDriverPulseAudio::capture_init_device() { return OK; } -void AudioDriverPulseAudio::capture_finish_device() { +void AudioDriverPulseAudio::finish_input_device() { if (pa_rec_str) { int ret = pa_stream_disconnect(pa_rec_str); if (ret != 0) { @@ -745,25 +745,25 @@ void AudioDriverPulseAudio::capture_finish_device() { } } -Error AudioDriverPulseAudio::capture_start() { +Error AudioDriverPulseAudio::input_start() { lock(); - Error err = capture_init_device(); + Error err = init_input_device(); unlock(); return err; } -Error AudioDriverPulseAudio::capture_stop() { +Error AudioDriverPulseAudio::input_stop() { lock(); - capture_finish_device(); + finish_input_device(); unlock(); return OK; } -void AudioDriverPulseAudio::capture_set_device(const String &p_name) { +void AudioDriverPulseAudio::set_input_device(const String &p_name) { lock(); - capture_new_device = p_name; + new_input_device = p_name; unlock(); } @@ -782,7 +782,7 @@ void AudioDriverPulseAudio::pa_sourcelist_cb(pa_context *c, const pa_source_info ad->pa_status++; } -PackedStringArray AudioDriverPulseAudio::capture_get_device_list() { +PackedStringArray AudioDriverPulseAudio::get_input_device_list() { pa_rec_devices.clear(); pa_rec_devices.push_back("Default"); @@ -813,9 +813,9 @@ PackedStringArray AudioDriverPulseAudio::capture_get_device_list() { return pa_rec_devices; } -String AudioDriverPulseAudio::capture_get_device() { +String AudioDriverPulseAudio::get_input_device() { lock(); - String name = capture_device_name; + String name = input_device_name; unlock(); return name; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 16398e67eb..68df03cb60 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -51,13 +51,13 @@ class AudioDriverPulseAudio : public AudioDriver { pa_channel_map pa_map = {}; pa_channel_map pa_rec_map = {}; - String device_name = "Default"; - String new_device = "Default"; - String default_device; + String output_device_name = "Default"; + String new_output_device = "Default"; + String default_output_device; - String capture_device_name; - String capture_new_device; - String capture_default_device; + String input_device_name; + String new_input_device; + String default_input_device; Vector<int32_t> samples_in; Vector<int16_t> samples_out; @@ -83,11 +83,11 @@ class AudioDriverPulseAudio : public AudioDriver { static void pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata); static void pa_sourcelist_cb(pa_context *c, const pa_source_info *l, int eol, void *userdata); - Error init_device(); - void finish_device(); + Error init_output_device(); + void finish_output_device(); - Error capture_init_device(); - void capture_finish_device(); + Error init_input_device(); + void finish_input_device(); Error detect_channels(bool capture = false); @@ -103,13 +103,13 @@ public: virtual int get_mix_rate() const; virtual SpeakerMode get_speaker_mode() const; - virtual PackedStringArray get_device_list(); - virtual String get_device(); - virtual void set_device(String device); + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(String output_device); - virtual PackedStringArray capture_get_device_list(); - virtual void capture_set_device(const String &p_name); - virtual String capture_get_device(); + virtual PackedStringArray get_input_device_list(); + virtual void set_input_device(const String &p_name); + virtual String get_input_device(); virtual void lock(); virtual void unlock(); @@ -117,8 +117,8 @@ public: virtual float get_latency(); - virtual Error capture_start(); - virtual Error capture_stop(); + virtual Error input_start(); + virtual Error input_stop(); AudioDriverPulseAudio(); ~AudioDriverPulseAudio() {} diff --git a/drivers/pulseaudio/pulse-so_wrap.c b/drivers/pulseaudio/pulse-so_wrap.c index 1765d7e7e6..8f477740ce 100644 --- a/drivers/pulseaudio/pulse-so_wrap.c +++ b/drivers/pulseaudio/pulse-so_wrap.c @@ -1,7 +1,7 @@ // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:26:29 -// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/pulse/pulseaudio.h --sys-include "thirdparty/linuxbsd_headers/pulse/pulseaudio.h" --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header ./drivers/pulseaudio/pulse-so_wrap.h --output-implementation ./drivers/pulseaudio/pulse-so_wrap.c +// generated by generate-wrapper.py 0.3 on 2023-01-12 10:26:29 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/pulse/pulseaudio.h --sys-include "thirdparty/linuxbsd_headers/pulse/pulseaudio.h" --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header ./drivers/pulseaudio/pulse-so_wrap.h --output-implementation ./drivers/pulseaudio/pulse-so_wrap.c // #include <stdint.h> diff --git a/drivers/pulseaudio/pulse-so_wrap.h b/drivers/pulseaudio/pulse-so_wrap.h index b3baf4c81a..bba8fd36a6 100644 --- a/drivers/pulseaudio/pulse-so_wrap.h +++ b/drivers/pulseaudio/pulse-so_wrap.h @@ -2,8 +2,8 @@ #define DYLIBLOAD_WRAPPER_PULSE // This file is generated. Do not edit! // see https://github.com/hpvb/dynload-wrapper for details -// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:26:29 -// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/pulse/pulseaudio.h --sys-include "thirdparty/linuxbsd_headers/pulse/pulseaudio.h" --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header ./drivers/pulseaudio/pulse-so_wrap.h --output-implementation ./drivers/pulseaudio/pulse-so_wrap.c +// generated by generate-wrapper.py 0.3 on 2023-01-12 10:26:29 +// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/pulse/pulseaudio.h --sys-include "thirdparty/linuxbsd_headers/pulse/pulseaudio.h" --soname libpulse.so.0 --omit-prefix _pa_ --init-name pulse --output-header ./drivers/pulseaudio/pulse-so_wrap.h --output-implementation ./drivers/pulseaudio/pulse-so_wrap.c // #include <stdint.h> diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index b2745b1e86..42a2b85200 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -118,8 +118,8 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient); #define CAPTURE_BUFFER_CHANNELS 2 -static bool default_render_device_changed = false; -static bool default_capture_device_changed = false; +static bool default_output_device_changed = false; +static bool default_input_device_changed = false; // Silence warning due to a COM API weirdness (GH-35194). #if defined(__GNUC__) && !defined(__clang__) @@ -181,9 +181,9 @@ public: HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) { if (role == eConsole) { if (flow == eRender) { - default_render_device_changed = true; + default_output_device_changed = true; } else if (flow == eCapture) { - default_capture_device_changed = true; + default_input_device_changed = true; } } @@ -201,10 +201,10 @@ public: static CMMNotificationClient notif_client; -Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool p_reinit, bool p_no_audio_client_3) { +Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_input, bool p_reinit, bool p_no_audio_client_3) { WAVEFORMATEX *pwfex; IMMDeviceEnumerator *enumerator = nullptr; - IMMDevice *device = nullptr; + IMMDevice *output_device = nullptr; CoInitialize(nullptr); @@ -212,11 +212,11 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); if (p_device->device_name == "Default") { - hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); + hr = enumerator->GetDefaultAudioEndpoint(p_input ? eCapture : eRender, eConsole, &output_device); } else { IMMDeviceCollection *devices = nullptr; - hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); + hr = enumerator->EnumAudioEndpoints(p_input ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); LPWSTR strId = nullptr; @@ -255,20 +255,20 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c } if (found) { - hr = enumerator->GetDevice(strId, &device); + hr = enumerator->GetDevice(strId, &output_device); } if (strId) { CoTaskMemFree(strId); } - if (device == nullptr) { - hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); + if (output_device == nullptr) { + hr = enumerator->GetDefaultAudioEndpoint(p_input ? eCapture : eRender, eConsole, &output_device); } } if (p_reinit) { - // In case we're trying to re-initialize the device prevent throwing this error on the console, + // In case we're trying to re-initialize the device, prevent throwing this error on the console, // otherwise if there is currently no device available this will spam the console. if (hr != S_OK) { return ERR_CANT_OPEN; @@ -284,28 +284,28 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error"); } - using_audio_client_3 = !p_capture; // IID_IAudioClient3 is only used for adjustable output latency (not input) + using_audio_client_3 = !p_input; // IID_IAudioClient3 is only used for adjustable output latency (not input) if (p_no_audio_client_3) { using_audio_client_3 = false; } if (using_audio_client_3) { - hr = device->Activate(IID_IAudioClient3, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); + hr = output_device->Activate(IID_IAudioClient3, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); if (hr != S_OK) { // IID_IAudioClient3 will never activate on OS versions before Windows 10. // Older Windows versions should fall back gracefully. using_audio_client_3 = false; - print_verbose("WASAPI: Couldn't activate device with IAudioClient3 interface, falling back to IAudioClient interface"); + print_verbose("WASAPI: Couldn't activate output_device with IAudioClient3 interface, falling back to IAudioClient interface"); } else { - print_verbose("WASAPI: Activated device using IAudioClient3 interface"); + print_verbose("WASAPI: Activated output_device using IAudioClient3 interface"); } } if (!using_audio_client_3) { - hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); + hr = output_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); } - SAFE_RELEASE(device) + SAFE_RELEASE(output_device) if (p_reinit) { if (hr != S_OK) { @@ -339,7 +339,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c WAVEFORMATEX *closest = nullptr; hr = p_device->audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, pwfex, &closest); if (hr == S_FALSE) { - WARN_PRINT("WASAPI: Mix format is not supported by the Device"); + WARN_PRINT("WASAPI: Mix format is not supported by the output_device"); if (closest) { print_verbose("WASAPI: closest->wFormatTag = " + itos(closest->wFormatTag)); print_verbose("WASAPI: closest->nChannels = " + itos(closest->nChannels)); @@ -385,14 +385,14 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c pwfex->nSamplesPerSec = mix_rate; pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8); } - hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr); + hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_input ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr); ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + "."); UINT32 max_frames; hr = p_device->audio_client->GetBufferSize(&max_frames); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Due to WASAPI Shared Mode we have no control of the buffer size - if (!p_capture) { + if (!p_input) { buffer_frames = max_frames; int64_t latency = 0; @@ -421,8 +421,8 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c if (hr != S_OK) { print_verbose("WASAPI: GetSharedModeEnginePeriod failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient."); CoTaskMemFree(pwfex); - SAFE_RELEASE(device) - return audio_device_init(p_device, p_capture, p_reinit, true); + SAFE_RELEASE(output_device) + return audio_device_init(p_device, p_input, p_reinit, true); } // Period frames must be an integral multiple of fundamental_period_frames or IAudioClient3 initialization will fail, @@ -443,8 +443,8 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c if (hr != S_OK) { print_verbose("WASAPI: InitializeSharedAudioStream failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient."); CoTaskMemFree(pwfex); - SAFE_RELEASE(device); - return audio_device_init(p_device, p_capture, p_reinit, true); + SAFE_RELEASE(output_device); + return audio_device_init(p_device, p_input, p_reinit, true); } else { uint32_t output_latency_in_frames; WAVEFORMATEX *current_pwfex; @@ -455,13 +455,13 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c } else { print_verbose("WASAPI: GetCurrentSharedModeEnginePeriod failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient."); CoTaskMemFree(pwfex); - SAFE_RELEASE(device); - return audio_device_init(p_device, p_capture, p_reinit, true); + SAFE_RELEASE(output_device); + return audio_device_init(p_device, p_input, p_reinit, true); } } } - if (p_capture) { + if (p_input) { hr = p_device->audio_client->GetService(IID_IAudioCaptureClient, (void **)&p_device->capture_client); } else { hr = p_device->audio_client->GetService(IID_IAudioRenderClient, (void **)&p_device->render_client); @@ -470,12 +470,12 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c // Free memory CoTaskMemFree(pwfex); - SAFE_RELEASE(device) + SAFE_RELEASE(output_device) return OK; } -Error AudioDriverWASAPI::init_render_device(bool p_reinit) { +Error AudioDriverWASAPI::init_output_device(bool p_reinit) { Error err = audio_device_init(&audio_output, false, p_reinit); if (err != OK) { return err; @@ -507,7 +507,7 @@ Error AudioDriverWASAPI::init_render_device(bool p_reinit) { return OK; } -Error AudioDriverWASAPI::init_capture_device(bool p_reinit) { +Error AudioDriverWASAPI::init_input_device(bool p_reinit) { Error err = audio_device_init(&audio_input, true, p_reinit); if (err != OK) { return err; @@ -538,11 +538,11 @@ Error AudioDriverWASAPI::audio_device_finish(AudioDeviceWASAPI *p_device) { return OK; } -Error AudioDriverWASAPI::finish_render_device() { +Error AudioDriverWASAPI::finish_output_device() { return audio_device_finish(&audio_output); } -Error AudioDriverWASAPI::finish_capture_device() { +Error AudioDriverWASAPI::finish_input_device() { return audio_device_finish(&audio_input); } @@ -551,9 +551,9 @@ Error AudioDriverWASAPI::init() { target_latency_ms = GLOBAL_GET("audio/driver/output_latency"); - Error err = init_render_device(); + Error err = init_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: init_render_device error"); + ERR_PRINT("WASAPI: init_output_device error"); } exit_thread.clear(); @@ -575,7 +575,7 @@ AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const { return get_speaker_mode_by_total_channels(channels); } -PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { +PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_input) { PackedStringArray list; IMMDeviceCollection *devices = nullptr; IMMDeviceEnumerator *enumerator = nullptr; @@ -587,7 +587,7 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator); ERR_FAIL_COND_V(hr != S_OK, PackedStringArray()); - hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); + hr = enumerator->EnumAudioEndpoints(p_input ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); ERR_FAIL_COND_V(hr != S_OK, PackedStringArray()); UINT count = 0; @@ -595,13 +595,13 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { ERR_FAIL_COND_V(hr != S_OK, PackedStringArray()); for (ULONG i = 0; i < count; i++) { - IMMDevice *device = nullptr; + IMMDevice *output_device = nullptr; - hr = devices->Item(i, &device); + hr = devices->Item(i, &output_device); ERR_BREAK(hr != S_OK); IPropertyStore *props = nullptr; - hr = device->OpenPropertyStore(STGM_READ, &props); + hr = output_device->OpenPropertyStore(STGM_READ, &props); ERR_BREAK(hr != S_OK); PROPVARIANT propvar; @@ -614,7 +614,7 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { PropVariantClear(&propvar); props->Release(); - device->Release(); + output_device->Release(); } devices->Release(); @@ -622,11 +622,11 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { return list; } -PackedStringArray AudioDriverWASAPI::get_device_list() { +PackedStringArray AudioDriverWASAPI::get_output_device_list() { return audio_device_get_list(false); } -String AudioDriverWASAPI::get_device() { +String AudioDriverWASAPI::get_output_device() { lock(); String name = audio_output.device_name; unlock(); @@ -634,9 +634,9 @@ String AudioDriverWASAPI::get_device() { return name; } -void AudioDriverWASAPI::set_device(String device) { +void AudioDriverWASAPI::set_output_device(String output_device) { lock(); - audio_output.new_device = device; + audio_output.new_device = output_device; unlock(); } @@ -769,13 +769,13 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { avail_frames -= write_frames; written_frames += write_frames; } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { - // Device is not valid anymore, reopen it + // output_device is not valid anymore, reopen it - Error err = ad->finish_render_device(); + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } else { - // We reopened the device and samples_in may have resized, so invalidate the current avail_frames + // We reopened the output device and samples_in may have resized, so invalidate the current avail_frames avail_frames = 0; } } else { @@ -790,37 +790,37 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { } if (invalidated) { - // Device is not valid anymore - WARN_PRINT("WASAPI: Current device invalidated, closing device"); + // output_device is not valid anymore + WARN_PRINT("WASAPI: Current output_device invalidated, closing output_device"); - Error err = ad->finish_render_device(); + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } } } - // If we're using the Default device and it changed finish it so we'll re-init the device - if (ad->audio_output.device_name == "Default" && default_render_device_changed) { - Error err = ad->finish_render_device(); + // If we're using the Default output device and it changed finish it so we'll re-init the output device + if (ad->audio_output.device_name == "Default" && default_output_device_changed) { + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } - default_render_device_changed = false; + default_output_device_changed = false; } - // User selected a new device, finish the current one so we'll init the new device + // User selected a new output device, finish the current one so we'll init the new output device if (ad->audio_output.device_name != ad->audio_output.new_device) { ad->audio_output.device_name = ad->audio_output.new_device; - Error err = ad->finish_render_device(); + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } } if (!ad->audio_output.audio_client) { - Error err = ad->init_render_device(true); + Error err = ad->init_output_device(true); if (err == OK) { ad->start(); } @@ -873,29 +873,29 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { } } - // If we're using the Default device and it changed finish it so we'll re-init the device - if (ad->audio_input.device_name == "Default" && default_capture_device_changed) { - Error err = ad->finish_capture_device(); + // If we're using the Default output device and it changed finish it so we'll re-init the output device + if (ad->audio_input.device_name == "Default" && default_input_device_changed) { + Error err = ad->finish_input_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_capture_device error"); + ERR_PRINT("WASAPI: finish_input_device error"); } - default_capture_device_changed = false; + default_input_device_changed = false; } - // User selected a new device, finish the current one so we'll init the new device + // User selected a new input device, finish the current one so we'll init the new input device if (ad->audio_input.device_name != ad->audio_input.new_device) { ad->audio_input.device_name = ad->audio_input.new_device; - Error err = ad->finish_capture_device(); + Error err = ad->finish_input_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_capture_device error"); + ERR_PRINT("WASAPI: finish_input_device error"); } } if (!ad->audio_input.audio_client) { - Error err = ad->init_capture_device(true); + Error err = ad->init_input_device(true); if (err == OK) { - ad->capture_start(); + ad->input_start(); } } } @@ -933,14 +933,14 @@ void AudioDriverWASAPI::finish() { exit_thread.set(); thread.wait_to_finish(); - finish_capture_device(); - finish_render_device(); + finish_input_device(); + finish_output_device(); } -Error AudioDriverWASAPI::capture_start() { - Error err = init_capture_device(); +Error AudioDriverWASAPI::input_start() { + Error err = init_input_device(); if (err != OK) { - ERR_PRINT("WASAPI: init_capture_device error"); + ERR_PRINT("WASAPI: init_input_device error"); return err; } @@ -953,7 +953,7 @@ Error AudioDriverWASAPI::capture_start() { return OK; } -Error AudioDriverWASAPI::capture_stop() { +Error AudioDriverWASAPI::input_stop() { if (audio_input.active.is_set()) { audio_input.audio_client->Stop(); audio_input.active.clear(); @@ -964,17 +964,17 @@ Error AudioDriverWASAPI::capture_stop() { return FAILED; } -void AudioDriverWASAPI::capture_set_device(const String &p_name) { +void AudioDriverWASAPI::set_input_device(const String &p_name) { lock(); audio_input.new_device = p_name; unlock(); } -PackedStringArray AudioDriverWASAPI::capture_get_device_list() { +PackedStringArray AudioDriverWASAPI::get_input_device_list() { return audio_device_get_list(true); } -String AudioDriverWASAPI::capture_get_device() { +String AudioDriverWASAPI::get_input_device() { lock(); String name = audio_input.device_name; unlock(); diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index 6eea24f78a..bf18ba8c99 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -47,8 +47,8 @@ class AudioDriverWASAPI : public AudioDriver { class AudioDeviceWASAPI { public: IAudioClient *audio_client = nullptr; - IAudioRenderClient *render_client = nullptr; - IAudioCaptureClient *capture_client = nullptr; + IAudioRenderClient *render_client = nullptr; // Output + IAudioCaptureClient *capture_client = nullptr; // Input SafeFlag active; WORD format_tag = 0; @@ -56,8 +56,8 @@ class AudioDriverWASAPI : public AudioDriver { unsigned int channels = 0; unsigned int frame_size = 0; - String device_name = "Default"; - String new_device = "Default"; + String device_name = "Default"; // Output OR Input + String new_device = "Default"; // Output OR Input AudioDeviceWASAPI() {} }; @@ -83,15 +83,15 @@ class AudioDriverWASAPI : public AudioDriver { static _FORCE_INLINE_ int32_t read_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i); static void thread_func(void *p_udata); - Error init_render_device(bool p_reinit = false); - Error init_capture_device(bool p_reinit = false); + Error init_output_device(bool p_reinit = false); + Error init_input_device(bool p_reinit = false); - Error finish_render_device(); - Error finish_capture_device(); + Error finish_output_device(); + Error finish_input_device(); - Error audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool p_reinit, bool p_no_audio_client_3 = false); + Error audio_device_init(AudioDeviceWASAPI *p_device, bool p_input, bool p_reinit, bool p_no_audio_client_3 = false); Error audio_device_finish(AudioDeviceWASAPI *p_device); - PackedStringArray audio_device_get_list(bool p_capture); + PackedStringArray audio_device_get_list(bool p_input); public: virtual const char *get_name() const { @@ -103,18 +103,18 @@ public: virtual int get_mix_rate() const; virtual float get_latency(); virtual SpeakerMode get_speaker_mode() const; - virtual PackedStringArray get_device_list(); - virtual String get_device(); - virtual void set_device(String device); + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(String output_device); virtual void lock(); virtual void unlock(); virtual void finish(); - virtual Error capture_start(); - virtual Error capture_stop(); - virtual PackedStringArray capture_get_device_list(); - virtual void capture_set_device(const String &p_name); - virtual String capture_get_device(); + virtual Error input_start(); + virtual Error input_stop(); + virtual PackedStringArray get_input_device_list(); + virtual void set_input_device(const String &p_name); + virtual String get_input_device(); AudioDriverWASAPI(); }; |