summaryrefslogtreecommitdiff
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/detect.py16
-rw-r--r--platform/linuxbsd/display_server_x11.cpp107
-rw-r--r--platform/linuxbsd/display_server_x11.h5
-rw-r--r--platform/linuxbsd/gl_manager_x11.cpp50
-rw-r--r--platform/linuxbsd/gl_manager_x11.h3
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp7
6 files changed, 116 insertions, 72 deletions
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index f5f7e65417..36644d5f29 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -31,7 +31,6 @@ def get_opts():
return [
EnumVariable("linker", "Linker program", "default", ("default", "bfd", "gold", "lld", "mold")),
BoolVariable("use_llvm", "Use the LLVM compiler", False),
- BoolVariable("use_thinlto", "Use ThinLTO (LLVM only, requires linker=lld, implies use_lto=yes)", False),
BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True),
BoolVariable("use_coverage", "Test Godot coverage", False),
BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False),
@@ -129,13 +128,6 @@ def configure(env):
else:
env.Append(LINKFLAGS=["-fuse-ld=%s" % env["linker"]])
- if env["use_thinlto"]:
- if not env["use_llvm"] or env["linker"] != "lld":
- print("ThinLTO is only compatible with LLVM and the LLD linker, use `use_llvm=yes linker=lld`.")
- sys.exit(255)
- else:
- env["use_lto"] = True # ThinLTO implies LTO
-
if env["use_coverage"]:
env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
env.Append(LINKFLAGS=["-ftest-coverage", "-fprofile-arcs"])
@@ -178,8 +170,12 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize-recover=memory"])
env.Append(LINKFLAGS=["-fsanitize=memory"])
- if env["use_lto"]:
- if env["use_thinlto"]:
+ # LTO
+ if env["lto"] != "none":
+ if env["lto"] == "thin":
+ if not env["use_llvm"]:
+ print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
+ sys.exit(255)
env.Append(CCFLAGS=["-flto=thin"])
env.Append(LINKFLAGS=["-flto=thin"])
elif not env["use_llvm"] and env.GetOption("num_jobs") > 1:
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index a329c7ee8c..66dea6cf1b 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -397,7 +397,10 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
//flush pending motion events
_flush_mouse_motion();
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
WindowData &window = windows[window_id];
if (XGrabPointer(
@@ -433,7 +436,11 @@ void DisplayServerX11::warp_mouse(const Point2i &p_position) {
if (mouse_mode == MOUSE_MODE_CAPTURED) {
last_mouse_pos = p_position;
} else {
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
+
XWarpPointer(x11_display, None, windows[window_id].x11_window,
0, 0, 0, 0, (int)p_position.x, (int)p_position.y);
}
@@ -1015,7 +1022,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i left_rect(pos.x, pos.y + left_start_y, left, left_end_y - left_start_y);
if (left_rect.size.x > 0) {
Rect2i intersection = rect.intersection(left_rect);
- if (!intersection.has_no_area() && intersection.size.x < rect.size.x) {
+ if (intersection.has_area() && intersection.size.x < rect.size.x) {
rect.position.x = left_rect.size.x;
rect.size.x = rect.size.x - intersection.size.x;
}
@@ -1024,7 +1031,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i right_rect(pos.x + size.x - right, pos.y + right_start_y, right, right_end_y - right_start_y);
if (right_rect.size.x > 0) {
Rect2i intersection = rect.intersection(right_rect);
- if (!intersection.has_no_area() && right_rect.size.x < rect.size.x) {
+ if (intersection.has_area() && right_rect.size.x < rect.size.x) {
rect.size.x = intersection.position.x - rect.position.x;
}
}
@@ -1032,7 +1039,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i top_rect(pos.x + top_start_x, pos.y, top_end_x - top_start_x, top);
if (top_rect.size.y > 0) {
Rect2i intersection = rect.intersection(top_rect);
- if (!intersection.has_no_area() && intersection.size.y < rect.size.y) {
+ if (intersection.has_area() && intersection.size.y < rect.size.y) {
rect.position.y = top_rect.size.y;
rect.size.y = rect.size.y - intersection.size.y;
}
@@ -1041,7 +1048,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i bottom_rect(pos.x + bottom_start_x, pos.y + size.y - bottom, bottom_end_x - bottom_start_x, bottom);
if (bottom_rect.size.y > 0) {
Rect2i intersection = rect.intersection(bottom_rect);
- if (!intersection.has_no_area() && right_rect.size.y < rect.size.y) {
+ if (intersection.has_area() && right_rect.size.y < rect.size.y) {
rect.size.y = intersection.position.y - rect.position.y;
}
}
@@ -2221,7 +2228,7 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
} break;
case WINDOW_FLAG_TRANSPARENT: {
- //todo reimplement
+ wd.layered_window = p_enabled;
} break;
case WINDOW_FLAG_NO_FOCUS: {
wd.no_focus = p_enabled;
@@ -2274,7 +2281,7 @@ bool DisplayServerX11::window_get_flag(WindowFlags p_flag, WindowID p_window) co
return wd.on_top;
} break;
case WINDOW_FLAG_TRANSPARENT: {
- //todo reimplement
+ return wd.layered_window;
} break;
case WINDOW_FLAG_NO_FOCUS: {
return wd.no_focus;
@@ -3181,6 +3188,15 @@ void DisplayServerX11::_window_changed(XEvent *event) {
}
}
+DisplayServer::WindowID DisplayServerX11::_get_focused_window_or_popup() const {
+ const List<WindowID>::Element *E = popup_list.back();
+ if (E) {
+ return E->get();
+ }
+
+ return last_focused_window;
+}
+
void DisplayServerX11::_dispatch_input_events(const Ref<InputEvent> &p_event) {
static_cast<DisplayServerX11 *>(get_singleton())->_dispatch_input_event(p_event);
}
@@ -3936,7 +3952,11 @@ void DisplayServerX11::process_events() {
// The X11 API requires filtering one-by-one through the motion
// notify events, in order to figure out which event is the one
// generated by warping the mouse pointer.
- WindowID focused_window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID focused_window_id = _get_focused_window_or_popup();
+ if (!windows.has(focused_window_id)) {
+ focused_window_id = MAIN_WINDOW_ID;
+ }
+
while (true) {
if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[focused_window_id].size.width / 2 && event.xmotion.y == windows[focused_window_id].size.height / 2) {
//this is likely the warp event since it was warped here
@@ -4426,13 +4446,41 @@ DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, W
DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
//Create window
- long visualMask = VisualScreenMask;
- int numberOfVisuals;
- XVisualInfo vInfoTemplate = {};
- vInfoTemplate.screen = DefaultScreen(x11_display);
- XVisualInfo *visualInfo = XGetVisualInfo(x11_display, visualMask, &vInfoTemplate, &numberOfVisuals);
+ XVisualInfo visualInfo;
+ bool vi_selected = false;
- Colormap colormap = XCreateColormap(x11_display, RootWindow(x11_display, vInfoTemplate.screen), visualInfo->visual, AllocNone);
+#ifdef GLES3_ENABLED
+ if (gl_manager) {
+ visualInfo = gl_manager->get_vi(x11_display);
+ vi_selected = true;
+ }
+#endif
+
+ if (!vi_selected) {
+ long visualMask = VisualScreenMask;
+ int numberOfVisuals;
+ XVisualInfo vInfoTemplate = {};
+ vInfoTemplate.screen = DefaultScreen(x11_display);
+ XVisualInfo *vi_list = XGetVisualInfo(x11_display, visualMask, &vInfoTemplate, &numberOfVisuals);
+ ERR_FAIL_COND_V(!vi_list, INVALID_WINDOW_ID);
+
+ visualInfo = vi_list[0];
+ if (OS::get_singleton()->is_layered_allowed()) {
+ for (int i = 0; i < numberOfVisuals; i++) {
+ XRenderPictFormat *pict_format = XRenderFindVisualFormat(x11_display, vi_list[i].visual);
+ if (!pict_format) {
+ continue;
+ }
+ visualInfo = vi_list[i];
+ if (pict_format->direct.alphaMask > 0) {
+ break;
+ }
+ }
+ }
+ XFree(vi_list);
+ }
+
+ Colormap colormap = XCreateColormap(x11_display, RootWindow(x11_display, visualInfo.screen), visualInfo.visual, AllocNone);
XSetWindowAttributes windowAttributes = {};
windowAttributes.colormap = colormap;
@@ -4442,6 +4490,13 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask;
+ if (OS::get_singleton()->is_layered_allowed()) {
+ windowAttributes.background_pixmap = None;
+ windowAttributes.background_pixel = 0;
+ windowAttributes.border_pixmap = None;
+ valuemask |= CWBackPixel;
+ }
+
WindowID id = window_id_counter++;
WindowData &wd = windows[id];
@@ -4465,7 +4520,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
}
{
- wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo->screen), p_rect.position.x, p_rect.position.y, p_rect.size.width > 0 ? p_rect.size.width : 1, p_rect.size.height > 0 ? p_rect.size.height : 1, 0, visualInfo->depth, InputOutput, visualInfo->visual, valuemask, &windowAttributes);
+ wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo.screen), p_rect.position.x, p_rect.position.y, p_rect.size.width > 0 ? p_rect.size.width : 1, p_rect.size.height > 0 ? p_rect.size.height : 1, 0, visualInfo.depth, InputOutput, visualInfo.visual, valuemask, &windowAttributes);
// Enable receiving notification when the window is initialized (MapNotify)
// so the focus can be set at the right time.
@@ -4602,8 +4657,6 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
XSync(x11_display, False);
//XSetErrorHandler(oldHandler);
-
- XFree(visualInfo);
}
window_set_mode(p_mode, id);
@@ -4867,6 +4920,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
}
show_window(main_window);
+ XSync(x11_display, False);
+ _validate_mode_on_map(main_window);
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
@@ -5013,17 +5068,13 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
cursor_set_shape(CURSOR_BUSY);
- XEvent xevent;
- while (XPending(x11_display) > 0) {
- XNextEvent(x11_display, &xevent);
- if (xevent.type == ConfigureNotify) {
- _window_changed(&xevent);
- } else if (xevent.type == MapNotify) {
- // Have we failed to set fullscreen while the window was unmapped?
- _validate_mode_on_map(main_window);
- }
+ // Search the X11 event queue for ConfigureNotify events and process all
+ // that are currently queued early, so we can get the final window size
+ // for correctly drawing of the bootsplash.
+ XEvent config_event;
+ while (XCheckTypedEvent(x11_display, ConfigureNotify, &config_event)) {
+ _window_changed(&config_event);
}
-
events_thread.start(_poll_events_thread, this);
_update_real_mouse_position(windows[MAIN_WINDOW_ID]);
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index dd9ac088d9..a5fa7613bc 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -159,6 +159,7 @@ class DisplayServerX11 : public DisplayServer {
bool minimized = false;
bool maximized = false;
bool is_popup = false;
+ bool layered_window = false;
Rect2i parent_safe_rect;
@@ -251,8 +252,6 @@ class DisplayServerX11 : public DisplayServer {
CursorShape current_cursor = CURSOR_ARROW;
HashMap<CursorShape, Vector<Variant>> cursors_cache;
- bool layered_window = false;
-
String rendering_driver;
void set_wm_fullscreen(bool p_enabled);
void set_wm_above(bool p_enabled);
@@ -285,6 +284,8 @@ class DisplayServerX11 : public DisplayServer {
Context context = CONTEXT_ENGINE;
+ WindowID _get_focused_window_or_popup() const;
+
void _send_window_event(const WindowData &wd, WindowEvent p_event);
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
void _dispatch_input_event(const Ref<InputEvent> &p_event);
diff --git a/platform/linuxbsd/gl_manager_x11.cpp b/platform/linuxbsd/gl_manager_x11.cpp
index d3fb1d6705..838be2c042 100644
--- a/platform/linuxbsd/gl_manager_x11.cpp
+++ b/platform/linuxbsd/gl_manager_x11.cpp
@@ -127,10 +127,6 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {
GLXFBConfig fbconfig = nullptr;
XVisualInfo *vi = nullptr;
- gl_display.x_swa.event_mask = StructureNotifyMask;
- gl_display.x_swa.border_pixel = 0;
- gl_display.x_valuemask = CWBorderPixel | CWColormap | CWEventMask;
-
if (OS::get_singleton()->is_layered_allowed()) {
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs_layered, &fbcount);
ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
@@ -156,12 +152,6 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {
XFree(fbc);
ERR_FAIL_COND_V(!fbconfig, ERR_UNCONFIGURED);
-
- gl_display.x_swa.background_pixmap = None;
- gl_display.x_swa.background_pixel = 0;
- gl_display.x_swa.border_pixmap = None;
- gl_display.x_valuemask |= CWBackPixel;
-
} else {
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
@@ -189,8 +179,6 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {
} break;
}
- gl_display.x_swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
-
XSync(x11_display, False);
XSetErrorHandler(oldHandler);
@@ -205,6 +193,10 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {
return OK;
}
+XVisualInfo GLManager_X11::get_vi(Display *p_display) {
+ return _displays[_find_or_create_display(p_display)].x_vi;
+}
+
Error GLManager_X11::window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height) {
// make sure vector is big enough...
// we can mirror the external vector, it is simpler
@@ -223,8 +215,6 @@ Error GLManager_X11::window_create(DisplayServer::WindowID p_window_id, ::Window
// the display could be invalid .. check NYI
GLDisplay &gl_display = _displays[win.gldisplay_id];
- //const XVisualInfo &vi = gl_display.x_vi;
- //XSetWindowAttributes &swa = gl_display.x_swa;
::Display *x11_display = gl_display.x11_display;
::Window &x11_window = win.x11_window;
@@ -266,7 +256,11 @@ void GLManager_X11::release_current() {
if (!_current_window) {
return;
}
- glXMakeCurrent(_x_windisp.x11_display, None, nullptr);
+
+ if (!glXMakeCurrent(_x_windisp.x11_display, None, nullptr)) {
+ ERR_PRINT("glXMakeCurrent failed");
+ }
+ _current_window = nullptr;
}
void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {
@@ -286,7 +280,9 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {
const GLDisplay &disp = get_display(win.gldisplay_id);
- glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context);
+ if (!glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context)) {
+ ERR_PRINT("glXMakeCurrent failed");
+ }
_internal_set_current_window(&win);
}
@@ -300,13 +296,12 @@ void GLManager_X11::make_current() {
return;
}
const GLDisplay &disp = get_current_display();
- glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context);
+ if (!glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context)) {
+ ERR_PRINT("glXMakeCurrent failed");
+ }
}
void GLManager_X11::swap_buffers() {
- // NO NEED TO CALL SWAP BUFFERS for each window...
- // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml
-
if (!_current_window) {
return;
}
@@ -315,13 +310,16 @@ void GLManager_X11::swap_buffers() {
return;
}
- // print_line("\tswap_buffers");
-
- // only for debugging without drawing anything
- // glClearColor(Math::randf(), 0, 1, 1);
- //glClear(GL_COLOR_BUFFER_BIT);
+ // On X11, when enabled, transparancy is always active, so clear alpha manually.
+ if (OS::get_singleton()->is_layered_allowed()) {
+ if (!DisplayServer::get_singleton()->window_get_flag(DisplayServer::WINDOW_FLAG_TRANSPARENT, _current_window->window_id)) {
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
- //const GLDisplay &disp = get_current_display();
glXSwapBuffers(_x_windisp.x11_display, _x_windisp.x11_window);
}
diff --git a/platform/linuxbsd/gl_manager_x11.h b/platform/linuxbsd/gl_manager_x11.h
index fb2c74a2b6..4f78c45c88 100644
--- a/platform/linuxbsd/gl_manager_x11.h
+++ b/platform/linuxbsd/gl_manager_x11.h
@@ -68,8 +68,6 @@ private:
GLManager_X11_Private *context = nullptr;
::Display *x11_display;
XVisualInfo x_vi;
- XSetWindowAttributes x_swa;
- unsigned long x_valuemask;
};
// just for convenience, window and display struct
@@ -102,6 +100,7 @@ private:
Error _create_context(GLDisplay &gl_display);
public:
+ XVisualInfo get_vi(Display *p_display);
Error window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height);
void window_destroy(DisplayServer::WindowID p_window_id);
void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 61faf3061c..f0d7b6ede5 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -686,10 +686,9 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
String renamed_path = path.get_base_dir() + "/" + file_name;
// Generates the .trashinfo file
- OS::Date date = OS::get_singleton()->get_date(false);
- OS::Time time = OS::get_singleton()->get_time(false);
- String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.minute);
- timestamp = vformat("%s%02d", timestamp, time.second); // vformat only supports up to 6 arguments.
+ OS::DateTime dt = OS::get_singleton()->get_datetime(false);
+ String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", dt.year, (int)dt.month, dt.day, dt.hour, dt.minute);
+ timestamp = vformat("%s%02d", timestamp, dt.second); // vformat only supports up to 6 arguments.
String trash_info = "[Trash Info]\nPath=" + path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;