summaryrefslogtreecommitdiffstats
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.cpp2
-rw-r--r--platform/linuxbsd/detect.py5
-rw-r--r--platform/linuxbsd/display_server_x11.cpp41
-rw-r--r--platform/linuxbsd/display_server_x11.h1
-rw-r--r--platform/linuxbsd/key_mapping_x11.cpp26
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp203
-rw-r--r--platform/linuxbsd/os_linuxbsd.h5
7 files changed, 243 insertions, 40 deletions
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp
index 33da094860..8c8c8588b8 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.cpp
+++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp
@@ -89,7 +89,7 @@ static void handle_crash(int sig) {
// Try to demangle the function name to provide a more readable one
if (dladdr(bt_buffer[i], &info) && info.dli_sname) {
if (info.dli_sname[0] == '_') {
- int status;
+ int status = 0;
char *demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
if (status == 0 && demangled) {
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index dfde0d249c..ac69f3806b 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -363,7 +363,10 @@ def configure(env: "Environment"):
if platform.system() == "Linux":
env.Append(LIBS=["dl"])
- if platform.system().find("BSD") >= 0:
+ if not env["execinfo"] and platform.libc_ver()[0] != "glibc":
+ # The default crash handler depends on glibc, so if the host uses
+ # a different libc (BSD libc, musl), fall back to libexecinfo.
+ print("Note: Using `execinfo=yes` for the crash handler as required on platforms where glibc is missing.")
env["execinfo"] = True
if env["execinfo"]:
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 81fc941608..e78467beff 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -49,10 +49,14 @@
#include "drivers/gles3/rasterizer_gles3.h"
#endif
+#include <dlfcn.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
@@ -66,17 +70,6 @@
#define _NET_WM_STATE_REMOVE 0L // remove/unset property
#define _NET_WM_STATE_ADD 1L // add/set property
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-//stupid linux.h
-#ifdef KEY_TAB
-#undef KEY_TAB
-#endif
-
#undef CursorShape
#include <X11/XKBlib.h>
@@ -1209,16 +1202,6 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
return SCREEN_REFRESH_RATE_FALLBACK;
}
-bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {
- _THREAD_SAFE_METHOD_
-
-#ifndef _MSC_VER
-#warning Need to get from proper window
-#endif
-
- return DisplayServer::screen_is_touchscreen(p_screen);
-}
-
#ifdef DBUS_ENABLED
void DisplayServerX11::screen_set_keep_on(bool p_enable) {
if (screen_is_kept_on() == p_enable) {
@@ -1746,6 +1729,18 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
usleep(10000);
}
+
+ // Keep rendering context window size in sync
+#if defined(VULKAN_ENABLED)
+ if (context_vulkan) {
+ context_vulkan->window_resize(p_window, xwa.width, xwa.height);
+ }
+#endif
+#if defined(GLES3_ENABLED)
+ if (gl_manager) {
+ gl_manager->window_resize(p_window, xwa.width, xwa.height);
+ }
+#endif
}
Size2i DisplayServerX11::window_get_size(WindowID p_window) const {
@@ -3149,7 +3144,7 @@ void DisplayServerX11::_window_changed(XEvent *event) {
{
//the position in xconfigure is not useful here, obtain it manually
- int x, y;
+ int x = 0, y = 0;
Window child;
XTranslateCoordinates(x11_display, wd.x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child);
new_rect.position.x = x;
@@ -3312,7 +3307,7 @@ void DisplayServerX11::_check_pending_events(LocalVector<XEvent> &r_events) {
XFlush(x11_display);
// Non-blocking wait for next event and remove it from the queue.
- XEvent ev;
+ XEvent ev = {};
while (XCheckIfEvent(x11_display, &ev, _predicate_all_events, nullptr)) {
// Check if the input manager wants to process the event.
if (XFilterEvent(&ev, None)) {
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index a5fa7613bc..5723abc751 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -349,7 +349,6 @@ public:
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
#if defined(DBUS_ENABLED)
virtual void screen_set_keep_on(bool p_enable) override;
diff --git a/platform/linuxbsd/key_mapping_x11.cpp b/platform/linuxbsd/key_mapping_x11.cpp
index 047ee74671..f774c99d99 100644
--- a/platform/linuxbsd/key_mapping_x11.cpp
+++ b/platform/linuxbsd/key_mapping_x11.cpp
@@ -108,17 +108,21 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
{ XK_KP_7, Key::KP_7 },
{ XK_KP_8, Key::KP_8 },
{ XK_KP_9, Key::KP_9 },
- // same but with numlock
- { XK_KP_Insert, Key::KP_0 },
- { XK_KP_End, Key::KP_1 },
- { XK_KP_Down, Key::KP_2 },
- { XK_KP_Page_Down, Key::KP_3 },
- { XK_KP_Left, Key::KP_4 },
- { XK_KP_Begin, Key::KP_5 },
- { XK_KP_Right, Key::KP_6 },
- { XK_KP_Home, Key::KP_7 },
- { XK_KP_Up, Key::KP_8 },
- { XK_KP_Page_Up, Key::KP_9 },
+ // same keys but with numlock off
+ { XK_KP_Insert, Key::INSERT },
+ { XK_KP_End, Key::END },
+ { XK_KP_Down, Key::DOWN },
+ { XK_KP_Page_Down, Key::PAGEDOWN },
+ { XK_KP_Left, Key::LEFT },
+ // X11 documents this (numpad 5) as "begin of line" but no toolkit
+ // seems to interpret it this way.
+ // On Windows this is emitting Key::Clear so for consistency it
+ // will be mapped to Key::Clear
+ { XK_KP_Begin, Key::CLEAR },
+ { XK_KP_Right, Key::RIGHT },
+ { XK_KP_Home, Key::HOME },
+ { XK_KP_Up, Key::UP },
+ { XK_KP_Page_Up, Key::PAGEUP },
{ XK_F1, Key::F1 },
{ XK_F2, Key::F2 },
{ XK_F3, Key::F3 },
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index f4e94f1a91..995a904398 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -34,6 +34,11 @@
#include "main/main.h"
#include "servers/display_server.h"
+#include "modules/modules_enabled.gen.h" // For regex.
+#ifdef MODULE_REGEX_ENABLED
+#include "modules/regex/regex.h"
+#endif
+
#ifdef X11_ENABLED
#include "display_server_x11.h"
#endif
@@ -42,12 +47,10 @@
#include <mntent.h>
#endif
+#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#include <dlfcn.h>
-#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
@@ -242,6 +245,200 @@ String OS_LinuxBSD::get_version() const {
return uts.version;
}
+Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
+ const String rendering_device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name(); // e.g. `NVIDIA GeForce GTX 970`
+ const String rendering_device_vendor = RenderingServer::get_singleton()->get_rendering_device()->get_device_vendor_name(); // e.g. `NVIDIA`
+ const String card_name = rendering_device_name.trim_prefix(rendering_device_vendor).strip_edges(); // -> `GeForce GTX 970`
+
+ String vendor_device_id_mappings;
+ List<String> lspci_args;
+ lspci_args.push_back("-n");
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("lspci", lspci_args, &vendor_device_id_mappings);
+ if (err != OK || vendor_device_id_mappings.is_empty()) {
+ return Vector<String>();
+ }
+
+ // Usually found under "VGA", but for example NVIDIA mobile/laptop adapters are often listed under "3D" and some AMD adapters are under "Display".
+ const String dc_vga = "0300"; // VGA compatible controller
+ const String dc_display = "0302"; // Display controller
+ const String dc_3d = "0380"; // 3D controller
+
+ // splitting results by device class allows prioritizing, if multiple devices are found.
+ Vector<String> class_vga_device_candidates;
+ Vector<String> class_display_device_candidates;
+ Vector<String> class_3d_device_candidates;
+
+#ifdef MODULE_REGEX_ENABLED
+ RegEx regex_id_format = RegEx();
+ regex_id_format.compile("^[a-f0-9]{4}:[a-f0-9]{4}$"); // e.g. `10de:13c2`; IDs are always in hexadecimal
+#endif
+
+ Vector<String> value_lines = vendor_device_id_mappings.split("\n", false); // example: `02:00.0 0300: 10de:13c2 (rev a1)`
+ for (const String &line : value_lines) {
+ Vector<String> columns = line.split(" ", false);
+ if (columns.size() < 3) {
+ continue;
+ }
+ String device_class = columns[1].trim_suffix(":");
+ String vendor_device_id_mapping = columns[2];
+
+#ifdef MODULE_REGEX_ENABLED
+ if (regex_id_format.search(vendor_device_id_mapping).is_null()) {
+ continue;
+ }
+#endif
+
+ if (device_class == dc_vga) {
+ class_vga_device_candidates.push_back(vendor_device_id_mapping);
+ } else if (device_class == dc_display) {
+ class_display_device_candidates.push_back(vendor_device_id_mapping);
+ } else if (device_class == dc_3d) {
+ class_3d_device_candidates.push_back(vendor_device_id_mapping);
+ }
+ }
+
+ // Check results against currently used device (`card_name`), in case the user has multiple graphics cards.
+ const String device_lit = "Device"; // line of interest
+ class_vga_device_candidates = OS_LinuxBSD::lspci_device_filter(class_vga_device_candidates, dc_vga, device_lit, card_name);
+ class_display_device_candidates = OS_LinuxBSD::lspci_device_filter(class_display_device_candidates, dc_display, device_lit, card_name);
+ class_3d_device_candidates = OS_LinuxBSD::lspci_device_filter(class_3d_device_candidates, dc_3d, device_lit, card_name);
+
+ // Get driver names and filter out invalid ones, because some adapters are dummys used only for passthrough.
+ // And they have no indicator besides certain driver names.
+ const String kernel_lit = "Kernel driver in use"; // line of interest
+ const String dummys = "vfio"; // for e.g. pci passthrough dummy kernel driver `vfio-pci`
+ Vector<String> class_vga_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_vga_device_candidates, kernel_lit, dummys);
+ Vector<String> class_display_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_display_device_candidates, kernel_lit, dummys);
+ Vector<String> class_3d_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_3d_device_candidates, kernel_lit, dummys);
+
+ static String driver_name;
+ static String driver_version;
+
+ // Use first valid value:
+ for (const String &driver : class_3d_device_drivers) {
+ driver_name = driver;
+ break;
+ }
+ if (driver_name.is_empty()) {
+ for (const String &driver : class_display_device_drivers) {
+ driver_name = driver;
+ break;
+ }
+ }
+ if (driver_name.is_empty()) {
+ for (const String &driver : class_vga_device_drivers) {
+ driver_name = driver;
+ break;
+ }
+ }
+
+ Vector<String> info;
+ info.push_back(driver_name);
+
+ String modinfo;
+ List<String> modinfo_args;
+ modinfo_args.push_back(driver_name);
+ err = const_cast<OS_LinuxBSD *>(this)->execute("modinfo", modinfo_args, &modinfo);
+ if (err != OK || modinfo.is_empty()) {
+ info.push_back(""); // So that this method always either returns an empty array, or an array of length 2.
+ return info;
+ }
+ Vector<String> lines = modinfo.split("\n", false);
+ for (const String &line : lines) {
+ Vector<String> columns = line.split(":", false, 1);
+ if (columns.size() < 2) {
+ continue;
+ }
+ if (columns[0].strip_edges() == "version") {
+ driver_version = columns[1].strip_edges(); // example value: `510.85.02` on Linux/BSD
+ break;
+ }
+ }
+
+ info.push_back(driver_version);
+
+ return info;
+}
+
+Vector<String> OS_LinuxBSD::lspci_device_filter(Vector<String> vendor_device_id_mapping, String class_suffix, String check_column, String whitelist) const {
+ // NOTE: whitelist can be changed to `Vector<String>`, if the need arises.
+ const String sep = ":";
+ Vector<String> devices;
+ for (const String &mapping : vendor_device_id_mapping) {
+ String device;
+ List<String> d_args;
+ d_args.push_back("-d");
+ d_args.push_back(mapping + sep + class_suffix);
+ d_args.push_back("-vmm");
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("lspci", d_args, &device); // e.g. `lspci -d 10de:13c2:0300 -vmm`
+ if (err != OK) {
+ return Vector<String>();
+ } else if (device.is_empty()) {
+ continue;
+ }
+
+ Vector<String> device_lines = device.split("\n", false);
+ for (const String &line : device_lines) {
+ Vector<String> columns = line.split(":", false, 1);
+ if (columns.size() < 2) {
+ continue;
+ }
+ if (columns[0].strip_edges() == check_column) {
+ // for `column[0] == "Device"` this may contain `GM204 [GeForce GTX 970]`
+ bool is_valid = true;
+ if (!whitelist.is_empty()) {
+ is_valid = columns[1].strip_edges().contains(whitelist);
+ }
+ if (is_valid) {
+ devices.push_back(mapping);
+ }
+ break;
+ }
+ }
+ }
+ return devices;
+}
+
+Vector<String> OS_LinuxBSD::lspci_get_device_value(Vector<String> vendor_device_id_mapping, String check_column, String blacklist) const {
+ // NOTE: blacklist can be changed to `Vector<String>`, if the need arises.
+ const String sep = ":";
+ Vector<String> values;
+ for (const String &mapping : vendor_device_id_mapping) {
+ String device;
+ List<String> d_args;
+ d_args.push_back("-d");
+ d_args.push_back(mapping);
+ d_args.push_back("-k");
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("lspci", d_args, &device); // e.g. `lspci -d 10de:13c2 -k`
+ if (err != OK) {
+ return Vector<String>();
+ } else if (device.is_empty()) {
+ continue;
+ }
+
+ Vector<String> device_lines = device.split("\n", false);
+ for (const String &line : device_lines) {
+ Vector<String> columns = line.split(":", false, 1);
+ if (columns.size() < 2) {
+ continue;
+ }
+ if (columns[0].strip_edges() == check_column) {
+ // for `column[0] == "Kernel driver in use"` this may contain `nvidia`
+ bool is_valid = true;
+ const String value = columns[1].strip_edges();
+ if (!blacklist.is_empty()) {
+ is_valid = !value.contains(blacklist);
+ }
+ if (is_valid) {
+ values.push_back(value);
+ }
+ break;
+ }
+ }
+ }
+ return values;
+}
+
Error OS_LinuxBSD::shell_open(String p_uri) {
Error ok;
int err_code;
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index 722d83ba19..aea04c1363 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -69,6 +69,9 @@ class OS_LinuxBSD : public OS_Unix {
String get_systemd_os_release_info_value(const String &key) const;
+ Vector<String> lspci_device_filter(Vector<String> vendor_device_id_mapping, String class_suffix, String check_column, String whitelist) const;
+ Vector<String> lspci_get_device_value(Vector<String> vendor_device_id_mapping, String check_column, String blacklist) const;
+
protected:
virtual void initialize() override;
virtual void finalize() override;
@@ -82,6 +85,8 @@ public:
virtual String get_distribution_name() const override;
virtual String get_version() const override;
+ virtual Vector<String> get_video_adapter_driver_info() const override;
+
virtual MainLoop *get_main_loop() const override;
virtual uint64_t get_embedded_pck_offset() const override;