summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/SCsub5
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp90
-rw-r--r--drivers/alsa/audio_driver_alsa.h1
-rw-r--r--drivers/alsamidi/SCsub8
-rw-r--r--drivers/alsamidi/alsa_midi.cpp201
-rw-r--r--drivers/alsamidi/alsa_midi.h69
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp7
-rw-r--r--drivers/coremidi/SCsub8
-rw-r--r--drivers/coremidi/core_midi.cpp105
-rw-r--r--drivers/coremidi/core_midi.h61
-rw-r--r--drivers/dummy/rasterizer_dummy.h1
-rw-r--r--drivers/dummy/texture_loader_dummy.cpp4
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp12
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp2
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp14
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h8
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp10
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp16
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp14
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h3
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp14
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h4
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp9
-rw-r--r--drivers/gles3/shaders/scene.glsl73
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp21
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp4
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp68
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h1
-rw-r--r--drivers/windows/file_access_windows.cpp6
-rw-r--r--drivers/winmidi/SCsub8
-rw-r--r--drivers/winmidi/win_midi.cpp100
-rw-r--r--drivers/winmidi/win_midi.h61
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.cpp4
33 files changed, 839 insertions, 173 deletions
diff --git a/drivers/SCsub b/drivers/SCsub
index 2c5e9434e8..f9cfa3fb05 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -21,6 +21,11 @@ if (env["platform"] == "windows"):
if env['xaudio2']:
SConscript("xaudio2/SCsub")
+# Midi drivers
+SConscript('alsamidi/SCsub')
+SConscript('coremidi/SCsub')
+SConscript('winmidi/SCsub')
+
# Graphics drivers
if (env["platform"] != "server"):
SConscript('gles3/SCsub')
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 1e17e72532..08005efa9d 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -58,7 +58,10 @@ Error AudioDriverALSA::init_device() {
#define CHECK_FAIL(m_cond) \
if (m_cond) { \
fprintf(stderr, "ALSA ERR: %s\n", snd_strerror(status)); \
- snd_pcm_close(pcm_handle); \
+ if (pcm_handle) { \
+ snd_pcm_close(pcm_handle); \
+ pcm_handle = NULL; \
+ } \
ERR_FAIL_COND_V(m_cond, ERR_CANT_OPEN); \
}
@@ -142,8 +145,6 @@ Error AudioDriverALSA::init_device() {
samples_in.resize(period_size * channels);
samples_out.resize(period_size * channels);
- snd_pcm_nonblock(pcm_handle, 0);
-
return OK;
}
@@ -152,7 +153,6 @@ Error AudioDriverALSA::init() {
active = false;
thread_exited = false;
exit_thread = false;
- pcm_open = false;
Error err = init_device();
if (err == OK) {
@@ -168,54 +168,50 @@ void AudioDriverALSA::thread_func(void *p_udata) {
AudioDriverALSA *ad = (AudioDriverALSA *)p_udata;
while (!ad->exit_thread) {
+
+ ad->lock();
+ ad->start_counting_ticks();
+
if (!ad->active) {
for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) {
ad->samples_out[i] = 0;
- };
- } else {
- ad->lock();
+ }
+ } else {
ad->audio_server_process(ad->period_size, ad->samples_in.ptrw());
- ad->unlock();
-
for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) {
ad->samples_out[i] = ad->samples_in[i] >> 16;
}
- };
+ }
int todo = ad->period_size;
int total = 0;
- while (todo) {
- if (ad->exit_thread)
- break;
+ while (todo && !ad->exit_thread) {
uint8_t *src = (uint8_t *)ad->samples_out.ptr();
int wrote = snd_pcm_writei(ad->pcm_handle, (void *)(src + (total * ad->channels)), todo);
- if (wrote < 0) {
- if (ad->exit_thread)
- break;
+ if (wrote > 0) {
+ total += wrote;
+ todo -= wrote;
+ } else if (wrote == -EAGAIN) {
+ ad->stop_counting_ticks();
+ ad->unlock();
- if (wrote == -EAGAIN) {
- //can't write yet (though this is blocking..)
- usleep(1000);
- continue;
- }
+ OS::get_singleton()->delay_usec(1000);
+
+ ad->lock();
+ ad->start_counting_ticks();
+ } else {
wrote = snd_pcm_recover(ad->pcm_handle, wrote, 0);
if (wrote < 0) {
- //absolute fail
- fprintf(stderr, "ALSA failed and can't recover: %s\n", snd_strerror(wrote));
+ ERR_PRINTS("ALSA: Failed and can't recover: " + String(snd_strerror(wrote)));
ad->active = false;
ad->exit_thread = true;
- break;
}
- continue;
- };
-
- total += wrote;
- todo -= wrote;
- };
+ }
+ }
// User selected a new device, finish the current one so we'll init the new device
if (ad->device_name != ad->new_device) {
@@ -232,10 +228,12 @@ void AudioDriverALSA::thread_func(void *p_udata) {
if (err != OK) {
ad->active = false;
ad->exit_thread = true;
- break;
}
}
}
+
+ ad->stop_counting_ticks();
+ ad->unlock();
};
ad->thread_exited = true;
@@ -296,7 +294,9 @@ String AudioDriverALSA::get_device() {
void AudioDriverALSA::set_device(String device) {
+ lock();
new_device = device;
+ unlock();
}
void AudioDriverALSA::lock() {
@@ -315,29 +315,29 @@ void AudioDriverALSA::unlock() {
void AudioDriverALSA::finish_device() {
- if (pcm_open) {
+ if (pcm_handle) {
snd_pcm_close(pcm_handle);
- pcm_open = NULL;
+ pcm_handle = NULL;
}
}
void AudioDriverALSA::finish() {
- if (!thread)
- return;
-
- exit_thread = true;
- Thread::wait_to_finish(thread);
+ if (thread) {
+ exit_thread = true;
+ Thread::wait_to_finish(thread);
- finish_device();
+ memdelete(thread);
+ thread = NULL;
- memdelete(thread);
- if (mutex) {
- memdelete(mutex);
- mutex = NULL;
+ if (mutex) {
+ memdelete(mutex);
+ mutex = NULL;
+ }
}
- thread = NULL;
-};
+
+ finish_device();
+}
AudioDriverALSA::AudioDriverALSA() {
diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h
index 2878e100a2..e2a2325cf3 100644
--- a/drivers/alsa/audio_driver_alsa.h
+++ b/drivers/alsa/audio_driver_alsa.h
@@ -66,7 +66,6 @@ class AudioDriverALSA : public AudioDriver {
bool active;
bool thread_exited;
mutable bool exit_thread;
- bool pcm_open;
public:
const char *get_name() const {
diff --git a/drivers/alsamidi/SCsub b/drivers/alsamidi/SCsub
new file mode 100644
index 0000000000..233593b0f9
--- /dev/null
+++ b/drivers/alsamidi/SCsub
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+Import('env')
+
+# Driver source files
+env.add_source_files(env.drivers_sources, "*.cpp")
+
+Export('env')
diff --git a/drivers/alsamidi/alsa_midi.cpp b/drivers/alsamidi/alsa_midi.cpp
new file mode 100644
index 0000000000..599470d7e0
--- /dev/null
+++ b/drivers/alsamidi/alsa_midi.cpp
@@ -0,0 +1,201 @@
+/*************************************************************************/
+/* alsa_midi.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef ALSAMIDI_ENABLED
+
+#include <errno.h>
+
+#include "alsa_midi.h"
+#include "os/os.h"
+#include "print_string.h"
+
+static int get_message_size(uint8_t message) {
+ switch (message & 0xF0) {
+ case 0x80: // note off
+ case 0x90: // note on
+ case 0xA0: // aftertouch
+ case 0xB0: // continuous controller
+ return 3;
+
+ case 0xC0: // patch change
+ case 0xD0: // channel pressure
+ case 0xE0: // pitch bend
+ return 2;
+ }
+
+ return 256;
+}
+
+void MIDIDriverALSAMidi::thread_func(void *p_udata) {
+ MIDIDriverALSAMidi *md = (MIDIDriverALSAMidi *)p_udata;
+ uint64_t timestamp = 0;
+ uint8_t buffer[256];
+ int expected_size = 255;
+ int bytes = 0;
+
+ while (!md->exit_thread) {
+ int ret;
+
+ md->lock();
+
+ for (int i = 0; i < md->connected_inputs.size(); i++) {
+ snd_rawmidi_t *midi_in = md->connected_inputs[i];
+ do {
+ uint8_t byte = 0;
+ ret = snd_rawmidi_read(midi_in, &byte, 1);
+ if (ret < 0) {
+ if (ret != -EAGAIN) {
+ ERR_PRINTS("snd_rawmidi_read error: " + String(snd_strerror(ret)));
+ }
+ } else {
+ if (byte & 0x80) {
+ // Flush previous packet if there is any
+ if (bytes) {
+ md->receive_input_packet(timestamp, buffer, bytes);
+ bytes = 0;
+ }
+ expected_size = get_message_size(byte);
+ }
+
+ if (bytes < 256) {
+ buffer[bytes++] = byte;
+ // If we know the size of the current packet receive it if it reached the expected size
+ if (bytes >= expected_size) {
+ md->receive_input_packet(timestamp, buffer, bytes);
+ bytes = 0;
+ }
+ }
+ }
+ } while (ret > 0);
+ }
+
+ md->unlock();
+
+ OS::get_singleton()->delay_usec(1000);
+ }
+}
+
+Error MIDIDriverALSAMidi::open() {
+
+ void **hints;
+
+ if (snd_device_name_hint(-1, "rawmidi", &hints) < 0)
+ return ERR_CANT_OPEN;
+
+ int i = 0;
+ for (void **n = hints; *n != NULL; n++) {
+ char *name = snd_device_name_get_hint(*n, "NAME");
+
+ if (name != NULL) {
+ snd_rawmidi_t *midi_in;
+ int ret = snd_rawmidi_open(&midi_in, NULL, name, SND_RAWMIDI_NONBLOCK);
+ if (ret >= 0) {
+ connected_inputs.insert(i++, midi_in);
+ }
+ }
+
+ if (name != NULL)
+ free(name);
+ }
+ snd_device_name_free_hint(hints);
+
+ mutex = Mutex::create();
+ thread = Thread::create(MIDIDriverALSAMidi::thread_func, this);
+
+ return OK;
+}
+
+void MIDIDriverALSAMidi::close() {
+
+ if (thread) {
+ exit_thread = true;
+ Thread::wait_to_finish(thread);
+
+ memdelete(thread);
+ thread = NULL;
+ }
+
+ if (mutex) {
+ memdelete(mutex);
+ mutex = NULL;
+ }
+
+ for (int i = 0; i < connected_inputs.size(); i++) {
+ snd_rawmidi_t *midi_in = connected_inputs[i];
+ snd_rawmidi_close(midi_in);
+ }
+ connected_inputs.clear();
+}
+
+void MIDIDriverALSAMidi::lock() const {
+
+ if (mutex)
+ mutex->lock();
+}
+
+void MIDIDriverALSAMidi::unlock() const {
+
+ if (mutex)
+ mutex->unlock();
+}
+
+PoolStringArray MIDIDriverALSAMidi::get_connected_inputs() {
+
+ PoolStringArray list;
+
+ lock();
+ for (int i = 0; i < connected_inputs.size(); i++) {
+ snd_rawmidi_t *midi_in = connected_inputs[i];
+ snd_rawmidi_info_t *info;
+
+ snd_rawmidi_info_malloc(&info);
+ snd_rawmidi_info(midi_in, info);
+ list.push_back(snd_rawmidi_info_get_name(info));
+ snd_rawmidi_info_free(info);
+ }
+ unlock();
+
+ return list;
+}
+
+MIDIDriverALSAMidi::MIDIDriverALSAMidi() {
+
+ mutex = NULL;
+ thread = NULL;
+
+ exit_thread = false;
+}
+
+MIDIDriverALSAMidi::~MIDIDriverALSAMidi() {
+
+ close();
+}
+
+#endif
diff --git a/drivers/alsamidi/alsa_midi.h b/drivers/alsamidi/alsa_midi.h
new file mode 100644
index 0000000000..90e458a365
--- /dev/null
+++ b/drivers/alsamidi/alsa_midi.h
@@ -0,0 +1,69 @@
+/*************************************************************************/
+/* alsa_midi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef ALSAMIDI_ENABLED
+
+#ifndef ALSA_MIDI_H
+#define ALSA_MIDI_H
+
+#include <alsa/asoundlib.h>
+#include <stdio.h>
+
+#include "core/os/mutex.h"
+#include "core/os/thread.h"
+#include "core/vector.h"
+#include "os/midi_driver.h"
+
+class MIDIDriverALSAMidi : public MIDIDriver {
+
+ Thread *thread;
+ Mutex *mutex;
+
+ Vector<snd_rawmidi_t *> connected_inputs;
+
+ bool exit_thread;
+
+ static void thread_func(void *p_udata);
+
+ void lock() const;
+ void unlock() const;
+
+public:
+ virtual Error open();
+ virtual void close();
+
+ virtual PoolStringArray get_connected_inputs();
+
+ MIDIDriverALSAMidi();
+ virtual ~MIDIDriverALSAMidi();
+};
+
+#endif
+#endif
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index ef7858b4ca..ac21de91e4 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -102,7 +102,7 @@ Error AudioDriverCoreAudio::init() {
break;
}
- mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
zeromem(&strdesc, sizeof(strdesc));
strdesc.mFormatID = kAudioFormatLinearPCM;
@@ -117,7 +117,7 @@ Error AudioDriverCoreAudio::init() {
result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc));
ERR_FAIL_COND_V(result != noErr, FAILED);
- int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
@@ -163,6 +163,8 @@ OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon,
return 0;
};
+ ad->start_counting_ticks();
+
for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
AudioBuffer *abuf = &ioData->mBuffers[i];
@@ -184,6 +186,7 @@ OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon,
};
};
+ ad->stop_counting_ticks();
ad->unlock();
return 0;
diff --git a/drivers/coremidi/SCsub b/drivers/coremidi/SCsub
new file mode 100644
index 0000000000..233593b0f9
--- /dev/null
+++ b/drivers/coremidi/SCsub
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+Import('env')
+
+# Driver source files
+env.add_source_files(env.drivers_sources, "*.cpp")
+
+Export('env')
diff --git a/drivers/coremidi/core_midi.cpp b/drivers/coremidi/core_midi.cpp
new file mode 100644
index 0000000000..3619be4a8e
--- /dev/null
+++ b/drivers/coremidi/core_midi.cpp
@@ -0,0 +1,105 @@
+/*************************************************************************/
+/* core_midi.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef COREMIDI_ENABLED
+
+#include "core_midi.h"
+#include "print_string.h"
+
+#include <CoreAudio/HostTime.h>
+#include <CoreServices/CoreServices.h>
+
+void MIDIDriverCoreMidi::read(const MIDIPacketList *packet_list, void *read_proc_ref_con, void *src_conn_ref_con) {
+ MIDIPacket *packet = const_cast<MIDIPacket *>(packet_list->packet);
+ for (int i = 0; i < packet_list->numPackets; i++) {
+ receive_input_packet(packet->timeStamp, packet->data, packet->length);
+ packet = MIDIPacketNext(packet);
+ }
+}
+
+Error MIDIDriverCoreMidi::open() {
+
+ CFStringRef name = CFStringCreateWithCString(NULL, "Godot", kCFStringEncodingASCII);
+ OSStatus result = MIDIClientCreate(name, NULL, NULL, &client);
+ CFRelease(name);
+ if (result != noErr) {
+ ERR_PRINTS("MIDIClientCreate failed: " + String(GetMacOSStatusErrorString(result)));
+ return ERR_CANT_OPEN;
+ }
+
+ result = MIDIInputPortCreate(client, CFSTR("Godot Input"), MIDIDriverCoreMidi::read, (void *)this, &port_in);
+ if (result != noErr) {
+ ERR_PRINTS("MIDIInputPortCreate failed: " + String(GetMacOSStatusErrorString(result)));
+ return ERR_CANT_OPEN;
+ }
+
+ int sources = MIDIGetNumberOfSources();
+ for (int i = 0; i < sources; i++) {
+
+ MIDIEndpointRef source = MIDIGetSource(i);
+ if (source != NULL) {
+ MIDIPortConnectSource(port_in, source, (void *)this);
+ connected_sources.insert(i, source);
+ }
+ }
+
+ return OK;
+}
+
+void MIDIDriverCoreMidi::close() {
+
+ for (int i = 0; i < connected_sources.size(); i++) {
+ MIDIEndpointRef source = connected_sources[i];
+ MIDIPortDisconnectSource(port_in, source);
+ }
+ connected_sources.clear();
+
+ if (port_in != 0) {
+ MIDIPortDispose(port_in);
+ port_in = 0;
+ }
+
+ if (client != 0) {
+ MIDIClientDispose(client);
+ client = 0;
+ }
+}
+
+MIDIDriverCoreMidi::MIDIDriverCoreMidi() {
+
+ client = 0;
+}
+
+MIDIDriverCoreMidi::~MIDIDriverCoreMidi() {
+
+ close();
+}
+
+#endif
diff --git a/drivers/coremidi/core_midi.h b/drivers/coremidi/core_midi.h
new file mode 100644
index 0000000000..fd35e12f4b
--- /dev/null
+++ b/drivers/coremidi/core_midi.h
@@ -0,0 +1,61 @@
+/*************************************************************************/
+/* core_midi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef COREMIDI_ENABLED
+
+#ifndef CORE_MIDI_H
+#define CORE_MIDI_H
+
+#include <stdio.h>
+
+#include <CoreMIDI/CoreMIDI.h>
+
+#include "core/vector.h"
+#include "os/midi_driver.h"
+
+class MIDIDriverCoreMidi : public MIDIDriver {
+
+ MIDIClientRef client;
+ MIDIPortRef port_in;
+
+ Vector<MIDIEndpointRef> connected_sources;
+
+ static void read(const MIDIPacketList *packet_list, void *read_proc_ref_con, void *src_conn_ref_con);
+
+public:
+ virtual Error open();
+ virtual void close();
+
+ MIDIDriverCoreMidi();
+ virtual ~MIDIDriverCoreMidi();
+};
+
+#endif
+#endif
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index 068a14cb8a..bab89f649a 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -235,6 +235,7 @@ public:
void textures_keep_original(bool p_enable) {}
void texture_set_proxy(RID p_proxy, RID p_base) {}
+ void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {}
/* SKY API */
diff --git a/drivers/dummy/texture_loader_dummy.cpp b/drivers/dummy/texture_loader_dummy.cpp
index 6d3e176bbb..b099019d17 100644
--- a/drivers/dummy/texture_loader_dummy.cpp
+++ b/drivers/dummy/texture_loader_dummy.cpp
@@ -45,10 +45,6 @@ RES ResourceFormatDummyTexture::load(const String &p_path, const String &p_origi
dstbuff.resize(rowsize * height);
- PoolVector<uint8_t>::Write dstbuff_write = dstbuff.write();
-
- uint8_t *data = dstbuff_write.ptr();
-
uint8_t **row_p = memnew_arr(uint8_t *, height);
for (unsigned int i = 0; i < height; i++) {
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index d5232a6511..fb150d6820 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -140,6 +140,10 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
texture = texture->get_ptr();
+ if (texture->redraw_if_visible) {
+ VisualServerRaster::redraw_request();
+ }
+
if (texture->render_target) {
texture->render_target->used_in_frame = true;
}
@@ -405,8 +409,6 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
Rect2 dst_rect = Rect2(r->rect.position, r->rect.size);
- state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
-
if (dst_rect.size.width < 0) {
dst_rect.position.x += dst_rect.size.width;
dst_rect.size.width *= -1;
@@ -659,6 +661,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (state.canvas_shader.bind())
_set_uniforms();
+ _bind_canvas_texture(RID(), RID());
+
if (pline->triangles.size()) {
_draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1);
} else {
@@ -909,6 +913,10 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
t = t->get_ptr();
+ if (t->redraw_if_visible) {
+ VisualServerRaster::redraw_request();
+ }
+
glBindTexture(t->target, t->tex_id);
}
} else {
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index ab48e682d6..9ea20ff15a 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -203,7 +203,7 @@ void RasterizerGLES2::initialize() {
#endif // GLAD_ENABLED
- // For debugging
+ // For debugging
#ifdef GLES_OVER_GL
if (GLAD_GL_ARB_debug_output) {
glDebugMessageControlARB(_EXT_DEBUG_SOURCE_API_ARB, _EXT_DEBUG_TYPE_ERROR_ARB, _EXT_DEBUG_SEVERITY_HIGH_ARB, 0, NULL, GL_TRUE);
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index ca39531b0d..0dc506d991 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -674,6 +674,14 @@ void RasterizerStorageGLES2::texture_set_proxy(RID p_texture, RID p_proxy) {
}
}
+void RasterizerStorageGLES2::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
+
+ Texture *texture = texture_owner.getornull(p_texture);
+ ERR_FAIL_COND(!texture);
+
+ texture->redraw_if_visible = p_enable;
+}
+
void RasterizerStorageGLES2::texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) {
// TODO
}
@@ -1182,7 +1190,7 @@ RID RasterizerStorageGLES2::multimesh_create() {
return RID();
}
-void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format,VS::MultimeshCustomDataFormat p_data) {
+void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data) {
}
int RasterizerStorageGLES2::multimesh_get_instance_count(RID p_multimesh) const {
@@ -1225,8 +1233,6 @@ Color RasterizerStorageGLES2::multimesh_instance_get_custom_data(RID p_multimesh
}
void RasterizerStorageGLES2::multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) {
-
-
}
void RasterizerStorageGLES2::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
@@ -1999,6 +2005,8 @@ void RasterizerStorageGLES2::initialize() {
}
}
+ config.shrink_textures_x2 = false;
+
frame.count = 0;
frame.prev_tick = 0;
frame.delta = 0;
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index df8c2fcf47..30e13a9f65 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -182,6 +182,8 @@ public:
Ref<Image> images[6];
+ bool redraw_if_visible;
+
Texture() {
flags = 0;
width = 0;
@@ -205,6 +207,8 @@ public:
proxy = NULL;
render_target = NULL;
+
+ redraw_if_visible = false;
}
_ALWAYS_INLINE_ Texture *get_ptr() {
@@ -264,6 +268,8 @@ public:
virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable);
+
/* SKY API */
virtual RID sky_create();
@@ -508,7 +514,7 @@ public:
virtual RID multimesh_create();
- virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format,VS::MultimeshCustomDataFormat p_data=VS::MULTIMESH_CUSTOM_DATA_NONE);
+ virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE);
virtual int multimesh_get_instance_count(RID p_multimesh) const;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index aa55e72083..549d91a5a0 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -721,8 +721,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth";
- actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
- actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture";
@@ -736,7 +734,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height";
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color";
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv";
- //actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_SHADOW_COLOR"]="light_shadow_color";
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light";
actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color";
@@ -768,7 +765,8 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp";
actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp";
actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
- //actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"]=ShaderLanguage::TYPE_INT;
+ // gl_InstanceID is not available in OpenGL ES 2.0
+ actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "0";
//builtins
@@ -790,13 +788,11 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
- //actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread";
actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission";
actions[VS::SHADER_SPATIAL].renames["AO"] = "ao";
actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission";
- //actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord";
actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom";
actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv";
@@ -838,8 +834,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
- actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
-
actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index f214943bcf..5e13bed198 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -211,6 +211,10 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
} else {
+ if (texture->redraw_if_visible) { //check before proxy, because this is usually used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
texture = texture->get_ptr();
if (texture->render_target)
@@ -248,6 +252,10 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con
} else {
+ if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
normal_map = normal_map->get_ptr();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normal_map->tex_id);
@@ -1266,6 +1274,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
continue;
}
+ if (t->redraw_if_visible) { //check before proxy, because this is usually used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
t = t->get_ptr();
if (storage->config.srgb_decode_supported && t->using_srgb) {
@@ -1883,7 +1895,7 @@ void RasterizerCanvasGLES3::initialize() {
}
{
- uint32_t poly_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128);
+ uint32_t poly_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128);
poly_size *= 1024; //kb
poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float));
glGenBuffers(1, &data.polygon_buffer);
@@ -1930,7 +1942,7 @@ void RasterizerCanvasGLES3::initialize() {
glGenVertexArrays(1, &data.polygon_buffer_pointer_array);
- uint32_t index_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", 128);
+ uint32_t index_size = GLOBAL_DEF_RST("rendering/limits/buffers/canvas_polygon_index_buffer_size_kb", 128);
index_size *= 1024; //kb
glGenBuffers(1, &data.polygon_index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 7c2af755cd..2b7cea8508 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1225,7 +1225,12 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
} else {
+ if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
t = t->get_ptr(); //resolve for proxies
+
#ifdef TOOLS_ENABLED
if (t->detect_3d) {
t->detect_3d(t->detect_3d_ud);
@@ -1569,6 +1574,11 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(c.texture);
t = t->get_ptr(); //resolve for proxies
+
+ if (t->redraw_if_visible) {
+ VisualServerRaster::redraw_request();
+ }
+
#ifdef TOOLS_ENABLED
if (t->detect_3d) {
t->detect_3d(t->detect_3d_ud);
@@ -4076,6 +4086,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
state.ubo_data.z_slope_scale = 0;
state.ubo_data.shadow_dual_paraboloid_render_side = 0;
state.ubo_data.shadow_dual_paraboloid_render_zfar = 0;
+ state.ubo_data.opaque_prepass_threshold = 0.99;
p_cam_projection.get_viewport_size(state.ubo_data.viewport_size[0], state.ubo_data.viewport_size[1]);
@@ -4688,6 +4699,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_
state.ubo_data.z_slope_scale = normal_bias;
state.ubo_data.shadow_dual_paraboloid_render_side = dp_direction;
state.ubo_data.shadow_dual_paraboloid_render_zfar = zfar;
+ state.ubo_data.opaque_prepass_threshold = 0.1;
_setup_environment(NULL, light_projection, light_transform);
@@ -4856,7 +4868,7 @@ void RasterizerSceneGLES3::initialize() {
glBufferData(GL_UNIFORM_BUFFER, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_ubo, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
- render_list.max_elements = GLOBAL_DEF("rendering/limits/rendering/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS);
+ render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)RenderList::DEFAULT_MAX_ELEMENTS);
if (render_list.max_elements > 1000000)
render_list.max_elements = 1000000;
if (render_list.max_elements < 1024)
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 524212b9c1..cf387a69bc 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -141,6 +141,7 @@ public:
float subsurface_scatter_width;
float ambient_occlusion_affect_light;
float ambient_occlusion_affect_ssao;
+ float opaque_prepass_threshold;
uint32_t fog_depth_enabled;
float fog_depth_begin;
@@ -152,7 +153,7 @@ public:
float fog_height_max;
float fog_height_curve;
// make sure this struct is padded to be a multiple of 16 bytes for webgl
- float pad[3];
+ float pad[2];
} ubo_data;
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 4a3ebf7a7c..9e389a353e 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1328,6 +1328,13 @@ void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) {
}
}
+void RasterizerStorageGLES3::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
+
+ Texture *texture = texture_owner.get(p_texture);
+ ERR_FAIL_COND(!texture);
+ texture->redraw_if_visible = p_enable;
+}
+
RID RasterizerStorageGLES3::sky_create() {
Sky *sky = memnew(Sky);
@@ -3233,7 +3240,7 @@ void RasterizerStorageGLES3::mesh_surface_update_region(RID p_mesh, int p_surfac
PoolVector<uint8_t>::Read r = p_data.read();
- glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->array_id);
+ glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaces[p_surface]->vertex_id);
glBufferSubData(GL_ARRAY_BUFFER, p_offset, total_size, r.ptr());
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
}
@@ -3397,6 +3404,7 @@ Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shap
return bsarr;
}
+
Vector<AABB> RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
@@ -3448,6 +3456,7 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface) {
mesh->instance_change_notify();
}
+
int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
@@ -3461,6 +3470,7 @@ void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb
ERR_FAIL_COND(!mesh);
mesh->custom_aabb = p_aabb;
+ mesh->instance_change_notify();
}
AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const {
@@ -7456,7 +7466,7 @@ void RasterizerStorageGLES3::initialize() {
{
//transform feedback buffers
- uint32_t xf_feedback_size = GLOBAL_DEF("rendering/limits/buffers/blend_shape_max_buffer_size_kb", 4096);
+ uint32_t xf_feedback_size = GLOBAL_DEF_RST("rendering/limits/buffers/blend_shape_max_buffer_size_kb", 4096);
for (int i = 0; i < 2; i++) {
glGenBuffers(1, &resources.transform_feedback_buffers[i]);
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 7a2d56f69b..1db577f23c 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -268,6 +268,7 @@ public:
GLuint tex_id;
bool using_srgb;
+ bool redraw_if_visible;
uint16_t stored_cube_sides;
@@ -306,6 +307,7 @@ public:
detect_normal = NULL;
detect_normal_ud = NULL;
proxy = NULL;
+ redraw_if_visible = false;
}
_ALWAYS_INLINE_ Texture *get_ptr() {
@@ -366,6 +368,7 @@ public:
virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata);
virtual void texture_set_proxy(RID p_texture, RID p_proxy);
+ virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable);
/* SKY API */
@@ -690,7 +693,6 @@ public:
AABB custom_aabb;
mutable uint64_t last_pass;
SelfList<MultiMesh>::List multimeshes;
-
_FORCE_INLINE_ void update_multimeshes() {
SelfList<MultiMesh> *mm = multimeshes.first();
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 9ad16ac2a2..f3ba7aa408 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -780,8 +780,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth";
- actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
- actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture";
@@ -824,7 +822,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp";
actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp";
actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
- //actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"]=ShaderLanguage::TYPE_INT;
+ actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID";
//builtins
@@ -846,13 +844,11 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy";
actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
- //actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread";
actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission";
actions[VS::SHADER_SPATIAL].renames["AO"] = "ao";
actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission";
- //actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord";
actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom";
actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv";
@@ -894,8 +890,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
- actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
-
actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n";
@@ -913,6 +907,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
/* PARTICLES SHADER */
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index ed8df04377..6fd85cc1dd 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -91,6 +91,7 @@ layout(std140) uniform SceneData { //ubo:0
mediump float subsurface_scatter_width;
mediump float ambient_occlusion_affect_light;
mediump float ambient_occlusion_affect_ao_channel;
+ mediump float opaque_prepass_threshold;
bool fog_depth_enabled;
highp float fog_depth_begin;
@@ -571,11 +572,6 @@ in vec3 normal_interp;
/* PBR CHANNELS */
-//used on forward mainly
-uniform bool no_ambient_light;
-
-
-
#ifdef USE_RADIANCE_MAP
@@ -684,6 +680,7 @@ layout(std140) uniform SceneData {
mediump float subsurface_scatter_width;
mediump float ambient_occlusion_affect_light;
mediump float ambient_occlusion_affect_ao_channel;
+ mediump float opaque_prepass_threshold;
bool fog_depth_enabled;
highp float fog_depth_begin;
@@ -1031,12 +1028,11 @@ LIGHT_SHADER_CODE
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
-#if defined(TRANSMISSION_USED)
- diffuse_light += light_color * diffuse_color * mix(vec3(diffuse_brdf_NL), vec3(M_PI), transmission) * attenuation;
-#else
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
-#endif
+#if defined(TRANSMISSION_USED)
+ diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
+#endif
#if defined(LIGHT_USE_RIM)
@@ -1633,7 +1629,7 @@ void main() {
float alpha = 1.0;
#if defined(DO_SIDE_CHECK)
- float side=float(gl_FrontFacing)*2.0-1.0;
+ float side=gl_FrontFacing ? 1.0 : -1.0;
#else
float side=1.0;
#endif
@@ -1695,9 +1691,10 @@ FRAGMENT_SHADER_CODE
#ifdef USE_OPAQUE_PREPASS
- if (alpha<0.99) {
+ if (alpha<opaque_prepass_threshold) {
discard;
}
+
#endif
#if defined(ENABLE_NORMALMAP)
@@ -1752,42 +1749,43 @@ FRAGMENT_SHADER_CODE
#ifdef USE_RADIANCE_MAP
- if (no_ambient_light) {
- ambient_light=vec3(0.0,0.0,0.0);
- } else {
- {
-
- { //read radiance from dual paraboloid
+#ifdef AMBIENT_LIGHT_DISABLED
+ ambient_light=vec3(0.0,0.0,0.0);
+#else
+ {
- vec3 ref_vec = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n);
- ref_vec=normalize((radiance_inverse_xform * vec4(ref_vec,0.0)).xyz);
- vec3 radiance = textureDualParaboloid(radiance_map,ref_vec,roughness) * bg_energy;
- env_reflection_light = radiance;
+ { //read radiance from dual paraboloid
- }
- //no longer a cubemap
- //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y);
+ vec3 ref_vec = reflect(-eye_vec,normal); //2.0 * ndotv * normal - view; // reflect(v, n);
+ ref_vec=normalize((radiance_inverse_xform * vec4(ref_vec,0.0)).xyz);
+ vec3 radiance = textureDualParaboloid(radiance_map,ref_vec,roughness) * bg_energy;
+ env_reflection_light = radiance;
}
+ //no longer a cubemap
+ //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y);
+
+ }
#ifndef USE_LIGHTMAP
- {
+ {
- vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz);
- vec3 env_ambient=textureDualParaboloid(radiance_map,ambient_dir,1.0) * bg_energy;
+ vec3 ambient_dir=normalize((radiance_inverse_xform * vec4(normal,0.0)).xyz);
+ vec3 env_ambient=textureDualParaboloid(radiance_map,ambient_dir,1.0) * bg_energy;
- ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution);
- //ambient_light=vec3(0.0,0.0,0.0);
- }
-#endif
+ ambient_light=mix(ambient_light_color.rgb,env_ambient,radiance_ambient_contribution);
+ //ambient_light=vec3(0.0,0.0,0.0);
}
+#endif
+#endif //AMBIENT_LIGHT_DISABLED
#else
- if (no_ambient_light){
- ambient_light=vec3(0.0,0.0,0.0);
- } else {
- ambient_light=ambient_light_color.rgb;
- }
+#ifdef AMBIENT_LIGHT_DISABLED
+ ambient_light=vec3(0.0,0.0,0.0);
+#else
+ ambient_light=ambient_light_color.rgb;
+#endif //AMBIENT_LIGHT_DISABLED
+
#endif
ambient_light*=ambient_energy;
@@ -2142,6 +2140,8 @@ FRAGMENT_SHADER_CODE
#else
+
+
//approximate ambient scale for SSAO, since we will lack full ambient
float max_emission=max(emission.r,max(emission.g,emission.b));
float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b));
@@ -2173,7 +2173,6 @@ FRAGMENT_SHADER_CODE
frag_color=vec4(emission+ambient_light+diffuse_light+specular_light,alpha);
#endif //SHADELESS
-
#endif //USE_MULTIPLE_RENDER_TARGETS
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 0f47949b4b..864b9714a9 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -155,7 +155,7 @@ Error AudioDriverPulseAudio::init_device() {
break;
}
- int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
pa_buffer_size = buffer_frames * pa_map.channels;
@@ -204,7 +204,7 @@ Error AudioDriverPulseAudio::init() {
thread_exited = false;
exit_thread = false;
- mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
pa_ml = pa_mainloop_new();
ERR_FAIL_COND_V(pa_ml == NULL, ERR_CANT_OPEN);
@@ -289,18 +289,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
AudioDriverPulseAudio *ad = (AudioDriverPulseAudio *)p_udata;
while (!ad->exit_thread) {
+
+ ad->lock();
+ ad->start_counting_ticks();
+
if (!ad->active) {
for (unsigned int i = 0; i < ad->pa_buffer_size; i++) {
ad->samples_out[i] = 0;
}
} else {
- ad->lock();
-
ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw());
- ad->unlock();
-
if (ad->channels == ad->pa_map.channels) {
for (unsigned int i = 0; i < ad->pa_buffer_size; i++) {
ad->samples_out[i] = ad->samples_in[i] >> 16;
@@ -323,9 +323,6 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
int error_code;
int byte_size = ad->pa_buffer_size * sizeof(int16_t);
-
- ad->lock();
-
int ret;
do {
ret = pa_mainloop_iterate(ad->pa_ml, 0, NULL);
@@ -350,11 +347,13 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
if (ret == 0) {
// If pa_mainloop_iterate returns 0 sleep for 1 msec to wait
// for the stream to be able to process more bytes
+ ad->stop_counting_ticks();
ad->unlock();
OS::get_singleton()->delay_usec(1000);
ad->lock();
+ ad->start_counting_ticks();
}
}
}
@@ -380,6 +379,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
}
}
+ ad->stop_counting_ticks();
ad->unlock();
}
@@ -403,7 +403,6 @@ AudioDriver::SpeakerMode AudioDriverPulseAudio::get_speaker_mode() const {
void AudioDriverPulseAudio::pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata) {
AudioDriverPulseAudio *ad = (AudioDriverPulseAudio *)userdata;
- int ctr = 0;
// If eol is set to a positive number, you're at the end of the list
if (eol > 0) {
@@ -453,7 +452,9 @@ String AudioDriverPulseAudio::get_device() {
void AudioDriverPulseAudio::set_device(String device) {
+ lock();
new_device = device;
+ unlock();
}
void AudioDriverPulseAudio::lock() {
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index 457486797f..365788e192 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -88,7 +88,7 @@ Error AudioDriverRtAudio::init() {
// FIXME: Adapt to the OutputFormat -> SpeakerMode change
/*
- String channels = GLOBAL_DEF("audio/output","stereo");
+ String channels = GLOBAL_DEF_RST("audio/output","stereo");
if (channels=="5.1")
output_format=OUTPUT_5_1;
@@ -108,7 +108,7 @@ Error AudioDriverRtAudio::init() {
options.numberOfBuffers = 4;
parameters.firstChannel = 0;
- mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
unsigned int buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index e1680601ad..1d96f9ee7d 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -318,7 +318,7 @@ Error AudioDriverWASAPI::finish_device() {
Error AudioDriverWASAPI::init() {
- mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
Error err = init_device();
if (err != OK) {
@@ -335,22 +335,6 @@ Error AudioDriverWASAPI::init() {
return OK;
}
-Error AudioDriverWASAPI::reopen() {
- Error err = finish_device();
- if (err != OK) {
- ERR_PRINT("WASAPI: finish_device error");
- } else {
- err = init_device();
- if (err != OK) {
- ERR_PRINT("WASAPI: init_device error");
- } else {
- start();
- }
- }
-
- return err;
-}
-
int AudioDriverWASAPI::get_mix_rate() const {
return mix_rate;
@@ -416,7 +400,9 @@ String AudioDriverWASAPI::get_device() {
void AudioDriverWASAPI::set_device(String device) {
+ lock();
new_device = device;
+ unlock();
}
void AudioDriverWASAPI::write_sample(AudioDriverWASAPI *ad, BYTE *buffer, int i, int32_t sample) {
@@ -453,24 +439,31 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
AudioDriverWASAPI *ad = (AudioDriverWASAPI *)p_udata;
while (!ad->exit_thread) {
- if (ad->active) {
- ad->lock();
- ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw());
+ ad->lock();
+ ad->start_counting_ticks();
- ad->unlock();
+ if (ad->active) {
+ ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw());
} else {
for (unsigned int i = 0; i < ad->buffer_size; i++) {
ad->samples_in[i] = 0;
}
}
+ ad->stop_counting_ticks();
+ ad->unlock();
+
unsigned int left_frames = ad->buffer_frames;
unsigned int buffer_idx = 0;
while (left_frames > 0 && ad->audio_client) {
WaitForSingleObject(ad->event, 1000);
+ ad->lock();
+ ad->start_counting_ticks();
+
UINT32 cur_frames;
+ bool invalidated = false;
HRESULT hr = ad->audio_client->GetCurrentPadding(&cur_frames);
if (hr == S_OK) {
// Check how much frames are available on the WASAPI buffer
@@ -506,34 +499,34 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
left_frames -= write_frames;
} else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
- // Device is not valid anymore, reopen it
-
- Error err = ad->finish_device();
- if (err != OK) {
- ERR_PRINT("WASAPI: finish_device error");
- } else {
- // We reopened the device and samples_in may have resized, so invalidate the current left_frames
- left_frames = 0;
- }
+ invalidated = true;
} else {
ERR_PRINT("WASAPI: Get buffer error");
ad->exit_thread = true;
}
} else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
- // Device is not valid anymore, reopen it
+ invalidated = true;
+ } else {
+ ERR_PRINT("WASAPI: GetCurrentPadding error");
+ }
+
+ if (invalidated) {
+ // Device is not valid anymore
+ WARN_PRINT("WASAPI: Current device invalidated, closing device");
Error err = ad->finish_device();
if (err != OK) {
ERR_PRINT("WASAPI: finish_device error");
- } else {
- // We reopened the device and samples_in may have resized, so invalidate the current left_frames
- left_frames = 0;
}
- } else {
- ERR_PRINT("WASAPI: GetCurrentPadding error");
}
+
+ ad->stop_counting_ticks();
+ ad->unlock();
}
+ ad->lock();
+ ad->start_counting_ticks();
+
// If we're using the Default device and it changed finish it so we'll re-init the device
if (ad->device_name == "Default" && default_device_changed) {
Error err = ad->finish_device();
@@ -559,6 +552,9 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
ad->start();
}
}
+
+ ad->stop_counting_ticks();
+ ad->unlock();
}
ad->thread_exited = true;
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index c97f4c288c..f3ee5976eb 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -72,7 +72,6 @@ class AudioDriverWASAPI : public AudioDriver {
Error init_device(bool reinit = false);
Error finish_device();
- Error reopen();
public:
virtual const char *get_name() const {
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index aa0fd34e0a..ea194e5eae 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -141,9 +141,9 @@ void FileAccessWindows::close() {
bool rename_error = true;
int attempts = 4;
while (rename_error && attempts) {
- // This workaround of trying multiple times is added to deal with paranoid Windows
- // antiviruses that love reading just written files even if they are not executable, thus
- // locking the file and preventing renaming from happening.
+ // This workaround of trying multiple times is added to deal with paranoid Windows
+ // antiviruses that love reading just written files even if they are not executable, thus
+ // locking the file and preventing renaming from happening.
#ifdef UWP_ENABLED
// UWP has no PathFileExists, so we check attributes instead
diff --git a/drivers/winmidi/SCsub b/drivers/winmidi/SCsub
new file mode 100644
index 0000000000..233593b0f9
--- /dev/null
+++ b/drivers/winmidi/SCsub
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+Import('env')
+
+# Driver source files
+env.add_source_files(env.drivers_sources, "*.cpp")
+
+Export('env')
diff --git a/drivers/winmidi/win_midi.cpp b/drivers/winmidi/win_midi.cpp
new file mode 100644
index 0000000000..6da6e31b2b
--- /dev/null
+++ b/drivers/winmidi/win_midi.cpp
@@ -0,0 +1,100 @@
+/*************************************************************************/
+/* win_midi.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef WINMIDI_ENABLED
+
+#include "win_midi.h"
+#include "print_string.h"
+
+void MIDIDriverWinMidi::read(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
+
+ if (wMsg == MIM_DATA) {
+ receive_input_packet((uint64_t)dwParam2, (uint8_t *)&dwParam1, 3);
+ }
+}
+
+Error MIDIDriverWinMidi::open() {
+
+ for (UINT i = 0; i < midiInGetNumDevs(); i++) {
+ HMIDIIN midi_in;
+
+ MMRESULT res = midiInOpen(&midi_in, i, (DWORD_PTR)read, (DWORD_PTR)this, CALLBACK_FUNCTION);
+ if (res == MMSYSERR_NOERROR) {
+ midiInStart(midi_in);
+ connected_sources.insert(i, midi_in);
+ } else {
+ char err[256];
+ midiInGetErrorText(res, err, 256);
+ ERR_PRINTS("midiInOpen error: " + String(err));
+ }
+ }
+
+ return OK;
+}
+
+PoolStringArray MIDIDriverWinMidi::get_connected_inputs() {
+
+ PoolStringArray list;
+
+ for (int i = 0; i < connected_sources.size(); i++) {
+ HMIDIIN midi_in = connected_sources[i];
+ UINT id = 0;
+ MMRESULT res = midiInGetID(midi_in, &id);
+ if (res == MMSYSERR_NOERROR) {
+ MIDIINCAPS caps;
+ res = midiInGetDevCaps(i, &caps, sizeof(MIDIINCAPS));
+ if (res == MMSYSERR_NOERROR) {
+ list.push_back(caps.szPname);
+ }
+ }
+ }
+
+ return list;
+}
+
+void MIDIDriverWinMidi::close() {
+
+ for (int i = 0; i < connected_sources.size(); i++) {
+ HMIDIIN midi_in = connected_sources[i];
+ midiInStop(midi_in);
+ midiInClose(midi_in);
+ }
+ connected_sources.clear();
+}
+
+MIDIDriverWinMidi::MIDIDriverWinMidi() {
+}
+
+MIDIDriverWinMidi::~MIDIDriverWinMidi() {
+
+ close();
+}
+
+#endif
diff --git a/drivers/winmidi/win_midi.h b/drivers/winmidi/win_midi.h
new file mode 100644
index 0000000000..1cf9b19b5d
--- /dev/null
+++ b/drivers/winmidi/win_midi.h
@@ -0,0 +1,61 @@
+/*************************************************************************/
+/* win_midi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef WINMIDI_ENABLED
+
+#ifndef WIN_MIDI_H
+#define WIN_MIDI_H
+
+#include <stdio.h>
+#include <windows.h>
+
+#include <mmsystem.h>
+
+#include "core/vector.h"
+#include "os/midi_driver.h"
+
+class MIDIDriverWinMidi : public MIDIDriver {
+
+ Vector<HMIDIIN> connected_sources;
+
+ static void CALLBACK read(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+
+public:
+ virtual Error open();
+ virtual void close();
+
+ virtual PoolStringArray get_connected_inputs();
+
+ MIDIDriverWinMidi();
+ virtual ~MIDIDriverWinMidi();
+};
+
+#endif
+#endif
diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp
index 6675459313..a1002ef4f9 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.cpp
+++ b/drivers/xaudio2/audio_driver_xaudio2.cpp
@@ -50,7 +50,7 @@ Error AudioDriverXAudio2::init() {
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
- int latency = GLOBAL_DEF("audio/output_latency", 25);
+ int latency = GLOBAL_DEF_RST("audio/output_latency", 25);
buffer_size = closest_power_of_2(latency * mix_rate / 1000);
samples_in = memnew_arr(int32_t, buffer_size * channels);
@@ -97,8 +97,6 @@ void AudioDriverXAudio2::thread_func(void *p_udata) {
AudioDriverXAudio2 *ad = (AudioDriverXAudio2 *)p_udata;
- uint64_t usdelay = (ad->buffer_size / float(ad->mix_rate)) * 1000000;
-
while (!ad->exit_thread) {
if (!ad->active) {