diff options
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r-- | platform/linuxbsd/detect.py | 21 | ||||
-rw-r--r-- | platform/linuxbsd/export/export_plugin.cpp | 18 | ||||
-rw-r--r-- | platform/linuxbsd/freedesktop_portal_desktop.cpp | 2 | ||||
-rw-r--r-- | platform/linuxbsd/tts_linux.cpp | 10 | ||||
-rw-r--r-- | platform/linuxbsd/tts_linux.h | 4 | ||||
-rw-r--r-- | platform/linuxbsd/x11/detect_prime_x11.cpp | 14 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 356 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.h | 15 | ||||
-rw-r--r-- | platform/linuxbsd/x11/gl_manager_x11.cpp | 9 | ||||
-rw-r--r-- | platform/linuxbsd/x11/gl_manager_x11.h | 1 | ||||
-rw-r--r-- | platform/linuxbsd/x11/vulkan_context_x11.cpp | 14 | ||||
-rw-r--r-- | platform/linuxbsd/x11/vulkan_context_x11.h | 8 |
12 files changed, 372 insertions, 100 deletions
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 72bffceb1f..59cc6e7962 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -85,6 +85,16 @@ def configure(env: "Environment"): # gdb works fine without it though, so maybe our crash handler could too. env.Append(LINKFLAGS=["-rdynamic"]) + # Cross-compilation + # TODO: Support cross-compilation on architectures other than x86. + host_is_64_bit = sys.maxsize > 2**32 + if host_is_64_bit and env["arch"] == "x86_32": + env.Append(CCFLAGS=["-m32"]) + env.Append(LINKFLAGS=["-m32"]) + elif not host_is_64_bit and env["arch"] == "x86_64": + env.Append(CCFLAGS=["-m64"]) + env.Append(LINKFLAGS=["-m64"]) + # CPU architecture flags. if env["arch"] == "rv64": # G = General-purpose extensions, C = Compression extension (very common). @@ -469,22 +479,11 @@ def configure(env: "Environment"): if platform.system() == "FreeBSD": env.Append(LINKFLAGS=["-lkvm"]) - ## Cross-compilation - # TODO: Support cross-compilation on architectures other than x86. - host_is_64_bit = sys.maxsize > 2**32 - if host_is_64_bit and env["arch"] == "x86_32": - env.Append(CCFLAGS=["-m32"]) - env.Append(LINKFLAGS=["-m32", "-L/usr/lib/i386-linux-gnu"]) - elif not host_is_64_bit and env["arch"] == "x86_64": - env.Append(CCFLAGS=["-m64"]) - env.Append(LINKFLAGS=["-m64", "-L/usr/lib/i686-linux-gnu"]) - # Link those statically for portability if env["use_static_cpp"]: env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"]) if env["use_llvm"] and platform.system() != "FreeBSD": env["LINKCOM"] = env["LINKCOM"] + " -l:libatomic.a" - else: if env["use_llvm"] and platform.system() != "FreeBSD": env.Append(LIBS=["atomic"]) diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp index 9d1e058b76..64efcffae3 100644 --- a/platform/linuxbsd/export/export_plugin.cpp +++ b/platform/linuxbsd/export/export_plugin.cpp @@ -79,6 +79,7 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> Ref<DirAccess> tmp_app_dir = DirAccess::create_for_path(tmp_dir_path); if (export_as_zip) { if (tmp_app_dir.is_null()) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Could not create and open the directory: \"%s\""), tmp_dir_path)); return ERR_CANT_CREATE; } if (DirAccess::exists(tmp_dir_path)) { @@ -93,19 +94,18 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> // Export project. Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, path, p_flags); if (err != OK) { + // Message is supplied by the subroutine method. return err; } // Save console wrapper. - if (err == OK) { - int con_scr = p_preset->get("debug/export_console_wrapper"); - if ((con_scr == 1 && p_debug) || (con_scr == 2)) { - String scr_path = path.get_basename() + ".sh"; - err = _export_debug_script(p_preset, pkg_name, path.get_file(), scr_path); - FileAccess::set_unix_permissions(scr_path, 0755); - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Console Export"), TTR("Could not create console wrapper.")); - } + int con_scr = p_preset->get("debug/export_console_wrapper"); + if ((con_scr == 1 && p_debug) || (con_scr == 2)) { + String scr_path = path.get_basename() + ".sh"; + err = _export_debug_script(p_preset, pkg_name, path.get_file(), scr_path); + FileAccess::set_unix_permissions(scr_path, 0755); + if (err != OK) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Console Export"), TTR("Could not create console wrapper.")); } } diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index d9aa98ba70..6a5b5b8064 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -434,7 +434,7 @@ void FreeDesktopPortalDesktop::_file_dialog_callback(const Callable &p_callable, p_callable.callp(args, 3, ret, ce); if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat(RTR("Failed to execute file dialogs callback: %s."), Variant::get_callable_error_text(p_callable, args, 3, ce))); + ERR_PRINT(vformat("Failed to execute file dialogs callback: %s.", Variant::get_callable_error_text(p_callable, args, 3, ce))); } } diff --git a/platform/linuxbsd/tts_linux.cpp b/platform/linuxbsd/tts_linux.cpp index 96745ab8ae..46291bb4da 100644 --- a/platform/linuxbsd/tts_linux.cpp +++ b/platform/linuxbsd/tts_linux.cpp @@ -82,11 +82,11 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) { void TTS_Linux::speech_event_index_mark(size_t p_msg_id, size_t p_client_id, SPDNotificationType p_type, char *p_index_mark) { TTS_Linux *tts = TTS_Linux::get_singleton(); if (tts) { - callable_mp(tts, &TTS_Linux::_speech_index_mark).call_deferred(p_msg_id, p_client_id, (int)p_type, String::utf8(p_index_mark)); + callable_mp(tts, &TTS_Linux::_speech_index_mark).call_deferred((int)p_msg_id, (int)p_type, String::utf8(p_index_mark)); } } -void TTS_Linux::_speech_index_mark(size_t p_msg_id, size_t p_client_id, int p_type, const String &p_index_mark) { +void TTS_Linux::_speech_index_mark(int p_msg_id, int p_type, const String &p_index_mark) { _THREAD_SAFE_METHOD_ if (ids.has(p_msg_id)) { @@ -97,7 +97,7 @@ void TTS_Linux::_speech_index_mark(size_t p_msg_id, size_t p_client_id, int p_ty void TTS_Linux::speech_event_callback(size_t p_msg_id, size_t p_client_id, SPDNotificationType p_type) { TTS_Linux *tts = TTS_Linux::get_singleton(); if (tts) { - callable_mp(tts, &TTS_Linux::_speech_event).call_deferred(p_msg_id, p_client_id, (int)p_type); + callable_mp(tts, &TTS_Linux::_speech_event).call_deferred((int)p_msg_id, (int)p_type); } } @@ -119,7 +119,7 @@ void TTS_Linux::_load_voices() { } } -void TTS_Linux::_speech_event(size_t p_msg_id, size_t p_client_id, int p_type) { +void TTS_Linux::_speech_event(int p_msg_id, int p_type) { _THREAD_SAFE_METHOD_ if (!paused && ids.has(p_msg_id)) { @@ -226,7 +226,7 @@ void TTS_Linux::speak(const String &p_text, const String &p_voice, int p_volume, if (is_paused()) { resume(); } else { - _speech_event(0, 0, (int)SPD_EVENT_BEGIN); + _speech_event(0, (int)SPD_EVENT_BEGIN); } } diff --git a/platform/linuxbsd/tts_linux.h b/platform/linuxbsd/tts_linux.h index ec68219689..2a3d33221d 100644 --- a/platform/linuxbsd/tts_linux.h +++ b/platform/linuxbsd/tts_linux.h @@ -72,8 +72,8 @@ class TTS_Linux : public Object { protected: void _load_voices(); - void _speech_event(size_t p_msg_id, size_t p_client_id, int p_type); - void _speech_index_mark(size_t p_msg_id, size_t p_client_id, int p_type, const String &p_index_mark); + void _speech_event(int p_msg_id, int p_type); + void _speech_index_mark(int p_msg_id, int p_type, const String &p_index_mark); public: static TTS_Linux *get_singleton(); diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp index 2b5776ce54..c2cb02b937 100644 --- a/platform/linuxbsd/x11/detect_prime_x11.cpp +++ b/platform/linuxbsd/x11/detect_prime_x11.cpp @@ -137,6 +137,19 @@ void create_context() { XFree(vi); } +int silent_error_handler(Display *display, XErrorEvent *error) { + static char message[1024]; + XGetErrorText(display, error->error_code, message, sizeof(message)); + print_verbose(vformat("XServer error: %s" + "\n Major opcode of failed request: %d" + "\n Serial number of failed request: %d" + "\n Current serial number in output stream: %d", + String::utf8(message), (uint64_t)error->request_code, (uint64_t)error->minor_code, (uint64_t)error->serial)); + + quick_exit(1); + return 0; +} + int detect_prime() { pid_t p; int priorities[2] = {}; @@ -189,6 +202,7 @@ int detect_prime() { // cleaning up these processes, and fork() makes a copy // of all globals. CoreGlobals::leak_reporting_enabled = false; + XSetErrorHandler(&silent_error_handler); char string[201]; diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index fe81da76d3..1434342bbc 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -39,6 +39,7 @@ #include "core/math/math_funcs.h" #include "core/string/print_string.h" #include "core/string/ustring.h" +#include "drivers/png/png_driver_common.h" #include "main/main.h" #include "scene/resources/atlas_texture.h" @@ -519,7 +520,7 @@ Bool DisplayServerX11::_predicate_clipboard_selection(Display *display, XEvent * } Bool DisplayServerX11::_predicate_clipboard_incr(Display *display, XEvent *event, XPointer arg) { - if (event->type == PropertyNotify && event->xproperty.state == PropertyNewValue) { + if (event->type == PropertyNotify && event->xproperty.state == PropertyNewValue && event->xproperty.atom == *(Atom *)arg) { return True; } else { return False; @@ -593,7 +594,7 @@ String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, A // Non-blocking wait for next event and remove it from the queue. XEvent ev; - while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_incr, nullptr)) { + while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_incr, (XPointer)&selection)) { result = XGetWindowProperty(x11_display, x11_window, selection, // selection type 0, LONG_MAX, // offset - len @@ -664,6 +665,74 @@ String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, A return ret; } +Atom DisplayServerX11::_clipboard_get_image_target(Atom p_source, Window x11_window) const { + Atom target = XInternAtom(x11_display, "TARGETS", 0); + Atom png = XInternAtom(x11_display, "image/png", 0); + Atom *valid_targets = nullptr; + unsigned long atom_count = 0; + + Window selection_owner = XGetSelectionOwner(x11_display, p_source); + if (selection_owner != None && selection_owner != x11_window) { + // Block events polling while processing selection events. + MutexLock mutex_lock(events_mutex); + + Atom selection = XA_PRIMARY; + XConvertSelection(x11_display, p_source, target, selection, x11_window, CurrentTime); + + XFlush(x11_display); + + // Blocking wait for predicate to be True and remove the event from the queue. + XEvent event; + XIfEvent(x11_display, &event, _predicate_clipboard_selection, (XPointer)&x11_window); + // Do not get any data, see how much data is there. + Atom type; + int format, result; + unsigned long len, bytes_left, dummy; + XGetWindowProperty(x11_display, x11_window, + selection, // Tricky.. + 0, 0, // offset - len + 0, // Delete 0==FALSE + XA_ATOM, // flag + &type, // return type + &format, // return format + &len, &bytes_left, // data length + (unsigned char **)&valid_targets); + + if (valid_targets) { + XFree(valid_targets); + valid_targets = nullptr; + } + + if (type == XA_ATOM && bytes_left > 0) { + // Data is ready and can be processed all at once. + result = XGetWindowProperty(x11_display, x11_window, + selection, 0, bytes_left / 4, 0, + XA_ATOM, &type, &format, + &len, &dummy, (unsigned char **)&valid_targets); + if (result == Success) { + atom_count = len; + } else { + print_verbose("Failed to get selection data."); + return None; + } + } else { + return None; + } + } else { + return None; + } + for (unsigned long i = 0; i < atom_count; i++) { + Atom atom = valid_targets[i]; + if (atom == png) { + XFree(valid_targets); + return png; + } + } + + XFree(valid_targets); + return None; +} + String DisplayServerX11::_clipboard_get(Atom p_source, Window x11_window) const { String ret; Atom utf8_atom = XInternAtom(x11_display, "UTF8_STRING", True); @@ -702,6 +771,158 @@ String DisplayServerX11::clipboard_get_primary() const { return ret; } +Ref<Image> DisplayServerX11::clipboard_get_image() const { + _THREAD_SAFE_METHOD_ + Atom clipboard = XInternAtom(x11_display, "CLIPBOARD", 0); + Window x11_window = windows[MAIN_WINDOW_ID].x11_window; + Ref<Image> ret; + Atom target = _clipboard_get_image_target(clipboard, x11_window); + if (target == None) { + return ret; + } + + Window selection_owner = XGetSelectionOwner(x11_display, clipboard); + + if (selection_owner != None && selection_owner != x11_window) { + // Block events polling while processing selection events. + MutexLock mutex_lock(events_mutex); + + // Identifier for the property the other window + // will send the converted data to. + Atom transfer_prop = XA_PRIMARY; + XConvertSelection(x11_display, + clipboard, // source selection + target, // format to convert to + transfer_prop, // output property + x11_window, CurrentTime); + + XFlush(x11_display); + + // Blocking wait for predicate to be True and remove the event from the queue. + XEvent event; + XIfEvent(x11_display, &event, _predicate_clipboard_selection, (XPointer)&x11_window); + + // Do not get any data, see how much data is there. + Atom type; + int format, result; + unsigned long len, bytes_left, dummy; + unsigned char *data; + XGetWindowProperty(x11_display, x11_window, + transfer_prop, // Property data is transferred through + 0, 1, // offset, len (4 so we can get the size if INCR is used) + 0, // Delete 0==FALSE + AnyPropertyType, // flag + &type, // return type + &format, // return format + &len, &bytes_left, // data length + &data); + + if (type == XInternAtom(x11_display, "INCR", 0)) { + ERR_FAIL_COND_V_MSG(len != 1, ret, "Incremental transfer initial value was not length."); + + // Data is going to be received incrementally. + DEBUG_LOG_X11("INCR selection started.\n"); + + LocalVector<uint8_t> incr_data; + uint32_t data_size = 0; + bool success = false; + + // Initial response is the lower bound of the length of the transferred data. + incr_data.resize(*(unsigned long *)data); + XFree(data); + data = nullptr; + + // Delete INCR property to notify the owner. + XDeleteProperty(x11_display, x11_window, transfer_prop); + + // Process events from the queue. + bool done = false; + while (!done) { + if (!_wait_for_events()) { + // Error or timeout, abort. + break; + } + // Non-blocking wait for next event and remove it from the queue. + XEvent ev; + while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_incr, (XPointer)&transfer_prop)) { + result = XGetWindowProperty(x11_display, x11_window, + transfer_prop, // output property + 0, LONG_MAX, // offset - len + True, // delete property to notify the owner + AnyPropertyType, // flag + &type, // return type + &format, // return format + &len, &bytes_left, // data length + &data); + + DEBUG_LOG_X11("PropertyNotify: len=%lu, format=%i\n", len, format); + + if (result == Success) { + if (data && (len > 0)) { + uint32_t prev_size = incr_data.size(); + // New chunk, resize to be safe and append data. + incr_data.resize(MAX(data_size + len, prev_size)); + memcpy(incr_data.ptr() + data_size, data, len); + data_size += len; + } else if (!(format == 0 && len == 0)) { + // For unclear reasons the first GetWindowProperty always returns a length and format of 0. + // Otherwise, last chunk, process finished. + done = true; + success = true; + } + } else { + print_verbose("Failed to get selection data chunk."); + done = true; + } + + if (data) { + XFree(data); + data = nullptr; + } + + if (done) { + break; + } + } + } + + if (success && (data_size > 0)) { + ret.instantiate(); + PNGDriverCommon::png_to_image(incr_data.ptr(), incr_data.size(), false, ret); + } + } else if (bytes_left > 0) { + if (data) { + XFree(data); + data = nullptr; + } + // Data is ready and can be processed all at once. + result = XGetWindowProperty(x11_display, x11_window, + transfer_prop, 0, bytes_left + 4, 0, + AnyPropertyType, &type, &format, + &len, &dummy, &data); + if (result == Success) { + ret.instantiate(); + PNGDriverCommon::png_to_image((uint8_t *)data, bytes_left, false, ret); + } else { + print_verbose("Failed to get selection data."); + } + + if (data) { + XFree(data); + } + } + } + + return ret; +} + +bool DisplayServerX11::clipboard_has_image() const { + Atom target = _clipboard_get_image_target( + XInternAtom(x11_display, "CLIPBOARD", 0), + windows[MAIN_WINDOW_ID].x11_window); + return target != None; +} + Bool DisplayServerX11::_predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg) { if (event->xany.window == *(Window *)arg) { return (event->type == SelectionRequest) || @@ -1350,7 +1571,7 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { //Use xrandr to get screen refresh rate. if (xrandr_ext_ok) { - XRRScreenResources *screen_info = XRRGetScreenResources(x11_display, windows[MAIN_WINDOW_ID].x11_window); + XRRScreenResources *screen_info = XRRGetScreenResourcesCurrent(x11_display, windows[MAIN_WINDOW_ID].x11_window); if (screen_info) { RRMode current_mode = 0; xrr_monitor_info *monitors = nullptr; @@ -1486,9 +1707,9 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { window_set_transient(p_id, INVALID_WINDOW_ID); } -#ifdef VULKAN_ENABLED - if (context_vulkan) { - context_vulkan->window_destroy(p_id); +#if defined(RD_ENABLED) + if (context_rd) { + context_rd->window_destroy(p_id); } #endif #ifdef GLES3_ENABLED @@ -2012,9 +2233,9 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) { } // Keep rendering context window size in sync -#if defined(VULKAN_ENABLED) - if (context_vulkan) { - context_vulkan->window_resize(p_window, xwa.width, xwa.height); +#if defined(RD_ENABLED) + if (context_rd) { + context_rd->window_resize(p_window, xwa.width, xwa.height); } #endif #if defined(GLES3_ENABLED) @@ -3654,7 +3875,7 @@ void DisplayServerX11::_xim_preedit_draw_callback(::XIM xim, ::XPointer client_d ds->im_selection = Point2i(); } - OS_Unix::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); + OS_Unix::get_singleton()->get_main_loop()->call_deferred(SNAME("notification"), MainLoop::NOTIFICATION_OS_IME_UPDATE); } } @@ -3724,9 +3945,9 @@ void DisplayServerX11::_window_changed(XEvent *event) { wd.position = new_rect.position; wd.size = new_rect.size; -#if defined(VULKAN_ENABLED) - if (context_vulkan) { - context_vulkan->window_resize(window_id, wd.size.width, wd.size.height); +#if defined(RD_ENABLED) + if (context_rd) { + context_rd->window_resize(window_id, wd.size.width, wd.size.height); } #endif #if defined(GLES3_ENABLED) @@ -5023,9 +5244,9 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) { void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ -#if defined(VULKAN_ENABLED) - if (context_vulkan) { - context_vulkan->set_vsync_mode(p_window, p_vsync_mode); +#if defined(RD_ENABLED) + if (context_rd) { + context_rd->set_vsync_mode(p_window, p_vsync_mode); } #endif @@ -5041,9 +5262,9 @@ void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo DisplayServer::VSyncMode DisplayServerX11::window_get_vsync_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ -#if defined(VULKAN_ENABLED) - if (context_vulkan) { - return context_vulkan->get_vsync_mode(p_window); +#if defined(RD_ENABLED) + if (context_rd) { + return context_rd->get_vsync_mode(p_window); } #endif #if defined(GLES3_ENABLED) @@ -5385,10 +5606,21 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V _update_size_hints(id); -#if defined(VULKAN_ENABLED) - if (context_vulkan) { - Error err = context_vulkan->window_create(id, p_vsync_mode, wd.x11_window, x11_display, win_rect.size.width, win_rect.size.height); - ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window"); +#if defined(RD_ENABLED) + if (context_rd) { + union { +#ifdef VULKAN_ENABLED + VulkanContextX11::WindowPlatformData vulkan; +#endif + } wpd; +#ifdef VULKAN_ENABLED + if (rendering_driver == "vulkan") { + wpd.vulkan.window = wd.x11_window; + wpd.vulkan.display = x11_display; + } +#endif + Error err = context_rd->window_create(id, p_vsync_mode, win_rect.size.width, win_rect.size.height, &wpd); + ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s window", context_rd->get_api_name())); } #endif #ifdef GLES3_ENABLED @@ -5787,14 +6019,19 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode rendering_driver = p_rendering_driver; bool driver_found = false; +#if defined(RD_ENABLED) #if defined(VULKAN_ENABLED) if (rendering_driver == "vulkan") { - context_vulkan = memnew(VulkanContextX11); - if (context_vulkan->initialize() != OK) { - memdelete(context_vulkan); - context_vulkan = nullptr; + context_rd = memnew(VulkanContextX11); + } +#endif + + if (context_rd) { + if (context_rd->initialize() != OK) { + memdelete(context_rd); + context_rd = nullptr; r_error = ERR_CANT_CREATE; - ERR_FAIL_MSG("Could not initialize Vulkan"); + ERR_FAIL_MSG(vformat("Could not initialize %s", context_rd->get_api_name())); } driver_found = true; } @@ -5844,33 +6081,36 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } } if (rendering_driver == "opengl3") { - GLManager_X11::ContextType opengl_api_type = GLManager_X11::GLES_3_0_COMPATIBLE; - - gl_manager = memnew(GLManager_X11(p_resolution, opengl_api_type)); - - if (gl_manager->initialize(x11_display) != OK) { + gl_manager = memnew(GLManager_X11(p_resolution, GLManager_X11::GLES_3_0_COMPATIBLE)); + if (gl_manager->initialize(x11_display) != OK || gl_manager->open_display(x11_display) != OK) { memdelete(gl_manager); gl_manager = nullptr; - r_error = ERR_UNAVAILABLE; - return; + bool fallback = GLOBAL_GET("rendering/gl_compatibility/fallback_to_gles"); + if (fallback) { + WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES."); + rendering_driver = "opengl3_es"; + } else { + r_error = ERR_UNAVAILABLE; + ERR_FAIL_MSG("Could not initialize OpenGL."); + } + } else { + driver_found = true; + RasterizerGLES3::make_current(true); } - driver_found = true; - - RasterizerGLES3::make_current(true); } + if (rendering_driver == "opengl3_es") { gl_manager_egl = memnew(GLManagerEGL_X11); - if (gl_manager_egl->initialize() != OK) { memdelete(gl_manager_egl); gl_manager_egl = nullptr; r_error = ERR_UNAVAILABLE; - return; + ERR_FAIL_MSG("Could not initialize OpenGLES."); } driver_found = true; - RasterizerGLES3::make_current(false); } + #endif if (!driver_found) { r_error = ERR_UNAVAILABLE; @@ -5884,7 +6124,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode if (p_screen == SCREEN_OF_MAIN_WINDOW) { p_screen = SCREEN_PRIMARY; } - window_position = screen_get_position(p_screen) + (screen_get_size(p_screen) - p_resolution) / 2; + Rect2i scr_rect = screen_get_usable_rect(p_screen); + window_position = scr_rect.position + (scr_rect.size - p_resolution) / 2; } WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution)); @@ -5899,11 +6140,10 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } show_window(main_window); -#if defined(VULKAN_ENABLED) - if (rendering_driver == "vulkan") { - //temporary - rendering_device_vulkan = memnew(RenderingDeviceVulkan); - rendering_device_vulkan->initialize(context_vulkan); +#if defined(RD_ENABLED) + if (context_rd) { + rendering_device = memnew(RenderingDevice); + rendering_device->initialize(context_rd); RendererCompositorRD::make_current(); } @@ -6077,9 +6317,9 @@ DisplayServerX11::~DisplayServerX11() { //destroy all windows for (KeyValue<WindowID, WindowData> &E : windows) { -#ifdef VULKAN_ENABLED - if (context_vulkan) { - context_vulkan->window_destroy(E.key); +#if defined(RD_ENABLED) + if (context_rd) { + context_rd->window_destroy(E.key); } #endif #ifdef GLES3_ENABLED @@ -6121,16 +6361,16 @@ DisplayServerX11::~DisplayServerX11() { #endif //destroy drivers -#if defined(VULKAN_ENABLED) - if (rendering_device_vulkan) { - rendering_device_vulkan->finalize(); - memdelete(rendering_device_vulkan); - rendering_device_vulkan = nullptr; +#if defined(RD_ENABLED) + if (rendering_device) { + rendering_device->finalize(); + memdelete(rendering_device); + rendering_device = nullptr; } - if (context_vulkan) { - memdelete(context_vulkan); - context_vulkan = nullptr; + if (context_rd) { + memdelete(context_rd); + context_rd = nullptr; } #endif diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index 9706a4aa11..ac2c7843f6 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -57,10 +57,12 @@ #include "x11/gl_manager_x11_egl.h" #endif +#if defined(RD_ENABLED) +#include "servers/rendering/rendering_device.h" + #if defined(VULKAN_ENABLED) #include "x11/vulkan_context_x11.h" - -#include "drivers/vulkan/rendering_device_vulkan.h" +#endif #endif #if defined(DBUS_ENABLED) @@ -141,9 +143,9 @@ class DisplayServerX11 : public DisplayServer { GLManager_X11 *gl_manager = nullptr; GLManagerEGL_X11 *gl_manager_egl = nullptr; #endif -#if defined(VULKAN_ENABLED) - VulkanContextX11 *context_vulkan = nullptr; - RenderingDeviceVulkan *rendering_device_vulkan = nullptr; +#if defined(RD_ENABLED) + ApiContextRD *context_rd = nullptr; + RenderingDevice *rendering_device = nullptr; #endif #if defined(DBUS_ENABLED) @@ -304,6 +306,7 @@ class DisplayServerX11 : public DisplayServer { String _clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const; String _clipboard_get(Atom p_source, Window x11_window) const; + Atom _clipboard_get_image_target(Atom p_source, Window x11_window) const; void _clipboard_transfer_ownership(Atom p_source, Window x11_window) const; bool do_mouse_warp = false; @@ -408,6 +411,8 @@ public: virtual void clipboard_set(const String &p_text) override; virtual String clipboard_get() const override; + virtual Ref<Image> clipboard_get_image() const override; + virtual bool clipboard_has_image() const override; virtual void clipboard_set_primary(const String &p_text) override; virtual String clipboard_get_primary() const override; diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp index 95947301cf..602dd784e0 100644 --- a/platform/linuxbsd/x11/gl_manager_x11.cpp +++ b/platform/linuxbsd/x11/gl_manager_x11.cpp @@ -208,6 +208,15 @@ XVisualInfo GLManager_X11::get_vi(Display *p_display, Error &r_error) { return _displays[display_id].x_vi; } +Error GLManager_X11::open_display(Display *p_display) { + int gldisplay_id = _find_or_create_display(p_display); + if (gldisplay_id < 0) { + return ERR_CANT_CREATE; + } else { + return OK; + } +} + 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 diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h index d3a25506a8..235c7d22f9 100644 --- a/platform/linuxbsd/x11/gl_manager_x11.h +++ b/platform/linuxbsd/x11/gl_manager_x11.h @@ -129,6 +129,7 @@ public: void *get_glx_context(DisplayServer::WindowID p_window_id); + Error open_display(Display *p_display); GLManager_X11(const Vector2i &p_size, ContextType p_context_type); ~GLManager_X11(); }; diff --git a/platform/linuxbsd/x11/vulkan_context_x11.cpp b/platform/linuxbsd/x11/vulkan_context_x11.cpp index d240480f61..3eee1706b0 100644 --- a/platform/linuxbsd/x11/vulkan_context_x11.cpp +++ b/platform/linuxbsd/x11/vulkan_context_x11.cpp @@ -42,15 +42,15 @@ const char *VulkanContextX11::_get_platform_surface_extension() const { return VK_KHR_XLIB_SURFACE_EXTENSION_NAME; } -Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height) { - VkXlibSurfaceCreateInfoKHR createInfo; +Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) { + const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data; + + VkXlibSurfaceCreateInfoKHR createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; - createInfo.pNext = nullptr; - createInfo.flags = 0; - createInfo.dpy = p_display; - createInfo.window = p_window; + createInfo.dpy = wpd->display; + createInfo.window = wpd->window; - VkSurfaceKHR surface; + VkSurfaceKHR surface = VK_NULL_HANDLE; VkResult err = vkCreateXlibSurfaceKHR(get_instance(), &createInfo, nullptr, &surface); ERR_FAIL_COND_V(err, ERR_CANT_CREATE); return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height); diff --git a/platform/linuxbsd/x11/vulkan_context_x11.h b/platform/linuxbsd/x11/vulkan_context_x11.h index 294fdc710e..2390326b44 100644 --- a/platform/linuxbsd/x11/vulkan_context_x11.h +++ b/platform/linuxbsd/x11/vulkan_context_x11.h @@ -38,10 +38,14 @@ #include <X11/Xlib.h> class VulkanContextX11 : public VulkanContext { - virtual const char *_get_platform_surface_extension() const; + virtual const char *_get_platform_surface_extension() const override final; public: - Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height); + struct WindowPlatformData { + ::Window window; + Display *display; + }; + virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final; VulkanContextX11(); ~VulkanContextX11(); |