summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSpartan322 <Megacake1234@gmail.com>2024-11-19 11:38:29 -0500
committerSpartan322 <Megacake1234@gmail.com>2024-11-19 11:39:37 -0500
commitcfc378b251e4330c6b6be949d4c054f9bae48159 (patch)
tree148a5511d3c1d723b2f2f364c832c2ba6f267fcc /drivers
parent9767837a7ec40697788765e581131cb2cf172567 (diff)
parentfd4c29a189e53a1e085df5b9b9a05cac9351b3ef (diff)
downloadredot-engine-cfc378b251e4330c6b6be949d4c054f9bae48159.tar.gz
Merge commit godotengine/godot@fd4c29a189e53a1e085df5b9b9a05cac9351b3ef
Diffstat (limited to 'drivers')
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp32
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h4
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp4
-rw-r--r--drivers/gles3/shaders/canvas.glsl11
-rw-r--r--drivers/gles3/shaders/sky.glsl6
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp4
-rw-r--r--drivers/gles3/storage/mesh_storage.h1
-rw-r--r--drivers/metal/rendering_device_driver_metal.mm3
-rw-r--r--drivers/unix/ip_unix.cpp75
-rw-r--r--drivers/unix/ip_unix.h6
-rw-r--r--drivers/unix/os_unix.cpp2
-rw-r--r--drivers/windows/dir_access_windows.cpp4
-rw-r--r--drivers/windows/file_access_windows.cpp2
-rw-r--r--drivers/windows/ip_windows.cpp166
-rw-r--r--drivers/windows/ip_windows.h56
16 files changed, 270 insertions, 108 deletions
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 530f0bf71e..2745b71fcf 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -82,7 +82,7 @@ Error AudioDriverALSA::init_output_device() {
status = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
} else {
String device = output_device_name;
- int pos = device.find(";");
+ int pos = device.find_char(';');
if (pos != -1) {
device = device.substr(0, pos);
}
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index b4160178c1..8e1b744113 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -689,6 +689,8 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
state.current_tex = RID();
+ const uint64_t base_specialization = GLES3::Config::get_singleton()->float_texture_supported ? 0 : CanvasShaderGLES3::USE_RGBA_SHADOWS;
+
for (uint32_t i = 0; i <= state.current_batch_index; i++) {
// Skipping when there is no instances.
if (state.canvas_instance_batches[i].instance_count == 0) {
@@ -707,10 +709,9 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
}
GLES3::CanvasMaterialData *material_data = state.canvas_instance_batches[i].material_data;
- CanvasShaderGLES3::ShaderVariant variant = state.canvas_instance_batches[i].shader_variant;
- uint64_t specialization = 0;
- specialization |= uint64_t(state.canvas_instance_batches[i].lights_disabled);
- specialization |= uint64_t(!GLES3::Config::get_singleton()->float_texture_supported) << 1;
+ CanvasShaderGLES3::ShaderVariant variant = CanvasShaderGLES3::MODE_DEFAULT;
+ uint64_t specialization = state.canvas_instance_batches[i].specialization;
+ specialization |= base_specialization;
RID shader_version = data.canvas_shader_default_version;
if (material_data) {
@@ -812,6 +813,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, const Point2 &p_repeat_offset) {
RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter;
+ const uint64_t specialization_command_mask = ~(CanvasShaderGLES3::USE_NINEPATCH | CanvasShaderGLES3::USE_PRIMITIVE | CanvasShaderGLES3::USE_ATTRIBUTES | CanvasShaderGLES3::USE_INSTANCING);
if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) {
_new_batch(r_batch_broken);
@@ -870,9 +872,9 @@ 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) {
+ if (lights_disabled != bool(state.canvas_instance_batches[state.current_batch_index].specialization & CanvasShaderGLES3::DISABLE_LIGHTING)) {
_new_batch(r_batch_broken);
- state.canvas_instance_batches[state.current_batch_index].lights_disabled = lights_disabled;
+ state.canvas_instance_batches[state.current_batch_index].specialization ^= CanvasShaderGLES3::DISABLE_LIGHTING;
}
const Item::Command *c = p_item->commands;
@@ -938,7 +940,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
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;
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_QUAD;
+ state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
}
_prepare_canvas_texture(rect->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
@@ -1028,7 +1030,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
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;
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_NINEPATCH;
+ state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
+ state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_NINEPATCH;
}
_prepare_canvas_texture(np->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
@@ -1094,7 +1097,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
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;
state.canvas_instance_batches[state.current_batch_index].command = c;
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES;
+ state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
+ state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES;
_prepare_canvas_texture(polygon->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
@@ -1121,7 +1125,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
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;
state.canvas_instance_batches[state.current_batch_index].command = c;
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_PRIMITIVE;
+ state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
+ state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_PRIMITIVE;
}
_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);
@@ -1166,7 +1171,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
_new_batch(r_batch_broken);
Color modulate(1, 1, 1, 1);
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_ATTRIBUTES;
+ state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
+ state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES;
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
state.canvas_instance_batches[state.current_batch_index].tex = m->texture;
@@ -1176,7 +1182,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
state.canvas_instance_batches[state.current_batch_index].tex = mm->texture;
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
+ state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING;
if (GLES3::MeshStorage::get_singleton()->multimesh_uses_colors(mm->multimesh)) {
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
@@ -1191,7 +1197,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
RID particles = pt->particles;
state.canvas_instance_batches[state.current_batch_index].tex = pt->texture;
- state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
+ state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING;
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index de64c4c89f..0fd82f841e 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -275,14 +275,12 @@ public:
RID material;
GLES3::CanvasMaterialData *material_data = nullptr;
- CanvasShaderGLES3::ShaderVariant shader_variant = CanvasShaderGLES3::MODE_QUAD;
uint64_t vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_COLOR | RS::ARRAY_FORMAT_TEX_UV;
+ uint64_t specialization = 0;
const Item::Command *command = nullptr;
Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch.
uint32_t primitive_points = 0;
-
- bool lights_disabled = false;
};
// DataBuffer contains our per-frame data. I.e. the resources that are updated each frame.
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 96b311b048..8b16da8d47 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -240,7 +240,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
GLES3::SceneMaterialData *material_shadow = nullptr;
void *surface_shadow = nullptr;
- if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates) {
+ if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_world_coordinates && !p_material->shader_data->wireframe) {
flags |= GeometryInstanceSurface::FLAG_USES_SHARED_SHADOW_MATERIAL;
material_shadow = static_cast<GLES3::SceneMaterialData *>(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.default_material, RS::SHADER_SPATIAL));
@@ -3159,7 +3159,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
bool use_wireframe = false;
- if (p_params->force_wireframe) {
+ if (p_params->force_wireframe || shader->wireframe) {
GLuint wireframe_index_array_gl = mesh_storage->mesh_surface_get_index_buffer_wireframe(mesh_surface);
if (wireframe_index_array_gl) {
index_array_gl = wireframe_index_array_gl;
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 5e7fb3b338..1ac289d5a2 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -1,17 +1,16 @@
/* clang-format off */
#[modes]
-mode_quad =
-mode_ninepatch = #define USE_NINEPATCH
-mode_primitive = #define USE_PRIMITIVE
-mode_attributes = #define USE_ATTRIBUTES
-mode_instanced = #define USE_ATTRIBUTES \n#define USE_INSTANCING
+mode_default =
#[specializations]
DISABLE_LIGHTING = true
USE_RGBA_SHADOWS = false
-SINGLE_INSTANCE = false
+USE_NINEPATCH = false
+USE_PRIMITIVE = false
+USE_ATTRIBUTES = false
+USE_INSTANCING = false
#[vertex]
diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl
index 186b630bc8..043023aee0 100644
--- a/drivers/gles3/shaders/sky.glsl
+++ b/drivers/gles3/shaders/sky.glsl
@@ -2,17 +2,15 @@
#[modes]
mode_background =
-mode_half_res = #define USE_HALF_RES_PASS
-mode_quarter_res = #define USE_QUARTER_RES_PASS
mode_cubemap = #define USE_CUBEMAP_PASS
-mode_cubemap_half_res = #define USE_CUBEMAP_PASS \n#define USE_HALF_RES_PASS
-mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PASS
#[specializations]
USE_MULTIVIEW = false
USE_INVERTED_Y = true
APPLY_TONEMAPPING = true
+USE_QUARTER_RES_PASS = false
+USE_HALF_RES_PASS = false
#[vertex]
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index ce2f63378e..917515bbdb 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -1976,6 +1976,10 @@ void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_
}
}
+RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const {
+ ERR_FAIL_V_MSG(RID(), "GLES3 does not contain a Rid for the multimesh buffer.");
+}
+
Vector<float> MeshStorage::_multimesh_get_buffer(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, Vector<float>());
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 09b7bfd16b..2577a19bd0 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -519,6 +519,7 @@ public:
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
+ virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override;
virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override;
virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
diff --git a/drivers/metal/rendering_device_driver_metal.mm b/drivers/metal/rendering_device_driver_metal.mm
index 5a30473735..7503558ee2 100644
--- a/drivers/metal/rendering_device_driver_metal.mm
+++ b/drivers/metal/rendering_device_driver_metal.mm
@@ -2022,7 +2022,8 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec
ERR_FAIL_COND_V_MSG(compiler.get_entry_points_and_stages().size() != 1, Result(), "Expected a single entry point and stage.");
- EntryPoint &entry_point_stage = compiler.get_entry_points_and_stages().front();
+ SmallVector<EntryPoint> entry_pts_stages = compiler.get_entry_points_and_stages();
+ EntryPoint &entry_point_stage = entry_pts_stages.front();
SPIREntryPoint &entry_point = compiler.get_entry_point(entry_point_stage.name, entry_point_stage.execution_model);
// Process specialization constants.
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index e9e267283f..951f969413 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -30,22 +30,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#include "ip_unix.h"
-
-#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
-
-#ifdef WINDOWS_ENABLED
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include <iphlpapi.h>
-
-#include <stdio.h>
+#if defined(UNIX_ENABLED)
-#else // UNIX
+#include "ip_unix.h"
#include <netdb.h>
@@ -69,8 +56,6 @@
#include <net/if.h> // Order is important on OpenBSD, leave as last.
-#endif // UNIX
-
#include <string.h>
static IPAddress _sockaddr2ip(struct sockaddr *p_addr) {
@@ -110,7 +95,7 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos
}
if (result == nullptr || result->ai_addr == nullptr) {
- print_verbose("Invalid response from getaddrinfo");
+ print_verbose("Invalid response from getaddrinfo.");
if (result) {
freeaddrinfo(result);
}
@@ -134,56 +119,6 @@ void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hos
freeaddrinfo(result);
}
-#if defined(WINDOWS_ENABLED)
-
-void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const {
- ULONG buf_size = 1024;
- IP_ADAPTER_ADDRESSES *addrs;
-
- while (true) {
- addrs = (IP_ADAPTER_ADDRESSES *)memalloc(buf_size);
- int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME,
- nullptr, addrs, &buf_size);
- if (err == NO_ERROR) {
- break;
- }
- memfree(addrs);
- if (err == ERROR_BUFFER_OVERFLOW) {
- continue; // will go back and alloc the right size
- }
-
- ERR_FAIL_MSG("Call to GetAdaptersAddresses failed with error " + itos(err) + ".");
- }
-
- IP_ADAPTER_ADDRESSES *adapter = addrs;
-
- while (adapter != nullptr) {
- Interface_Info info;
- info.name = adapter->AdapterName;
- info.name_friendly = adapter->FriendlyName;
- info.index = String::num_uint64(adapter->IfIndex);
-
- IP_ADAPTER_UNICAST_ADDRESS *address = adapter->FirstUnicastAddress;
- while (address != nullptr) {
- int family = address->Address.lpSockaddr->sa_family;
- if (family != AF_INET && family != AF_INET6) {
- continue;
- }
- info.ip_addresses.push_front(_sockaddr2ip(address->Address.lpSockaddr));
- address = address->Next;
- }
- adapter = adapter->Next;
- // Only add interface if it has at least one IP
- if (info.ip_addresses.size() > 0) {
- r_interfaces->insert(info.name, info);
- }
- }
-
- memfree(addrs);
-}
-
-#else // UNIX
-
void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const {
struct ifaddrs *ifAddrStruct = nullptr;
struct ifaddrs *ifa = nullptr;
@@ -221,8 +156,6 @@ void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces)
}
}
-#endif // UNIX
-
void IPUnix::make_default() {
_create = _create_unix;
}
@@ -234,4 +167,4 @@ IP *IPUnix::_create_unix() {
IPUnix::IPUnix() {
}
-#endif // UNIX_ENABLED || WINDOWS_ENABLED
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index 390e7aa904..54a5c67783 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -33,9 +33,9 @@
#ifndef IP_UNIX_H
#define IP_UNIX_H
-#include "core/io/ip.h"
+#if defined(UNIX_ENABLED)
-#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
+#include "core/io/ip.h"
class IPUnix : public IP {
GDCLASS(IPUnix, IP);
@@ -51,6 +51,6 @@ public:
IPUnix();
};
-#endif
+#endif // UNIX_ENABLED
#endif // IP_UNIX_H
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 8df91d1500..440b78e0b7 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -862,7 +862,7 @@ String OS_Unix::get_locale() const {
}
String locale = get_environment("LANG");
- int tp = locale.find(".");
+ int tp = locale.find_char('.');
if (tp != -1) {
locale = locale.substr(0, tp);
}
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 8c578e07de..8244c18051 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -232,7 +232,7 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) const {
return cdir;
} else {
if (_get_root_string().is_empty()) {
- int pos = cdir.find(":");
+ int pos = cdir.find_char(':');
if (pos != -1) {
return cdir.substr(pos + 1);
}
@@ -346,7 +346,7 @@ String DirAccessWindows::get_filesystem_type() const {
return "Network Share";
}
- int unit_end = path.find(":");
+ int unit_end = path.find_char(':');
ERR_FAIL_COND_V(unit_end == -1, String());
String unit = path.substr(0, unit_end + 1) + "\\";
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index b1dbb167a1..5e858cc0fa 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -66,7 +66,7 @@ bool FileAccessWindows::is_path_invalid(const String &p_path) {
// Check for invalid operating system file.
String fname = p_path.get_file().to_lower();
- int dot = fname.find(".");
+ int dot = fname.find_char('.');
if (dot != -1) {
fname = fname.substr(0, dot);
}
diff --git a/drivers/windows/ip_windows.cpp b/drivers/windows/ip_windows.cpp
new file mode 100644
index 0000000000..c8d94bfb2a
--- /dev/null
+++ b/drivers/windows/ip_windows.cpp
@@ -0,0 +1,166 @@
+/**************************************************************************/
+/* ip_windows.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* REDOT ENGINE */
+/* https://redotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2024-present Redot Engine contributors */
+/* (see REDOT_AUTHORS.md) */
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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. */
+/**************************************************************************/
+
+#if defined(WINDOWS_ENABLED)
+
+#include "ip_windows.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#include <iphlpapi.h>
+
+#include <stdio.h>
+
+#include <string.h>
+
+static IPAddress _sockaddr2ip(struct sockaddr *p_addr) {
+ IPAddress ip;
+
+ if (p_addr->sa_family == AF_INET) {
+ struct sockaddr_in *addr = (struct sockaddr_in *)p_addr;
+ ip.set_ipv4((uint8_t *)&(addr->sin_addr));
+ } else if (p_addr->sa_family == AF_INET6) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
+ ip.set_ipv6(addr6->sin6_addr.s6_addr);
+ }
+
+ return ip;
+}
+
+void IPWindows::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type) const {
+ struct addrinfo hints;
+ struct addrinfo *result = nullptr;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ if (p_type == TYPE_IPV4) {
+ hints.ai_family = AF_INET;
+ } else if (p_type == TYPE_IPV6) {
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = 0;
+ } else {
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_ADDRCONFIG;
+ }
+ hints.ai_flags &= ~AI_NUMERICHOST;
+
+ int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result);
+ if (s != 0) {
+ print_verbose("getaddrinfo failed! Cannot resolve hostname.");
+ return;
+ }
+
+ if (result == nullptr || result->ai_addr == nullptr) {
+ print_verbose("Invalid response from getaddrinfo.");
+ if (result) {
+ freeaddrinfo(result);
+ }
+ return;
+ }
+
+ struct addrinfo *next = result;
+
+ do {
+ if (next->ai_addr == nullptr) {
+ next = next->ai_next;
+ continue;
+ }
+ IPAddress ip = _sockaddr2ip(next->ai_addr);
+ if (ip.is_valid() && !r_addresses.find(ip)) {
+ r_addresses.push_back(ip);
+ }
+ next = next->ai_next;
+ } while (next);
+
+ freeaddrinfo(result);
+}
+
+void IPWindows::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const {
+ ULONG buf_size = 1024;
+ IP_ADAPTER_ADDRESSES *addrs;
+
+ while (true) {
+ addrs = (IP_ADAPTER_ADDRESSES *)memalloc(buf_size);
+ int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME,
+ nullptr, addrs, &buf_size);
+ if (err == NO_ERROR) {
+ break;
+ }
+ memfree(addrs);
+ if (err == ERROR_BUFFER_OVERFLOW) {
+ continue; // Will go back and alloc the right size.
+ }
+
+ ERR_FAIL_MSG("Call to GetAdaptersAddresses failed with error " + itos(err) + ".");
+ }
+
+ IP_ADAPTER_ADDRESSES *adapter = addrs;
+
+ while (adapter != nullptr) {
+ Interface_Info info;
+ info.name = adapter->AdapterName;
+ info.name_friendly = adapter->FriendlyName;
+ info.index = String::num_uint64(adapter->IfIndex);
+
+ IP_ADAPTER_UNICAST_ADDRESS *address = adapter->FirstUnicastAddress;
+ while (address != nullptr) {
+ int family = address->Address.lpSockaddr->sa_family;
+ if (family != AF_INET && family != AF_INET6) {
+ continue;
+ }
+ info.ip_addresses.push_front(_sockaddr2ip(address->Address.lpSockaddr));
+ address = address->Next;
+ }
+ adapter = adapter->Next;
+ // Only add interface if it has at least one IP.
+ if (info.ip_addresses.size() > 0) {
+ r_interfaces->insert(info.name, info);
+ }
+ }
+
+ memfree(addrs);
+}
+
+void IPWindows::make_default() {
+ _create = _create_unix;
+}
+
+IP *IPWindows::_create_unix() {
+ return memnew(IPWindows);
+}
+
+IPWindows::IPWindows() {
+}
+
+#endif // WINDOWS_ENABLED
diff --git a/drivers/windows/ip_windows.h b/drivers/windows/ip_windows.h
new file mode 100644
index 0000000000..69cb7996f8
--- /dev/null
+++ b/drivers/windows/ip_windows.h
@@ -0,0 +1,56 @@
+/**************************************************************************/
+/* ip_windows.h */
+/**************************************************************************/
+/* This file is part of: */
+/* REDOT ENGINE */
+/* https://redotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2024-present Redot Engine contributors */
+/* (see REDOT_AUTHORS.md) */
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef IP_WINDOWS_H
+#define IP_WINDOWS_H
+
+#if defined(WINDOWS_ENABLED)
+
+#include "core/io/ip.h"
+
+class IPWindows : public IP {
+ GDCLASS(IPWindows, IP);
+
+ virtual void _resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type = TYPE_ANY) const override;
+
+ static IP *_create_unix();
+
+public:
+ virtual void get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const override;
+
+ static void make_default();
+ IPWindows();
+};
+
+#endif // WINDOWS_ENABLED
+
+#endif // IP_WINDOWS_H