You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
Effective DisplayServer separation, rename X11 -> LinuxBSD
This commit is contained in:
committed by
Juan Linietsky
parent
4396e98834
commit
f8a79a97c7
23
platform/linuxbsd/SCsub
Normal file
23
platform/linuxbsd/SCsub
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
from platform_methods import run_in_subprocess
|
||||
import platform_linuxbsd_builders
|
||||
|
||||
common_x11 = [
|
||||
"crash_handler_linuxbsd.cpp",
|
||||
"os_linuxbsd.cpp",
|
||||
"joypad_linux.cpp",
|
||||
"context_gl_x11.cpp",
|
||||
"detect_prime_x11.cpp",
|
||||
"display_server_x11.cpp",
|
||||
"vulkan_context_x11.cpp",
|
||||
"key_mapping_x11.cpp",
|
||||
|
||||
]
|
||||
|
||||
prog = env.add_program('#bin/godot', ['godot_linuxbsd.cpp'] + common_x11)
|
||||
|
||||
if (env["debug_symbols"] == "full" or env["debug_symbols"] == "yes") and env["separate_debug_symbols"]:
|
||||
env.AddPostAction(prog, run_in_subprocess(platform_linuxbsd_builders.make_debug_linuxbsd))
|
||||
265
platform/linuxbsd/context_gl_x11.cpp
Normal file
265
platform/linuxbsd/context_gl_x11.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/*************************************************************************/
|
||||
/* context_gl_x11.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "context_gl_x11.h"
|
||||
|
||||
#ifdef X11_ENABLED
|
||||
#if defined(OPENGL_ENABLED)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define GLX_GLXEXT_PROTOTYPES
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glxext.h>
|
||||
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
|
||||
typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
|
||||
|
||||
struct ContextGL_X11_Private {
|
||||
|
||||
::GLXContext glx_context;
|
||||
};
|
||||
|
||||
void ContextGL_X11::release_current() {
|
||||
|
||||
glXMakeCurrent(x11_display, None, NULL);
|
||||
}
|
||||
|
||||
void ContextGL_X11::make_current() {
|
||||
|
||||
glXMakeCurrent(x11_display, x11_window, p->glx_context);
|
||||
}
|
||||
|
||||
void ContextGL_X11::swap_buffers() {
|
||||
|
||||
glXSwapBuffers(x11_display, x11_window);
|
||||
}
|
||||
|
||||
static bool ctxErrorOccurred = false;
|
||||
static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {
|
||||
ctxErrorOccurred = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_class_hint(Display *p_display, Window p_window) {
|
||||
XClassHint *classHint;
|
||||
|
||||
/* set the name and class hints for the window manager to use */
|
||||
classHint = XAllocClassHint();
|
||||
if (classHint) {
|
||||
classHint->res_name = (char *)"Godot_Engine";
|
||||
classHint->res_class = (char *)"Godot";
|
||||
}
|
||||
XSetClassHint(p_display, p_window, classHint);
|
||||
XFree(classHint);
|
||||
}
|
||||
|
||||
Error ContextGL_X11::initialize() {
|
||||
|
||||
//const char *extensions = glXQueryExtensionsString(x11_display, DefaultScreen(x11_display));
|
||||
|
||||
GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
|
||||
|
||||
ERR_FAIL_COND_V(!glXCreateContextAttribsARB, ERR_UNCONFIGURED);
|
||||
|
||||
static int visual_attribs[] = {
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_DOUBLEBUFFER, true,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
None
|
||||
};
|
||||
|
||||
static int visual_attribs_layered[] = {
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_DOUBLEBUFFER, true,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
None
|
||||
};
|
||||
|
||||
int fbcount;
|
||||
GLXFBConfig fbconfig = 0;
|
||||
XVisualInfo *vi = NULL;
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
swa.border_pixel = 0;
|
||||
unsigned long 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);
|
||||
|
||||
for (int i = 0; i < fbcount; i++) {
|
||||
vi = (XVisualInfo *)glXGetVisualFromFBConfig(x11_display, fbc[i]);
|
||||
if (!vi)
|
||||
continue;
|
||||
|
||||
XRenderPictFormat *pict_format = XRenderFindVisualFormat(x11_display, vi->visual);
|
||||
if (!pict_format) {
|
||||
XFree(vi);
|
||||
vi = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
fbconfig = fbc[i];
|
||||
if (pict_format->direct.alphaMask > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(fbc);
|
||||
ERR_FAIL_COND_V(!fbconfig, ERR_UNCONFIGURED);
|
||||
|
||||
swa.background_pixmap = None;
|
||||
swa.background_pixel = 0;
|
||||
swa.border_pixmap = None;
|
||||
valuemask |= CWBackPixel;
|
||||
|
||||
} else {
|
||||
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
|
||||
ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
|
||||
|
||||
vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
|
||||
|
||||
fbconfig = fbc[0];
|
||||
XFree(fbc);
|
||||
}
|
||||
|
||||
int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&ctxErrorHandler);
|
||||
|
||||
switch (context_type) {
|
||||
case GLES_2_0_COMPATIBLE: {
|
||||
|
||||
p->glx_context = glXCreateNewContext(x11_display, fbconfig, GLX_RGBA_TYPE, 0, true);
|
||||
ERR_FAIL_COND_V(!p->glx_context, ERR_UNCONFIGURED);
|
||||
} break;
|
||||
}
|
||||
|
||||
swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
|
||||
x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, vi->depth, InputOutput, vi->visual, valuemask, &swa);
|
||||
XStoreName(x11_display, x11_window, "Godot Engine");
|
||||
|
||||
ERR_FAIL_COND_V(!x11_window, ERR_UNCONFIGURED);
|
||||
set_class_hint(x11_display, x11_window);
|
||||
XMapWindow(x11_display, x11_window);
|
||||
|
||||
XSync(x11_display, False);
|
||||
XSetErrorHandler(oldHandler);
|
||||
|
||||
glXMakeCurrent(x11_display, x11_window, p->glx_context);
|
||||
|
||||
XFree(vi);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int ContextGL_X11::get_window_width() {
|
||||
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes(x11_display, x11_window, &xwa);
|
||||
|
||||
return xwa.width;
|
||||
}
|
||||
|
||||
int ContextGL_X11::get_window_height() {
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes(x11_display, x11_window, &xwa);
|
||||
|
||||
return xwa.height;
|
||||
}
|
||||
|
||||
void ContextGL_X11::set_use_vsync(bool p_use) {
|
||||
static bool setup = false;
|
||||
static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = NULL;
|
||||
static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = NULL;
|
||||
static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = NULL;
|
||||
|
||||
if (!setup) {
|
||||
setup = true;
|
||||
String extensions = glXQueryExtensionsString(x11_display, DefaultScreen(x11_display));
|
||||
if (extensions.find("GLX_EXT_swap_control") != -1)
|
||||
glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT");
|
||||
if (extensions.find("GLX_MESA_swap_control") != -1)
|
||||
glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA");
|
||||
if (extensions.find("GLX_SGI_swap_control") != -1)
|
||||
glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI");
|
||||
}
|
||||
int val = p_use ? 1 : 0;
|
||||
if (glXSwapIntervalMESA) {
|
||||
glXSwapIntervalMESA(val);
|
||||
} else if (glXSwapIntervalSGI) {
|
||||
glXSwapIntervalSGI(val);
|
||||
} else if (glXSwapIntervalEXT) {
|
||||
GLXDrawable drawable = glXGetCurrentDrawable();
|
||||
glXSwapIntervalEXT(x11_display, drawable, val);
|
||||
} else
|
||||
return;
|
||||
use_vsync = p_use;
|
||||
}
|
||||
bool ContextGL_X11::is_using_vsync() const {
|
||||
|
||||
return use_vsync;
|
||||
}
|
||||
|
||||
ContextGL_X11::ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, ContextType p_context_type) :
|
||||
x11_window(p_x11_window) {
|
||||
|
||||
default_video_mode = p_default_video_mode;
|
||||
x11_display = p_x11_display;
|
||||
|
||||
context_type = p_context_type;
|
||||
|
||||
double_buffer = false;
|
||||
direct_render = false;
|
||||
glx_minor = glx_major = 0;
|
||||
p = memnew(ContextGL_X11_Private);
|
||||
p->glx_context = 0;
|
||||
use_vsync = false;
|
||||
}
|
||||
|
||||
ContextGL_X11::~ContextGL_X11() {
|
||||
release_current();
|
||||
glXDestroyContext(x11_display, p->glx_context);
|
||||
memdelete(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
81
platform/linuxbsd/context_gl_x11.h
Normal file
81
platform/linuxbsd/context_gl_x11.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*************************************************************************/
|
||||
/* context_gl_x11.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef CONTEXT_GL_X11_H
|
||||
#define CONTEXT_GL_X11_H
|
||||
|
||||
#ifdef X11_ENABLED
|
||||
|
||||
#if defined(OPENGL_ENABLED)
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
struct ContextGL_X11_Private;
|
||||
|
||||
class ContextGL_X11 {
|
||||
|
||||
public:
|
||||
enum ContextType {
|
||||
GLES_2_0_COMPATIBLE,
|
||||
};
|
||||
|
||||
private:
|
||||
ContextGL_X11_Private *p;
|
||||
OS::VideoMode default_video_mode;
|
||||
::Display *x11_display;
|
||||
::Window &x11_window;
|
||||
bool double_buffer;
|
||||
bool direct_render;
|
||||
int glx_minor, glx_major;
|
||||
bool use_vsync;
|
||||
ContextType context_type;
|
||||
|
||||
public:
|
||||
void release_current();
|
||||
void make_current();
|
||||
void swap_buffers();
|
||||
int get_window_width();
|
||||
int get_window_height();
|
||||
|
||||
Error initialize();
|
||||
|
||||
void set_use_vsync(bool p_use);
|
||||
bool is_using_vsync() const;
|
||||
|
||||
ContextGL_X11(::Display *p_x11_display, ::Window &p_x11_window, const OS::VideoMode &p_default_video_mode, ContextType p_context_type);
|
||||
~ContextGL_X11();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
149
platform/linuxbsd/crash_handler_linuxbsd.cpp
Normal file
149
platform/linuxbsd/crash_handler_linuxbsd.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/*************************************************************************/
|
||||
/* crash_handler_linuxbsd.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "crash_handler_linuxbsd.h"
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "main/main.h"
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
#define CRASH_HANDLER_ENABLED 1
|
||||
#endif
|
||||
|
||||
#ifdef CRASH_HANDLER_ENABLED
|
||||
#include <cxxabi.h>
|
||||
#include <dlfcn.h>
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void handle_crash(int sig) {
|
||||
if (OS::get_singleton() == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
void *bt_buffer[256];
|
||||
size_t size = backtrace(bt_buffer, 256);
|
||||
String _execpath = OS::get_singleton()->get_executable_path();
|
||||
|
||||
String msg;
|
||||
const ProjectSettings *proj_settings = ProjectSettings::get_singleton();
|
||||
if (proj_settings) {
|
||||
msg = proj_settings->get("debug/settings/crash_handler/message");
|
||||
}
|
||||
|
||||
// Dump the backtrace to stderr with a message to the user
|
||||
fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig);
|
||||
|
||||
if (OS::get_singleton()->get_main_loop())
|
||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_CRASH);
|
||||
|
||||
fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str());
|
||||
char **strings = backtrace_symbols(bt_buffer, size);
|
||||
if (strings) {
|
||||
for (size_t i = 1; i < size; i++) {
|
||||
char fname[1024];
|
||||
Dl_info info;
|
||||
|
||||
snprintf(fname, 1024, "%s", strings[i]);
|
||||
|
||||
// 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;
|
||||
char *demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status);
|
||||
|
||||
if (status == 0 && demangled) {
|
||||
snprintf(fname, 1024, "%s", demangled);
|
||||
}
|
||||
|
||||
if (demangled)
|
||||
free(demangled);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> args;
|
||||
|
||||
char str[1024];
|
||||
snprintf(str, 1024, "%p", bt_buffer[i]);
|
||||
args.push_back(str);
|
||||
args.push_back("-e");
|
||||
args.push_back(_execpath);
|
||||
|
||||
String output = "";
|
||||
|
||||
// Try to get the file/line number using addr2line
|
||||
int ret;
|
||||
Error err = OS::get_singleton()->execute(String("addr2line"), args, true, NULL, &output, &ret);
|
||||
if (err == OK) {
|
||||
output.erase(output.length() - 1, 1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "[%ld] %s (%ls)\n", (long int)i, fname, output.c_str());
|
||||
}
|
||||
|
||||
free(strings);
|
||||
}
|
||||
fprintf(stderr, "-- END OF BACKTRACE --\n");
|
||||
|
||||
// Abort to pass the error to the OS
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
CrashHandler::CrashHandler() {
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
CrashHandler::~CrashHandler() {
|
||||
disable();
|
||||
}
|
||||
|
||||
void CrashHandler::disable() {
|
||||
if (disabled)
|
||||
return;
|
||||
|
||||
#ifdef CRASH_HANDLER_ENABLED
|
||||
signal(SIGSEGV, NULL);
|
||||
signal(SIGFPE, NULL);
|
||||
signal(SIGILL, NULL);
|
||||
#endif
|
||||
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
void CrashHandler::initialize() {
|
||||
#ifdef CRASH_HANDLER_ENABLED
|
||||
signal(SIGSEGV, handle_crash);
|
||||
signal(SIGFPE, handle_crash);
|
||||
signal(SIGILL, handle_crash);
|
||||
#endif
|
||||
}
|
||||
48
platform/linuxbsd/crash_handler_linuxbsd.h
Normal file
48
platform/linuxbsd/crash_handler_linuxbsd.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*************************************************************************/
|
||||
/* crash_handler_linuxbsd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef CRASH_HANDLER_X11_H
|
||||
#define CRASH_HANDLER_X11_H
|
||||
|
||||
class CrashHandler {
|
||||
|
||||
bool disabled;
|
||||
|
||||
public:
|
||||
void initialize();
|
||||
|
||||
void disable();
|
||||
bool is_disabled() const { return disabled; };
|
||||
|
||||
CrashHandler();
|
||||
~CrashHandler();
|
||||
};
|
||||
|
||||
#endif // CRASH_HANDLER_X11_H
|
||||
368
platform/linuxbsd/detect.py
Normal file
368
platform/linuxbsd/detect.py
Normal file
@@ -0,0 +1,368 @@
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
|
||||
def is_active():
|
||||
return True
|
||||
|
||||
|
||||
def get_name():
|
||||
return "LinuxBSD"
|
||||
|
||||
|
||||
def can_build():
|
||||
|
||||
if (os.name != "posix" or sys.platform == "darwin"):
|
||||
return False
|
||||
|
||||
# Check the minimal dependencies
|
||||
x11_error = os.system("pkg-config --version > /dev/null")
|
||||
if (x11_error):
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config x11 --modversion > /dev/null ")
|
||||
if (x11_error):
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xcursor --modversion > /dev/null ")
|
||||
if (x11_error):
|
||||
print("xcursor not found.. x11 disabled.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xinerama --modversion > /dev/null ")
|
||||
if (x11_error):
|
||||
print("xinerama not found.. x11 disabled.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xrandr --modversion > /dev/null ")
|
||||
if (x11_error):
|
||||
print("xrandr not found.. x11 disabled.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xrender --modversion > /dev/null ")
|
||||
if (x11_error):
|
||||
print("xrender not found.. x11 disabled.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xi --modversion > /dev/null ")
|
||||
if (x11_error):
|
||||
print("xi not found.. Aborting.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_opts():
|
||||
from SCons.Variables import BoolVariable, EnumVariable
|
||||
|
||||
return [
|
||||
BoolVariable('use_llvm', 'Use the LLVM compiler', False),
|
||||
BoolVariable('use_lld', 'Use the LLD linker', False),
|
||||
BoolVariable('use_thinlto', 'Use ThinLTO', False),
|
||||
BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically for better portability', False),
|
||||
BoolVariable('use_coverage', 'Test Godot coverage', False),
|
||||
BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False),
|
||||
BoolVariable('use_asan', 'Use LLVM/GCC compiler address sanitizer (ASAN))', False),
|
||||
BoolVariable('use_lsan', 'Use LLVM/GCC compiler leak sanitizer (LSAN))', False),
|
||||
BoolVariable('use_tsan', 'Use LLVM/GCC compiler thread sanitizer (TSAN))', False),
|
||||
BoolVariable('pulseaudio', 'Detect and use PulseAudio', True),
|
||||
BoolVariable('udev', 'Use udev for gamepad connection callbacks', False),
|
||||
EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')),
|
||||
BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False),
|
||||
BoolVariable('touch', 'Enable touch events', True),
|
||||
BoolVariable('execinfo', 'Use libexecinfo on systems where glibc is not available', False),
|
||||
]
|
||||
|
||||
|
||||
def get_flags():
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
||||
## Build type
|
||||
|
||||
if (env["target"] == "release"):
|
||||
if (env["optimize"] == "speed"): #optimize for speed (default)
|
||||
env.Prepend(CCFLAGS=['-O3'])
|
||||
else: #optimize for size
|
||||
env.Prepend(CCFLAGS=['-Os'])
|
||||
|
||||
if (env["debug_symbols"] == "yes"):
|
||||
env.Prepend(CCFLAGS=['-g1'])
|
||||
if (env["debug_symbols"] == "full"):
|
||||
env.Prepend(CCFLAGS=['-g2'])
|
||||
|
||||
elif (env["target"] == "release_debug"):
|
||||
if (env["optimize"] == "speed"): #optimize for speed (default)
|
||||
env.Prepend(CCFLAGS=['-O2'])
|
||||
else: #optimize for size
|
||||
env.Prepend(CCFLAGS=['-Os'])
|
||||
env.Prepend(CPPDEFINES=['DEBUG_ENABLED'])
|
||||
|
||||
if (env["debug_symbols"] == "yes"):
|
||||
env.Prepend(CCFLAGS=['-g1'])
|
||||
if (env["debug_symbols"] == "full"):
|
||||
env.Prepend(CCFLAGS=['-g2'])
|
||||
|
||||
elif (env["target"] == "debug"):
|
||||
env.Prepend(CCFLAGS=['-g3'])
|
||||
env.Prepend(CPPDEFINES=['DEBUG_ENABLED', 'DEBUG_MEMORY_ENABLED'])
|
||||
env.Append(LINKFLAGS=['-rdynamic'])
|
||||
|
||||
## Architecture
|
||||
|
||||
is64 = sys.maxsize > 2**32
|
||||
if (env["bits"] == "default"):
|
||||
env["bits"] = "64" if is64 else "32"
|
||||
|
||||
## Compiler configuration
|
||||
|
||||
if 'CXX' in env and 'clang' in os.path.basename(env['CXX']):
|
||||
# Convenience check to enforce the use_llvm overrides when CXX is clang(++)
|
||||
env['use_llvm'] = True
|
||||
|
||||
if env['use_llvm']:
|
||||
if ('clang++' not in os.path.basename(env['CXX'])):
|
||||
env["CC"] = "clang"
|
||||
env["CXX"] = "clang++"
|
||||
env["LINK"] = "clang++"
|
||||
env.Append(CPPDEFINES=['TYPED_METHOD_BIND'])
|
||||
env.extra_suffix = ".llvm" + env.extra_suffix
|
||||
|
||||
if env['use_lld']:
|
||||
if env['use_llvm']:
|
||||
env.Append(LINKFLAGS=['-fuse-ld=lld'])
|
||||
if env['use_thinlto']:
|
||||
# A convenience so you don't need to write use_lto too when using SCons
|
||||
env['use_lto'] = True
|
||||
else:
|
||||
print("Using LLD with GCC is not supported yet, try compiling with 'use_llvm=yes'.")
|
||||
sys.exit(255)
|
||||
|
||||
if env['use_coverage']:
|
||||
env.Append(CCFLAGS=['-ftest-coverage', '-fprofile-arcs'])
|
||||
env.Append(LINKFLAGS=['-ftest-coverage', '-fprofile-arcs'])
|
||||
|
||||
if env['use_ubsan'] or env['use_asan'] or env['use_lsan'] or env['use_tsan']:
|
||||
env.extra_suffix += "s"
|
||||
|
||||
if env['use_ubsan']:
|
||||
env.Append(CCFLAGS=['-fsanitize=undefined'])
|
||||
env.Append(LINKFLAGS=['-fsanitize=undefined'])
|
||||
|
||||
if env['use_asan']:
|
||||
env.Append(CCFLAGS=['-fsanitize=address'])
|
||||
env.Append(LINKFLAGS=['-fsanitize=address'])
|
||||
|
||||
if env['use_lsan']:
|
||||
env.Append(CCFLAGS=['-fsanitize=leak'])
|
||||
env.Append(LINKFLAGS=['-fsanitize=leak'])
|
||||
|
||||
if env['use_tsan']:
|
||||
env.Append(CCFLAGS=['-fsanitize=thread'])
|
||||
env.Append(LINKFLAGS=['-fsanitize=thread'])
|
||||
|
||||
if env['use_lto']:
|
||||
if not env['use_llvm'] and env.GetOption("num_jobs") > 1:
|
||||
env.Append(CCFLAGS=['-flto'])
|
||||
env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))])
|
||||
else:
|
||||
if env['use_lld'] and env['use_thinlto']:
|
||||
env.Append(CCFLAGS=['-flto=thin'])
|
||||
env.Append(LINKFLAGS=['-flto=thin'])
|
||||
else:
|
||||
env.Append(CCFLAGS=['-flto'])
|
||||
env.Append(LINKFLAGS=['-flto'])
|
||||
|
||||
if not env['use_llvm']:
|
||||
env['RANLIB'] = 'gcc-ranlib'
|
||||
env['AR'] = 'gcc-ar'
|
||||
|
||||
env.Append(CCFLAGS=['-pipe'])
|
||||
env.Append(LINKFLAGS=['-pipe'])
|
||||
|
||||
# -fpie and -no-pie is supported on GCC 6+ and Clang 4+, both below our
|
||||
# minimal requirements.
|
||||
env.Append(CCFLAGS=['-fpie'])
|
||||
env.Append(LINKFLAGS=['-no-pie'])
|
||||
|
||||
## Dependencies
|
||||
|
||||
env.ParseConfig('pkg-config x11 --cflags --libs')
|
||||
env.ParseConfig('pkg-config xcursor --cflags --libs')
|
||||
env.ParseConfig('pkg-config xinerama --cflags --libs')
|
||||
env.ParseConfig('pkg-config xrandr --cflags --libs')
|
||||
env.ParseConfig('pkg-config xrender --cflags --libs')
|
||||
env.ParseConfig('pkg-config xi --cflags --libs')
|
||||
|
||||
if (env['touch']):
|
||||
env.Append(CPPDEFINES=['TOUCH_ENABLED'])
|
||||
|
||||
# FIXME: Check for existence of the libs before parsing their flags with pkg-config
|
||||
|
||||
# freetype depends on libpng and zlib, so bundling one of them while keeping others
|
||||
# as shared libraries leads to weird issues
|
||||
if env['builtin_freetype'] or env['builtin_libpng'] or env['builtin_zlib']:
|
||||
env['builtin_freetype'] = True
|
||||
env['builtin_libpng'] = True
|
||||
env['builtin_zlib'] = True
|
||||
|
||||
if not env['builtin_freetype']:
|
||||
env.ParseConfig('pkg-config freetype2 --cflags --libs')
|
||||
|
||||
if not env['builtin_libpng']:
|
||||
env.ParseConfig('pkg-config libpng16 --cflags --libs')
|
||||
|
||||
if not env['builtin_bullet']:
|
||||
# We need at least version 2.89
|
||||
import subprocess
|
||||
bullet_version = subprocess.check_output(['pkg-config', 'bullet', '--modversion']).strip()
|
||||
if str(bullet_version) < "2.89":
|
||||
# Abort as system bullet was requested but too old
|
||||
print("Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format(bullet_version, "2.89"))
|
||||
sys.exit(255)
|
||||
env.ParseConfig('pkg-config bullet --cflags --libs')
|
||||
|
||||
if False: # not env['builtin_assimp']:
|
||||
# FIXME: Add min version check
|
||||
env.ParseConfig('pkg-config assimp --cflags --libs')
|
||||
|
||||
if not env['builtin_enet']:
|
||||
env.ParseConfig('pkg-config libenet --cflags --libs')
|
||||
|
||||
if not env['builtin_squish']:
|
||||
env.ParseConfig('pkg-config libsquish --cflags --libs')
|
||||
|
||||
if not env['builtin_zstd']:
|
||||
env.ParseConfig('pkg-config libzstd --cflags --libs')
|
||||
|
||||
# Sound and video libraries
|
||||
# Keep the order as it triggers chained dependencies (ogg needed by others, etc.)
|
||||
|
||||
if not env['builtin_libtheora']:
|
||||
env['builtin_libogg'] = False # Needed to link against system libtheora
|
||||
env['builtin_libvorbis'] = False # Needed to link against system libtheora
|
||||
env.ParseConfig('pkg-config theora theoradec --cflags --libs')
|
||||
else:
|
||||
list_of_x86 = ['x86_64', 'x86', 'i386', 'i586']
|
||||
if any(platform.machine() in s for s in list_of_x86):
|
||||
env["x86_libtheora_opt_gcc"] = True
|
||||
|
||||
if not env['builtin_libvpx']:
|
||||
env.ParseConfig('pkg-config vpx --cflags --libs')
|
||||
|
||||
if not env['builtin_libvorbis']:
|
||||
env['builtin_libogg'] = False # Needed to link against system libvorbis
|
||||
env.ParseConfig('pkg-config vorbis vorbisfile --cflags --libs')
|
||||
|
||||
if not env['builtin_opus']:
|
||||
env['builtin_libogg'] = False # Needed to link against system opus
|
||||
env.ParseConfig('pkg-config opus opusfile --cflags --libs')
|
||||
|
||||
if not env['builtin_libogg']:
|
||||
env.ParseConfig('pkg-config ogg --cflags --libs')
|
||||
|
||||
if not env['builtin_libwebp']:
|
||||
env.ParseConfig('pkg-config libwebp --cflags --libs')
|
||||
|
||||
if not env['builtin_mbedtls']:
|
||||
# mbedTLS does not provide a pkgconfig config yet. See https://github.com/ARMmbed/mbedtls/issues/228
|
||||
env.Append(LIBS=['mbedtls', 'mbedcrypto', 'mbedx509'])
|
||||
|
||||
if not env['builtin_wslay']:
|
||||
env.ParseConfig('pkg-config libwslay --cflags --libs')
|
||||
|
||||
if not env['builtin_miniupnpc']:
|
||||
# No pkgconfig file so far, hardcode default paths.
|
||||
env.Prepend(CPPPATH=["/usr/include/miniupnpc"])
|
||||
env.Append(LIBS=["miniupnpc"])
|
||||
|
||||
# On Linux wchar_t should be 32-bits
|
||||
# 16-bit library shouldn't be required due to compiler optimisations
|
||||
if not env['builtin_pcre2']:
|
||||
env.ParseConfig('pkg-config libpcre2-32 --cflags --libs')
|
||||
|
||||
## Flags
|
||||
|
||||
if (os.system("pkg-config --exists alsa") == 0): # 0 means found
|
||||
print("Enabling ALSA")
|
||||
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
|
||||
# Don't parse --cflags, we don't need to add /usr/include/alsa to include path
|
||||
env.ParseConfig('pkg-config alsa --libs')
|
||||
else:
|
||||
print("ALSA libraries not found, disabling driver")
|
||||
|
||||
if env['pulseaudio']:
|
||||
if (os.system("pkg-config --exists libpulse") == 0): # 0 means found
|
||||
print("Enabling PulseAudio")
|
||||
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"])
|
||||
env.ParseConfig('pkg-config --cflags --libs libpulse')
|
||||
else:
|
||||
print("PulseAudio development libraries not found, disabling driver")
|
||||
|
||||
if (platform.system() == "Linux"):
|
||||
env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
|
||||
|
||||
if env['udev']:
|
||||
if (os.system("pkg-config --exists libudev") == 0): # 0 means found
|
||||
print("Enabling udev support")
|
||||
env.Append(CPPDEFINES=["UDEV_ENABLED"])
|
||||
env.ParseConfig('pkg-config libudev --cflags --libs')
|
||||
else:
|
||||
print("libudev development libraries not found, disabling udev support")
|
||||
|
||||
# Linkflags below this line should typically stay the last ones
|
||||
if not env['builtin_zlib']:
|
||||
env.ParseConfig('pkg-config zlib --cflags --libs')
|
||||
|
||||
env.Prepend(CPPPATH=['#platform/linuxbsd'])
|
||||
env.Append(CPPDEFINES=['X11_ENABLED', 'UNIX_ENABLED'])
|
||||
|
||||
env.Append(CPPDEFINES=['VULKAN_ENABLED'])
|
||||
if not env['builtin_vulkan']:
|
||||
env.ParseConfig('pkg-config vulkan --cflags --libs')
|
||||
if not env['builtin_glslang']:
|
||||
# No pkgconfig file for glslang so far
|
||||
env.Append(LIBS=['glslang', 'SPIRV'])
|
||||
|
||||
#env.Append(CPPDEFINES=['OPENGL_ENABLED'])
|
||||
env.Append(LIBS=['GL'])
|
||||
|
||||
env.Append(LIBS=['pthread'])
|
||||
|
||||
if (platform.system() == "Linux"):
|
||||
env.Append(LIBS=['dl'])
|
||||
|
||||
if (platform.system().find("BSD") >= 0):
|
||||
env["execinfo"] = True
|
||||
|
||||
if env["execinfo"]:
|
||||
env.Append(LIBS=['execinfo'])
|
||||
|
||||
if not env['tools']:
|
||||
import subprocess
|
||||
import re
|
||||
linker_version_str = subprocess.check_output([env.subst(env["LINK"]), '-Wl,--version']).decode("utf-8")
|
||||
gnu_ld_version = re.search('^GNU ld [^$]*(\d+\.\d+)$', linker_version_str, re.MULTILINE)
|
||||
if not gnu_ld_version:
|
||||
print("Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld")
|
||||
else:
|
||||
if float(gnu_ld_version.group(1)) >= 2.30:
|
||||
env.Append(LINKFLAGS=['-T', 'platform/linuxbsd/pck_embed.ld'])
|
||||
else:
|
||||
env.Append(LINKFLAGS=['-T', 'platform/linuxbsd/pck_embed.legacy.ld'])
|
||||
|
||||
## Cross-compilation
|
||||
|
||||
if (is64 and env["bits"] == "32"):
|
||||
env.Append(CCFLAGS=['-m32'])
|
||||
env.Append(LINKFLAGS=['-m32', '-L/usr/lib/i386-linux-gnu'])
|
||||
elif (not is64 and env["bits"] == "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++'])
|
||||
238
platform/linuxbsd/detect_prime_x11.cpp
Normal file
238
platform/linuxbsd/detect_prime_x11.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/*************************************************************************/
|
||||
/* detect_prime_x11.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef X11_ENABLED
|
||||
#if defined(OPENGL_ENABLED)
|
||||
|
||||
#include "detect_prime.h"
|
||||
|
||||
#include "core/print_string.h"
|
||||
#include "core/ustring.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
|
||||
typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
|
||||
|
||||
struct vendor {
|
||||
const char *glxvendor;
|
||||
int priority;
|
||||
};
|
||||
|
||||
vendor vendormap[] = {
|
||||
{ "Advanced Micro Devices, Inc.", 30 },
|
||||
{ "NVIDIA Corporation", 30 },
|
||||
{ "X.Org", 30 },
|
||||
{ "Intel Open Source Technology Center", 20 },
|
||||
{ "Intel", 20 },
|
||||
{ "nouveau", 10 },
|
||||
{ "Mesa Project", 0 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
// Runs inside a child. Exiting will not quit the engine.
|
||||
void create_context() {
|
||||
Display *x11_display = XOpenDisplay(NULL);
|
||||
Window x11_window;
|
||||
GLXContext glx_context;
|
||||
|
||||
GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
|
||||
|
||||
static int visual_attribs[] = {
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_DOUBLEBUFFER, true,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
None
|
||||
};
|
||||
|
||||
int fbcount;
|
||||
GLXFBConfig fbconfig = 0;
|
||||
XVisualInfo *vi = NULL;
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
swa.border_pixel = 0;
|
||||
unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
|
||||
if (!fbc)
|
||||
exit(1);
|
||||
|
||||
vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
|
||||
|
||||
fbconfig = fbc[0];
|
||||
|
||||
static int context_attribs[] = {
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
|
||||
glx_context = glXCreateContextAttribsARB(x11_display, fbconfig, NULL, true, context_attribs);
|
||||
|
||||
swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
|
||||
x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, 10, 10, 0, vi->depth, InputOutput, vi->visual, valuemask, &swa);
|
||||
|
||||
if (!x11_window)
|
||||
exit(1);
|
||||
|
||||
glXMakeCurrent(x11_display, x11_window, glx_context);
|
||||
XFree(vi);
|
||||
}
|
||||
|
||||
int detect_prime() {
|
||||
pid_t p;
|
||||
int priorities[2];
|
||||
String vendors[2];
|
||||
String renderers[2];
|
||||
|
||||
vendors[0] = "Unknown";
|
||||
vendors[1] = "Unknown";
|
||||
renderers[0] = "Unknown";
|
||||
renderers[1] = "Unknown";
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
int fdset[2];
|
||||
|
||||
if (pipe(fdset) == -1) {
|
||||
print_verbose("Failed to pipe(), using default GPU");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Fork so the driver initialization can crash without taking down the engine.
|
||||
p = fork();
|
||||
|
||||
if (p > 0) {
|
||||
// Main thread
|
||||
|
||||
int stat_loc = 0;
|
||||
char string[201];
|
||||
string[200] = '\0';
|
||||
|
||||
close(fdset[1]);
|
||||
|
||||
waitpid(p, &stat_loc, 0);
|
||||
|
||||
if (!stat_loc) {
|
||||
// No need to do anything complicated here. Anything less than
|
||||
// PIPE_BUF will be delivered in one read() call.
|
||||
// Leave it 'Unknown' otherwise.
|
||||
if (read(fdset[0], string, sizeof(string) - 1) > 0) {
|
||||
vendors[i] = string;
|
||||
renderers[i] = string + strlen(string) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
close(fdset[0]);
|
||||
|
||||
} else {
|
||||
// In child, exit() here will not quit the engine.
|
||||
|
||||
char string[201];
|
||||
|
||||
close(fdset[0]);
|
||||
|
||||
if (i) setenv("DRI_PRIME", "1", 1);
|
||||
create_context();
|
||||
|
||||
const char *vendor = (const char *)glGetString(GL_VENDOR);
|
||||
const char *renderer = (const char *)glGetString(GL_RENDERER);
|
||||
|
||||
unsigned int vendor_len = strlen(vendor) + 1;
|
||||
unsigned int renderer_len = strlen(renderer) + 1;
|
||||
|
||||
if (vendor_len + renderer_len >= sizeof(string)) {
|
||||
renderer_len = 200 - vendor_len;
|
||||
}
|
||||
|
||||
memcpy(&string, vendor, vendor_len);
|
||||
memcpy(&string[vendor_len], renderer, renderer_len);
|
||||
|
||||
if (write(fdset[1], string, vendor_len + renderer_len) == -1) {
|
||||
print_verbose("Couldn't write vendor/renderer string.");
|
||||
}
|
||||
close(fdset[1]);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int preferred = 0;
|
||||
int priority = 0;
|
||||
|
||||
if (vendors[0] == vendors[1]) {
|
||||
print_verbose("Only one GPU found, using default.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 1; i >= 0; --i) {
|
||||
vendor *v = vendormap;
|
||||
while (v->glxvendor) {
|
||||
if (v->glxvendor == vendors[i]) {
|
||||
priorities[i] = v->priority;
|
||||
|
||||
if (v->priority >= priority) {
|
||||
priority = v->priority;
|
||||
preferred = i;
|
||||
}
|
||||
}
|
||||
++v;
|
||||
}
|
||||
}
|
||||
|
||||
print_verbose("Found renderers:");
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
print_verbose("Renderer " + itos(i) + ": " + renderers[i] + " with priority: " + itos(priorities[i]));
|
||||
}
|
||||
|
||||
print_verbose("Using renderer: " + renderers[preferred]);
|
||||
return preferred;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
37
platform/linuxbsd/detect_prime_x11.h
Normal file
37
platform/linuxbsd/detect_prime_x11.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*************************************************************************/
|
||||
/* detect_prime_x11.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef X11_ENABLED
|
||||
#if defined(OPENGL_ENABLED)
|
||||
|
||||
int detect_prime();
|
||||
|
||||
#endif
|
||||
#endif
|
||||
3347
platform/linuxbsd/display_server_x11.cpp
Normal file
3347
platform/linuxbsd/display_server_x11.cpp
Normal file
File diff suppressed because it is too large
Load Diff
323
platform/linuxbsd/display_server_x11.h
Normal file
323
platform/linuxbsd/display_server_x11.h
Normal file
@@ -0,0 +1,323 @@
|
||||
/*************************************************************************/
|
||||
/* display_server_x11.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef DISPLAY_SERVER_X11_H
|
||||
#define DISPLAY_SERVER_X11_H
|
||||
|
||||
#ifdef X11_ENABLED
|
||||
|
||||
#include "servers/display_server.h"
|
||||
|
||||
#include "core/input/input.h"
|
||||
|
||||
#include "drivers/alsa/audio_driver_alsa.h"
|
||||
#include "drivers/alsamidi/midi_driver_alsamidi.h"
|
||||
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
|
||||
#include "drivers/unix/os_unix.h"
|
||||
#include "joypad_linux.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/visual/rasterizer.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
#if defined(OPENGL_ENABLED)
|
||||
#include "context_gl_x11.h"
|
||||
#endif
|
||||
|
||||
#if defined(VULKAN_ENABLED)
|
||||
#include "drivers/vulkan/rendering_device_vulkan.h"
|
||||
#include "platform/linuxbsd/vulkan_context_x11.h"
|
||||
#endif
|
||||
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
// Hints for X11 fullscreen
|
||||
typedef struct {
|
||||
unsigned long flags;
|
||||
unsigned long functions;
|
||||
unsigned long decorations;
|
||||
long inputMode;
|
||||
unsigned long status;
|
||||
} Hints;
|
||||
|
||||
typedef struct _xrr_monitor_info {
|
||||
Atom name;
|
||||
Bool primary;
|
||||
Bool automatic;
|
||||
int noutput;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int mwidth;
|
||||
int mheight;
|
||||
RROutput *outputs;
|
||||
} xrr_monitor_info;
|
||||
|
||||
#undef CursorShape
|
||||
|
||||
class DisplayServerX11 : public DisplayServer {
|
||||
//No need to register, it's platform-specific and nothing is added
|
||||
//GDCLASS(DisplayServerX11, DisplayServer)
|
||||
|
||||
Atom wm_delete;
|
||||
Atom xdnd_enter;
|
||||
Atom xdnd_position;
|
||||
Atom xdnd_status;
|
||||
Atom xdnd_action_copy;
|
||||
Atom xdnd_drop;
|
||||
Atom xdnd_finished;
|
||||
Atom xdnd_selection;
|
||||
Atom xdnd_aware;
|
||||
Atom requested;
|
||||
int xdnd_version;
|
||||
|
||||
#if defined(OPENGL_ENABLED)
|
||||
ContextGL_X11 *context_gles2;
|
||||
#endif
|
||||
#if defined(VULKAN_ENABLED)
|
||||
VulkanContextX11 *context_vulkan;
|
||||
RenderingDeviceVulkan *rendering_device_vulkan;
|
||||
#endif
|
||||
|
||||
struct WindowData {
|
||||
Window x11_window;
|
||||
::XIC xic;
|
||||
#if defined(VULKAN_ENABLED)
|
||||
int vulkan_window;
|
||||
#endif
|
||||
Size2i min_size;
|
||||
Size2i max_size;
|
||||
Size2i size;
|
||||
Size2i im_position;
|
||||
bool im_active = false;
|
||||
|
||||
//better to guess on the fly, given WM can change it
|
||||
//WindowMode mode;
|
||||
bool fullscreen = false; //OS can't exit from this mode
|
||||
bool on_top = false;
|
||||
bool borderless = false;
|
||||
bool resize_disabled = false;
|
||||
Vector2i last_position_before_fs;
|
||||
};
|
||||
|
||||
Map<WindowID, WindowData> windows;
|
||||
|
||||
WindowID window_id_counter = MAIN_WINDOW_ID;
|
||||
WindowID _create_window(WindowMode p_mode, const Vector2i &p_resolution);
|
||||
|
||||
String internal_clipboard;
|
||||
Window xdnd_source_window;
|
||||
::Display *x11_display;
|
||||
char *xmbstring;
|
||||
int xmblen;
|
||||
unsigned long last_timestamp;
|
||||
::Time last_keyrelease_time;
|
||||
::XIM xim;
|
||||
::XIMStyle xim_style;
|
||||
static void _xim_destroy_callback(::XIM im, ::XPointer client_data,
|
||||
::XPointer call_data);
|
||||
|
||||
Point2i last_mouse_pos;
|
||||
bool last_mouse_pos_valid;
|
||||
Point2i last_click_pos;
|
||||
uint64_t last_click_ms;
|
||||
int last_click_button_index;
|
||||
uint32_t last_button_state;
|
||||
|
||||
struct {
|
||||
int opcode;
|
||||
Vector<int> touch_devices;
|
||||
Map<int, Vector2> absolute_devices;
|
||||
Map<int, Vector3> pen_devices;
|
||||
XIEventMask all_event_mask;
|
||||
Map<int, Vector2> state;
|
||||
double pressure;
|
||||
Vector2 tilt;
|
||||
Vector2 mouse_pos_to_filter;
|
||||
Vector2 relative_motion;
|
||||
Vector2 raw_pos;
|
||||
Vector2 old_raw_pos;
|
||||
::Time last_relative_time;
|
||||
} xi;
|
||||
|
||||
bool _refresh_device_info();
|
||||
|
||||
unsigned int _get_mouse_button_state(unsigned int p_x11_button, int p_x11_type);
|
||||
void _get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state);
|
||||
void _flush_mouse_motion();
|
||||
|
||||
MouseMode mouse_mode;
|
||||
Point2i center;
|
||||
|
||||
void _handle_key_event(WindowID p_window, XKeyEvent *p_event, bool p_echo = false);
|
||||
|
||||
bool force_quit;
|
||||
bool minimized;
|
||||
bool window_has_focus;
|
||||
bool do_mouse_warp;
|
||||
|
||||
const char *cursor_theme;
|
||||
int cursor_size;
|
||||
XcursorImage *img[CURSOR_MAX];
|
||||
Cursor cursors[CURSOR_MAX];
|
||||
Cursor null_cursor;
|
||||
CursorShape current_cursor;
|
||||
Map<CursorShape, Vector<Variant>> cursors_cache;
|
||||
|
||||
bool layered_window;
|
||||
|
||||
String rendering_driver;
|
||||
bool window_focused;
|
||||
//void set_wm_border(bool p_enabled);
|
||||
void set_wm_fullscreen(bool p_enabled);
|
||||
void set_wm_above(bool p_enabled);
|
||||
|
||||
typedef xrr_monitor_info *(*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors);
|
||||
typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors);
|
||||
xrr_get_monitors_t xrr_get_monitors;
|
||||
xrr_free_monitors_t xrr_free_monitors;
|
||||
void *xrandr_handle;
|
||||
Bool xrandr_ext_ok;
|
||||
|
||||
struct Property {
|
||||
unsigned char *data;
|
||||
int format, nitems;
|
||||
Atom type;
|
||||
};
|
||||
static Property _read_property(Display *p_display, Window p_window, Atom p_property);
|
||||
|
||||
void _update_real_mouse_position(const WindowData &wd);
|
||||
void _set_wm_fullscreen(WindowID p_window, bool p_enabled);
|
||||
void _set_wm_maximized(WindowID p_window, bool p_enabled);
|
||||
|
||||
void _update_context(WindowData &wd);
|
||||
|
||||
Context context = CONTEXT_ENGINE;
|
||||
|
||||
protected:
|
||||
void _window_changed(XEvent *event);
|
||||
|
||||
public:
|
||||
virtual bool has_feature(Feature p_feature) const;
|
||||
virtual String get_name() const;
|
||||
|
||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
|
||||
virtual void mouse_set_mode(MouseMode p_mode);
|
||||
virtual MouseMode mouse_get_mode() const;
|
||||
|
||||
virtual void mouse_warp_to_position(const Point2i &p_to);
|
||||
virtual Point2i mouse_get_position() const;
|
||||
virtual int mouse_get_button_state() const;
|
||||
|
||||
virtual void clipboard_set(const String &p_text);
|
||||
virtual String clipboard_get() const;
|
||||
|
||||
virtual int get_screen_count() const;
|
||||
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
||||
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
||||
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
||||
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
||||
|
||||
virtual Vector<int> get_window_list() const;
|
||||
|
||||
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
|
||||
virtual void delete_sub_window(WindowID p_id);
|
||||
|
||||
virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
||||
virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
||||
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
||||
virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
||||
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
||||
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual bool can_any_window_draw() const;
|
||||
|
||||
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
||||
virtual void cursor_set_shape(CursorShape p_shape);
|
||||
virtual CursorShape cursor_get_shape() const;
|
||||
virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||
|
||||
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
||||
|
||||
virtual void process_events();
|
||||
|
||||
virtual void release_rendering_thread();
|
||||
virtual void make_rendering_thread();
|
||||
virtual void swap_buffers();
|
||||
|
||||
virtual void set_context(Context p_context);
|
||||
|
||||
virtual void set_native_icon(const String &p_filename);
|
||||
virtual void set_icon(const Ref<Image> &p_icon);
|
||||
|
||||
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
|
||||
static Vector<String> get_rendering_drivers_func();
|
||||
|
||||
static void register_x11_driver();
|
||||
|
||||
DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
|
||||
~DisplayServerX11();
|
||||
};
|
||||
|
||||
#endif // X11 enabled
|
||||
|
||||
#endif // DISPLAY_SERVER_X11_H
|
||||
169
platform/linuxbsd/export/export.cpp
Normal file
169
platform/linuxbsd/export/export.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*************************************************************************/
|
||||
/* export.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#include "core/os/file_access.h"
|
||||
#include "editor/editor_export.h"
|
||||
#include "platform/linuxbsd/logo.gen.h"
|
||||
#include "scene/resources/texture.h"
|
||||
|
||||
static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
|
||||
|
||||
void register_linuxbsd_exporter() {
|
||||
|
||||
Ref<EditorExportPlatformPC> platform;
|
||||
platform.instance();
|
||||
|
||||
Ref<Image> img = memnew(Image(_linuxbsd_logo));
|
||||
Ref<ImageTexture> logo;
|
||||
logo.instance();
|
||||
logo->create_from_image(img);
|
||||
platform->set_logo(logo);
|
||||
platform->set_name("Linux/X11");
|
||||
platform->set_extension("x86");
|
||||
platform->set_extension("x86_64", "binary_format/64_bits");
|
||||
platform->set_release_32("linux_x11_32_release");
|
||||
platform->set_debug_32("linux_x11_32_debug");
|
||||
platform->set_release_64("linux_x11_64_release");
|
||||
platform->set_debug_64("linux_x11_64_debug");
|
||||
platform->set_os_name("X11");
|
||||
platform->set_chmod_flags(0755);
|
||||
platform->set_fixup_embedded_pck_func(&fixup_embedded_pck);
|
||||
|
||||
EditorExport::get_singleton()->add_export_platform(platform);
|
||||
}
|
||||
|
||||
static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
|
||||
|
||||
// Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data
|
||||
|
||||
FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE);
|
||||
if (!f) {
|
||||
return ERR_CANT_OPEN;
|
||||
}
|
||||
|
||||
// Read and check ELF magic number
|
||||
{
|
||||
uint32_t magic = f->get_32();
|
||||
if (magic != 0x464c457f) { // 0x7F + "ELF"
|
||||
f->close();
|
||||
return ERR_FILE_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
||||
// Read program architecture bits from class field
|
||||
|
||||
int bits = f->get_8() * 32;
|
||||
|
||||
if (bits == 32 && p_embedded_size >= 0x100000000) {
|
||||
f->close();
|
||||
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "32-bit executables cannot have embedded data >= 4 GiB.");
|
||||
}
|
||||
|
||||
// Get info about the section header table
|
||||
|
||||
int64_t section_table_pos;
|
||||
int64_t section_header_size;
|
||||
if (bits == 32) {
|
||||
section_header_size = 40;
|
||||
f->seek(0x20);
|
||||
section_table_pos = f->get_32();
|
||||
f->seek(0x30);
|
||||
} else { // 64
|
||||
section_header_size = 64;
|
||||
f->seek(0x28);
|
||||
section_table_pos = f->get_64();
|
||||
f->seek(0x3c);
|
||||
}
|
||||
int num_sections = f->get_16();
|
||||
int string_section_idx = f->get_16();
|
||||
|
||||
// Load the strings table
|
||||
uint8_t *strings;
|
||||
{
|
||||
// Jump to the strings section header
|
||||
f->seek(section_table_pos + string_section_idx * section_header_size);
|
||||
|
||||
// Read strings data size and offset
|
||||
int64_t string_data_pos;
|
||||
int64_t string_data_size;
|
||||
if (bits == 32) {
|
||||
f->seek(f->get_position() + 0x10);
|
||||
string_data_pos = f->get_32();
|
||||
string_data_size = f->get_32();
|
||||
} else { // 64
|
||||
f->seek(f->get_position() + 0x18);
|
||||
string_data_pos = f->get_64();
|
||||
string_data_size = f->get_64();
|
||||
}
|
||||
|
||||
// Read strings data
|
||||
f->seek(string_data_pos);
|
||||
strings = (uint8_t *)memalloc(string_data_size);
|
||||
if (!strings) {
|
||||
f->close();
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
f->get_buffer(strings, string_data_size);
|
||||
}
|
||||
|
||||
// Search for the "pck" section
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < num_sections; ++i) {
|
||||
|
||||
int64_t section_header_pos = section_table_pos + i * section_header_size;
|
||||
f->seek(section_header_pos);
|
||||
|
||||
uint32_t name_offset = f->get_32();
|
||||
if (strcmp((char *)strings + name_offset, "pck") == 0) {
|
||||
// "pck" section found, let's patch!
|
||||
|
||||
if (bits == 32) {
|
||||
f->seek(section_header_pos + 0x10);
|
||||
f->store_32(p_embedded_start);
|
||||
f->store_32(p_embedded_size);
|
||||
} else { // 64
|
||||
f->seek(section_header_pos + 0x18);
|
||||
f->store_64(p_embedded_start);
|
||||
f->store_64(p_embedded_size);
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memfree(strings);
|
||||
f->close();
|
||||
|
||||
return found ? OK : ERR_FILE_CORRUPT;
|
||||
}
|
||||
36
platform/linuxbsd/export/export.h
Normal file
36
platform/linuxbsd/export/export.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*************************************************************************/
|
||||
/* export.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef LINUXBSD_EXPORT_H
|
||||
#define LINUXBSD_EXPORT_H
|
||||
|
||||
void register_linuxbsd_exporter();
|
||||
|
||||
#endif // LINUXBSD_EXPORT_H
|
||||
67
platform/linuxbsd/godot_linuxbsd.cpp
Normal file
67
platform/linuxbsd/godot_linuxbsd.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*************************************************************************/
|
||||
/* godot_linuxbsd.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "main/main.h"
|
||||
#include "os_linuxbsd.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
OS_LinuxBSD os;
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
char *cwd = (char *)malloc(PATH_MAX);
|
||||
ERR_FAIL_COND_V(!cwd, ERR_OUT_OF_MEMORY);
|
||||
char *ret = getcwd(cwd, PATH_MAX);
|
||||
|
||||
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
|
||||
if (err != OK) {
|
||||
free(cwd);
|
||||
return 255;
|
||||
}
|
||||
|
||||
if (Main::start())
|
||||
os.run(); // it is actually the OS that decides how to run
|
||||
Main::cleanup();
|
||||
|
||||
if (ret) { // Previous getcwd was successful
|
||||
if (chdir(cwd) != 0) {
|
||||
ERR_PRINT("Couldn't return to previous working directory.");
|
||||
}
|
||||
}
|
||||
free(cwd);
|
||||
|
||||
return os.get_exit_code();
|
||||
}
|
||||
554
platform/linuxbsd/joypad_linux.cpp
Normal file
554
platform/linuxbsd/joypad_linux.cpp
Normal file
@@ -0,0 +1,554 @@
|
||||
/*************************************************************************/
|
||||
/* joypad_linux.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef JOYDEV_ENABLED
|
||||
|
||||
#include "joypad_linux.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef UDEV_ENABLED
|
||||
#include <libudev.h>
|
||||
#endif
|
||||
|
||||
#define LONG_BITS (sizeof(long) * 8)
|
||||
#define test_bit(nr, addr) (((1UL << ((nr) % LONG_BITS)) & ((addr)[(nr) / LONG_BITS])) != 0)
|
||||
#define NBITS(x) ((((x)-1) / LONG_BITS) + 1)
|
||||
|
||||
#ifdef UDEV_ENABLED
|
||||
static const char *ignore_str = "/dev/input/js";
|
||||
#endif
|
||||
|
||||
JoypadLinux::Joypad::Joypad() {
|
||||
fd = -1;
|
||||
dpad = 0;
|
||||
devpath = "";
|
||||
for (int i = 0; i < MAX_ABS; i++) {
|
||||
abs_info[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JoypadLinux::Joypad::~Joypad() {
|
||||
|
||||
for (int i = 0; i < MAX_ABS; i++) {
|
||||
if (abs_info[i]) {
|
||||
memdelete(abs_info[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoypadLinux::Joypad::reset() {
|
||||
dpad = 0;
|
||||
fd = -1;
|
||||
|
||||
Input::JoyAxis jx;
|
||||
jx.min = -1;
|
||||
jx.value = 0.0f;
|
||||
for (int i = 0; i < MAX_ABS; i++) {
|
||||
abs_map[i] = -1;
|
||||
curr_axis[i] = jx;
|
||||
}
|
||||
}
|
||||
|
||||
JoypadLinux::JoypadLinux(Input *in) {
|
||||
exit_udev = false;
|
||||
input = in;
|
||||
joy_thread = Thread::create(joy_thread_func, this);
|
||||
}
|
||||
|
||||
JoypadLinux::~JoypadLinux() {
|
||||
exit_udev = true;
|
||||
Thread::wait_to_finish(joy_thread);
|
||||
memdelete(joy_thread);
|
||||
close_joypad();
|
||||
}
|
||||
|
||||
void JoypadLinux::joy_thread_func(void *p_user) {
|
||||
|
||||
if (p_user) {
|
||||
JoypadLinux *joy = (JoypadLinux *)p_user;
|
||||
joy->run_joypad_thread();
|
||||
}
|
||||
}
|
||||
|
||||
void JoypadLinux::run_joypad_thread() {
|
||||
#ifdef UDEV_ENABLED
|
||||
udev *_udev = udev_new();
|
||||
ERR_FAIL_COND(!_udev);
|
||||
enumerate_joypads(_udev);
|
||||
monitor_joypads(_udev);
|
||||
udev_unref(_udev);
|
||||
#else
|
||||
monitor_joypads();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UDEV_ENABLED
|
||||
void JoypadLinux::enumerate_joypads(udev *p_udev) {
|
||||
|
||||
udev_enumerate *enumerate;
|
||||
udev_list_entry *devices, *dev_list_entry;
|
||||
udev_device *dev;
|
||||
|
||||
enumerate = udev_enumerate_new(p_udev);
|
||||
udev_enumerate_add_match_subsystem(enumerate, "input");
|
||||
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
devices = udev_enumerate_get_list_entry(enumerate);
|
||||
udev_list_entry_foreach(dev_list_entry, devices) {
|
||||
|
||||
const char *path = udev_list_entry_get_name(dev_list_entry);
|
||||
dev = udev_device_new_from_syspath(p_udev, path);
|
||||
const char *devnode = udev_device_get_devnode(dev);
|
||||
|
||||
if (devnode) {
|
||||
|
||||
String devnode_str = devnode;
|
||||
if (devnode_str.find(ignore_str) == -1) {
|
||||
MutexLock lock(joy_mutex);
|
||||
open_joypad(devnode);
|
||||
}
|
||||
}
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
}
|
||||
|
||||
void JoypadLinux::monitor_joypads(udev *p_udev) {
|
||||
|
||||
udev_device *dev = NULL;
|
||||
udev_monitor *mon = udev_monitor_new_from_netlink(p_udev, "udev");
|
||||
udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL);
|
||||
udev_monitor_enable_receiving(mon);
|
||||
int fd = udev_monitor_get_fd(mon);
|
||||
|
||||
while (!exit_udev) {
|
||||
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ret = select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
|
||||
/* Check if our file descriptor has received data. */
|
||||
if (ret > 0 && FD_ISSET(fd, &fds)) {
|
||||
/* Make the call to receive the device.
|
||||
select() ensured that this will not block. */
|
||||
dev = udev_monitor_receive_device(mon);
|
||||
|
||||
if (dev && udev_device_get_devnode(dev) != 0) {
|
||||
|
||||
MutexLock lock(joy_mutex);
|
||||
String action = udev_device_get_action(dev);
|
||||
const char *devnode = udev_device_get_devnode(dev);
|
||||
if (devnode) {
|
||||
|
||||
String devnode_str = devnode;
|
||||
if (devnode_str.find(ignore_str) == -1) {
|
||||
|
||||
if (action == "add")
|
||||
open_joypad(devnode);
|
||||
else if (String(action) == "remove")
|
||||
close_joypad(get_joy_from_path(devnode));
|
||||
}
|
||||
}
|
||||
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
usleep(50000);
|
||||
}
|
||||
udev_monitor_unref(mon);
|
||||
}
|
||||
#endif
|
||||
|
||||
void JoypadLinux::monitor_joypads() {
|
||||
|
||||
while (!exit_udev) {
|
||||
{
|
||||
MutexLock lock(joy_mutex);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
char fname[64];
|
||||
sprintf(fname, "/dev/input/event%d", i);
|
||||
if (attached_devices.find(fname) == -1) {
|
||||
open_joypad(fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
usleep(1000000); // 1s
|
||||
}
|
||||
}
|
||||
|
||||
int JoypadLinux::get_joy_from_path(String p_path) const {
|
||||
|
||||
for (int i = 0; i < JOYPADS_MAX; i++) {
|
||||
|
||||
if (joypads[i].devpath == p_path) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
void JoypadLinux::close_joypad(int p_id) {
|
||||
if (p_id == -1) {
|
||||
for (int i = 0; i < JOYPADS_MAX; i++) {
|
||||
|
||||
close_joypad(i);
|
||||
};
|
||||
return;
|
||||
} else if (p_id < 0)
|
||||
return;
|
||||
|
||||
Joypad &joy = joypads[p_id];
|
||||
|
||||
if (joy.fd != -1) {
|
||||
|
||||
close(joy.fd);
|
||||
joy.fd = -1;
|
||||
attached_devices.remove(attached_devices.find(joy.devpath));
|
||||
input->joy_connection_changed(p_id, false, "");
|
||||
};
|
||||
}
|
||||
|
||||
static String _hex_str(uint8_t p_byte) {
|
||||
|
||||
static const char *dict = "0123456789abcdef";
|
||||
char ret[3];
|
||||
ret[2] = 0;
|
||||
|
||||
ret[0] = dict[p_byte >> 4];
|
||||
ret[1] = dict[p_byte & 0xF];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JoypadLinux::setup_joypad_properties(int p_id) {
|
||||
|
||||
Joypad *joy = &joypads[p_id];
|
||||
|
||||
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
|
||||
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
|
||||
|
||||
int num_buttons = 0;
|
||||
int num_axes = 0;
|
||||
|
||||
if ((ioctl(joy->fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
|
||||
(ioctl(joy->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
|
||||
return;
|
||||
}
|
||||
for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
|
||||
|
||||
if (test_bit(i, keybit)) {
|
||||
|
||||
joy->key_map[i] = num_buttons++;
|
||||
}
|
||||
}
|
||||
for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
|
||||
|
||||
if (test_bit(i, keybit)) {
|
||||
|
||||
joy->key_map[i] = num_buttons++;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ABS_MISC; ++i) {
|
||||
/* Skip hats */
|
||||
if (i == ABS_HAT0X) {
|
||||
i = ABS_HAT3Y;
|
||||
continue;
|
||||
}
|
||||
if (test_bit(i, absbit)) {
|
||||
|
||||
joy->abs_map[i] = num_axes++;
|
||||
joy->abs_info[i] = memnew(input_absinfo);
|
||||
if (ioctl(joy->fd, EVIOCGABS(i), joy->abs_info[i]) < 0) {
|
||||
memdelete(joy->abs_info[i]);
|
||||
joy->abs_info[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
joy->force_feedback = false;
|
||||
joy->ff_effect_timestamp = 0;
|
||||
unsigned long ffbit[NBITS(FF_CNT)];
|
||||
if (ioctl(joy->fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) != -1) {
|
||||
if (test_bit(FF_RUMBLE, ffbit)) {
|
||||
joy->force_feedback = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoypadLinux::open_joypad(const char *p_path) {
|
||||
|
||||
int joy_num = input->get_unused_joy_id();
|
||||
int fd = open(p_path, O_RDWR | O_NONBLOCK);
|
||||
if (fd != -1 && joy_num != -1) {
|
||||
|
||||
unsigned long evbit[NBITS(EV_MAX)] = { 0 };
|
||||
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
|
||||
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
|
||||
|
||||
// add to attached devices so we don't try to open it again
|
||||
attached_devices.push_back(String(p_path));
|
||||
|
||||
if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
|
||||
(ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
|
||||
(ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
//check if the device supports basic gamepad events, prevents certain keyboards from
|
||||
//being detected as joypads
|
||||
if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
|
||||
(test_bit(ABS_X, absbit) || test_bit(ABS_Y, absbit) || test_bit(ABS_HAT0X, absbit) ||
|
||||
test_bit(ABS_GAS, absbit) || test_bit(ABS_RUDDER, absbit)) &&
|
||||
(test_bit(BTN_A, keybit) || test_bit(BTN_THUMBL, keybit) ||
|
||||
test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_1, keybit))) &&
|
||||
!(test_bit(EV_ABS, evbit) &&
|
||||
test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) &&
|
||||
test_bit(ABS_RX, absbit) && test_bit(ABS_RY, absbit))) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
char uid[128];
|
||||
char namebuf[128];
|
||||
String name = "";
|
||||
input_id inpid;
|
||||
if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) >= 0) {
|
||||
name = namebuf;
|
||||
}
|
||||
|
||||
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
joypads[joy_num].reset();
|
||||
|
||||
Joypad &joy = joypads[joy_num];
|
||||
joy.fd = fd;
|
||||
joy.devpath = String(p_path);
|
||||
setup_joypad_properties(joy_num);
|
||||
sprintf(uid, "%04x%04x", BSWAP16(inpid.bustype), 0);
|
||||
if (inpid.vendor && inpid.product && inpid.version) {
|
||||
|
||||
uint16_t vendor = BSWAP16(inpid.vendor);
|
||||
uint16_t product = BSWAP16(inpid.product);
|
||||
uint16_t version = BSWAP16(inpid.version);
|
||||
|
||||
sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor, 0, product, 0, version, 0);
|
||||
input->joy_connection_changed(joy_num, true, name, uid);
|
||||
} else {
|
||||
String uidname = uid;
|
||||
int uidlen = MIN(name.length(), 11);
|
||||
for (int i = 0; i < uidlen; i++) {
|
||||
|
||||
uidname = uidname + _hex_str(name[i]);
|
||||
}
|
||||
uidname += "00";
|
||||
input->joy_connection_changed(joy_num, true, name, uidname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoypadLinux::joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) {
|
||||
Joypad &joy = joypads[p_id];
|
||||
if (!joy.force_feedback || joy.fd == -1 || p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) {
|
||||
return;
|
||||
}
|
||||
if (joy.ff_effect_id != -1) {
|
||||
joypad_vibration_stop(p_id, p_timestamp);
|
||||
}
|
||||
|
||||
struct ff_effect effect;
|
||||
effect.type = FF_RUMBLE;
|
||||
effect.id = -1;
|
||||
effect.u.rumble.weak_magnitude = floor(p_weak_magnitude * (float)0xffff);
|
||||
effect.u.rumble.strong_magnitude = floor(p_strong_magnitude * (float)0xffff);
|
||||
effect.replay.length = floor(p_duration * 1000);
|
||||
effect.replay.delay = 0;
|
||||
|
||||
if (ioctl(joy.fd, EVIOCSFF, &effect) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct input_event play;
|
||||
play.type = EV_FF;
|
||||
play.code = effect.id;
|
||||
play.value = 1;
|
||||
if (write(joy.fd, (const void *)&play, sizeof(play)) == -1) {
|
||||
print_verbose("Couldn't write to Joypad device.");
|
||||
}
|
||||
|
||||
joy.ff_effect_id = effect.id;
|
||||
joy.ff_effect_timestamp = p_timestamp;
|
||||
}
|
||||
|
||||
void JoypadLinux::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
|
||||
Joypad &joy = joypads[p_id];
|
||||
if (!joy.force_feedback || joy.fd == -1 || joy.ff_effect_id == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ioctl(joy.fd, EVIOCRMFF, joy.ff_effect_id) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
joy.ff_effect_id = -1;
|
||||
joy.ff_effect_timestamp = p_timestamp;
|
||||
}
|
||||
|
||||
Input::JoyAxis JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const {
|
||||
|
||||
int min = p_abs->minimum;
|
||||
int max = p_abs->maximum;
|
||||
Input::JoyAxis jx;
|
||||
|
||||
if (min < 0) {
|
||||
jx.min = -1;
|
||||
if (p_value < 0) {
|
||||
jx.value = (float)-p_value / min;
|
||||
} else {
|
||||
jx.value = (float)p_value / max;
|
||||
}
|
||||
} else if (min == 0) {
|
||||
jx.min = 0;
|
||||
jx.value = 0.0f + (float)p_value / max;
|
||||
}
|
||||
return jx;
|
||||
}
|
||||
|
||||
void JoypadLinux::process_joypads() {
|
||||
|
||||
if (joy_mutex.try_lock() != OK) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < JOYPADS_MAX; i++) {
|
||||
|
||||
if (joypads[i].fd == -1) continue;
|
||||
|
||||
input_event events[32];
|
||||
Joypad *joy = &joypads[i];
|
||||
|
||||
int len;
|
||||
|
||||
while ((len = read(joy->fd, events, (sizeof events))) > 0) {
|
||||
len /= sizeof(events[0]);
|
||||
for (int j = 0; j < len; j++) {
|
||||
|
||||
input_event &ev = events[j];
|
||||
|
||||
// ev may be tainted and out of MAX_KEY range, which will cause
|
||||
// joy->key_map[ev.code] to crash
|
||||
if (ev.code >= MAX_KEY)
|
||||
return;
|
||||
|
||||
switch (ev.type) {
|
||||
case EV_KEY:
|
||||
input->joy_button(i, joy->key_map[ev.code], ev.value);
|
||||
break;
|
||||
|
||||
case EV_ABS:
|
||||
|
||||
switch (ev.code) {
|
||||
case ABS_HAT0X:
|
||||
if (ev.value != 0) {
|
||||
if (ev.value < 0)
|
||||
joy->dpad |= Input::HAT_MASK_LEFT;
|
||||
else
|
||||
joy->dpad |= Input::HAT_MASK_RIGHT;
|
||||
} else
|
||||
joy->dpad &= ~(Input::HAT_MASK_LEFT | Input::HAT_MASK_RIGHT);
|
||||
|
||||
input->joy_hat(i, joy->dpad);
|
||||
break;
|
||||
|
||||
case ABS_HAT0Y:
|
||||
if (ev.value != 0) {
|
||||
if (ev.value < 0)
|
||||
joy->dpad |= Input::HAT_MASK_UP;
|
||||
else
|
||||
joy->dpad |= Input::HAT_MASK_DOWN;
|
||||
} else
|
||||
joy->dpad &= ~(Input::HAT_MASK_UP | Input::HAT_MASK_DOWN);
|
||||
|
||||
input->joy_hat(i, joy->dpad);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ev.code >= MAX_ABS)
|
||||
return;
|
||||
if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) {
|
||||
Input::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value);
|
||||
joy->curr_axis[joy->abs_map[ev.code]] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < MAX_ABS; j++) {
|
||||
int index = joy->abs_map[j];
|
||||
if (index != -1) {
|
||||
input->joy_axis(i, index, joy->curr_axis[index]);
|
||||
}
|
||||
}
|
||||
if (len == 0 || (len < 0 && errno != EAGAIN)) {
|
||||
close_joypad(i);
|
||||
};
|
||||
|
||||
if (joy->force_feedback) {
|
||||
uint64_t timestamp = input->get_joy_vibration_timestamp(i);
|
||||
if (timestamp > joy->ff_effect_timestamp) {
|
||||
Vector2 strength = input->get_joy_vibration_strength(i);
|
||||
float duration = input->get_joy_vibration_duration(i);
|
||||
if (strength.x == 0 && strength.y == 0) {
|
||||
joypad_vibration_stop(i, timestamp);
|
||||
} else {
|
||||
joypad_vibration_start(i, strength.x, strength.y, duration, timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
joy_mutex.unlock();
|
||||
}
|
||||
#endif
|
||||
102
platform/linuxbsd/joypad_linux.h
Normal file
102
platform/linuxbsd/joypad_linux.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*************************************************************************/
|
||||
/* joypad_linux.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
//author: Andreas Haas <hondres, liugam3@gmail.com>
|
||||
#ifndef JOYPAD_LINUX_H
|
||||
#define JOYPAD_LINUX_H
|
||||
|
||||
#ifdef JOYDEV_ENABLED
|
||||
#include "core/input/input.h"
|
||||
#include "core/os/mutex.h"
|
||||
#include "core/os/thread.h"
|
||||
|
||||
struct input_absinfo;
|
||||
|
||||
class JoypadLinux {
|
||||
public:
|
||||
JoypadLinux(Input *in);
|
||||
~JoypadLinux();
|
||||
void process_joypads();
|
||||
|
||||
private:
|
||||
enum {
|
||||
JOYPADS_MAX = 16,
|
||||
MAX_ABS = 63,
|
||||
MAX_KEY = 767, // Hack because <linux/input.h> can't be included here
|
||||
};
|
||||
|
||||
struct Joypad {
|
||||
Input::JoyAxis curr_axis[MAX_ABS];
|
||||
int key_map[MAX_KEY];
|
||||
int abs_map[MAX_ABS];
|
||||
int dpad;
|
||||
int fd;
|
||||
|
||||
String devpath;
|
||||
input_absinfo *abs_info[MAX_ABS];
|
||||
|
||||
bool force_feedback;
|
||||
int ff_effect_id;
|
||||
uint64_t ff_effect_timestamp;
|
||||
|
||||
Joypad();
|
||||
~Joypad();
|
||||
void reset();
|
||||
};
|
||||
|
||||
bool exit_udev;
|
||||
Mutex joy_mutex;
|
||||
Thread *joy_thread;
|
||||
Input *input;
|
||||
Joypad joypads[JOYPADS_MAX];
|
||||
Vector<String> attached_devices;
|
||||
|
||||
static void joy_thread_func(void *p_user);
|
||||
|
||||
int get_joy_from_path(String p_path) const;
|
||||
|
||||
void setup_joypad_properties(int p_id);
|
||||
void close_joypad(int p_id = -1);
|
||||
#ifdef UDEV_ENABLED
|
||||
void enumerate_joypads(struct udev *p_udev);
|
||||
void monitor_joypads(struct udev *p_udev);
|
||||
#endif
|
||||
void monitor_joypads();
|
||||
void run_joypad_thread();
|
||||
void open_joypad(const char *p_path);
|
||||
|
||||
void joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
|
||||
void joypad_vibration_stop(int p_id, uint64_t p_timestamp);
|
||||
|
||||
Input::JoyAxis axis_correct(const input_absinfo *p_abs, int p_value) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // JOYPAD_LINUX_H
|
||||
1944
platform/linuxbsd/key_mapping_x11.cpp
Normal file
1944
platform/linuxbsd/key_mapping_x11.cpp
Normal file
File diff suppressed because it is too large
Load Diff
54
platform/linuxbsd/key_mapping_x11.h
Normal file
54
platform/linuxbsd/key_mapping_x11.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*************************************************************************/
|
||||
/* key_mapping_x11.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef KEY_MAPPING_X11_H
|
||||
#define KEY_MAPPING_X11_H
|
||||
|
||||
#include <X11/XF86keysym.h>
|
||||
#include <X11/Xlib.h>
|
||||
#define XK_MISCELLANY
|
||||
#define XK_LATIN1
|
||||
#define XK_XKB_KEYS
|
||||
#include <X11/keysymdef.h>
|
||||
|
||||
#include "core/os/keyboard.h"
|
||||
|
||||
class KeyMappingX11 {
|
||||
KeyMappingX11(){};
|
||||
|
||||
public:
|
||||
static unsigned int get_keycode(KeySym p_keysym);
|
||||
static unsigned int get_scancode(unsigned int p_code);
|
||||
static KeySym get_keysym(unsigned int p_code);
|
||||
static unsigned int get_unicode_from_keysym(KeySym p_keysym);
|
||||
static KeySym get_keysym_from_unicode(unsigned int p_unicode);
|
||||
};
|
||||
|
||||
#endif
|
||||
BIN
platform/linuxbsd/logo.png
Normal file
BIN
platform/linuxbsd/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
381
platform/linuxbsd/os_linuxbsd.cpp
Normal file
381
platform/linuxbsd/os_linuxbsd.cpp
Normal file
@@ -0,0 +1,381 @@
|
||||
/*************************************************************************/
|
||||
/* os_linuxbsd.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "os_linuxbsd.h"
|
||||
|
||||
#include "core/os/dir_access.h"
|
||||
#include "core/print_string.h"
|
||||
#include "errno.h"
|
||||
|
||||
#ifdef HAVE_MNTENT
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "main/main.h"
|
||||
|
||||
#ifdef X11_ENABLED
|
||||
#include "display_server_x11.h"
|
||||
#endif
|
||||
|
||||
void OS_LinuxBSD::initialize() {
|
||||
|
||||
crash_handler.initialize();
|
||||
|
||||
OS_Unix::initialize_core();
|
||||
}
|
||||
|
||||
void OS_LinuxBSD::initialize_joypads() {
|
||||
|
||||
#ifdef JOYDEV_ENABLED
|
||||
joypad = memnew(JoypadLinux(Input::get_singleton()));
|
||||
#endif
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_unique_id() const {
|
||||
|
||||
static String machine_id;
|
||||
if (machine_id.empty()) {
|
||||
if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) {
|
||||
while (machine_id.empty() && !f->eof_reached()) {
|
||||
machine_id = f->get_line().strip_edges();
|
||||
}
|
||||
f->close();
|
||||
memdelete(f);
|
||||
}
|
||||
}
|
||||
return machine_id;
|
||||
}
|
||||
|
||||
void OS_LinuxBSD::finalize() {
|
||||
|
||||
if (main_loop)
|
||||
memdelete(main_loop);
|
||||
main_loop = NULL;
|
||||
|
||||
#ifdef ALSAMIDI_ENABLED
|
||||
driver_alsamidi.close();
|
||||
#endif
|
||||
|
||||
#ifdef JOYDEV_ENABLED
|
||||
memdelete(joypad);
|
||||
#endif
|
||||
}
|
||||
|
||||
MainLoop *OS_LinuxBSD::get_main_loop() const {
|
||||
|
||||
return main_loop;
|
||||
}
|
||||
|
||||
void OS_LinuxBSD::delete_main_loop() {
|
||||
|
||||
if (main_loop)
|
||||
memdelete(main_loop);
|
||||
main_loop = NULL;
|
||||
}
|
||||
|
||||
void OS_LinuxBSD::set_main_loop(MainLoop *p_main_loop) {
|
||||
|
||||
main_loop = p_main_loop;
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_name() const {
|
||||
|
||||
#ifdef __linux__
|
||||
return "Linux";
|
||||
#elif defined(__FreeBSD__)
|
||||
return "FreeBSD";
|
||||
#elif defined(__NetBSD__)
|
||||
return "NetBSD";
|
||||
#else
|
||||
return "BSD";
|
||||
#endif
|
||||
}
|
||||
|
||||
Error OS_LinuxBSD::shell_open(String p_uri) {
|
||||
|
||||
Error ok;
|
||||
List<String> args;
|
||||
args.push_back(p_uri);
|
||||
ok = execute("xdg-open", args, false);
|
||||
if (ok == OK)
|
||||
return OK;
|
||||
ok = execute("gnome-open", args, false);
|
||||
if (ok == OK)
|
||||
return OK;
|
||||
ok = execute("kde-open", args, false);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
|
||||
|
||||
return p_feature == "pc";
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_config_path() const {
|
||||
|
||||
if (has_environment("XDG_CONFIG_HOME")) {
|
||||
return get_environment("XDG_CONFIG_HOME");
|
||||
} else if (has_environment("HOME")) {
|
||||
return get_environment("HOME").plus_file(".config");
|
||||
} else {
|
||||
return ".";
|
||||
}
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_data_path() const {
|
||||
|
||||
if (has_environment("XDG_DATA_HOME")) {
|
||||
return get_environment("XDG_DATA_HOME");
|
||||
} else if (has_environment("HOME")) {
|
||||
return get_environment("HOME").plus_file(".local/share");
|
||||
} else {
|
||||
return get_config_path();
|
||||
}
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_cache_path() const {
|
||||
|
||||
if (has_environment("XDG_CACHE_HOME")) {
|
||||
return get_environment("XDG_CACHE_HOME");
|
||||
} else if (has_environment("HOME")) {
|
||||
return get_environment("HOME").plus_file(".cache");
|
||||
} else {
|
||||
return get_config_path();
|
||||
}
|
||||
}
|
||||
|
||||
String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
|
||||
|
||||
String xdgparam;
|
||||
|
||||
switch (p_dir) {
|
||||
case SYSTEM_DIR_DESKTOP: {
|
||||
|
||||
xdgparam = "DESKTOP";
|
||||
} break;
|
||||
case SYSTEM_DIR_DCIM: {
|
||||
|
||||
xdgparam = "PICTURES";
|
||||
|
||||
} break;
|
||||
case SYSTEM_DIR_DOCUMENTS: {
|
||||
|
||||
xdgparam = "DOCUMENTS";
|
||||
|
||||
} break;
|
||||
case SYSTEM_DIR_DOWNLOADS: {
|
||||
|
||||
xdgparam = "DOWNLOAD";
|
||||
|
||||
} break;
|
||||
case SYSTEM_DIR_MOVIES: {
|
||||
|
||||
xdgparam = "VIDEOS";
|
||||
|
||||
} break;
|
||||
case SYSTEM_DIR_MUSIC: {
|
||||
|
||||
xdgparam = "MUSIC";
|
||||
|
||||
} break;
|
||||
case SYSTEM_DIR_PICTURES: {
|
||||
|
||||
xdgparam = "PICTURES";
|
||||
|
||||
} break;
|
||||
case SYSTEM_DIR_RINGTONES: {
|
||||
|
||||
xdgparam = "MUSIC";
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
String pipe;
|
||||
List<String> arg;
|
||||
arg.push_back(xdgparam);
|
||||
Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, true, NULL, &pipe);
|
||||
if (err != OK)
|
||||
return ".";
|
||||
return pipe.strip_edges();
|
||||
}
|
||||
|
||||
void OS_LinuxBSD::run() {
|
||||
|
||||
force_quit = false;
|
||||
|
||||
if (!main_loop)
|
||||
return;
|
||||
|
||||
main_loop->init();
|
||||
|
||||
//uint64_t last_ticks=get_ticks_usec();
|
||||
|
||||
//int frames=0;
|
||||
//uint64_t frame=0;
|
||||
|
||||
while (!force_quit) {
|
||||
|
||||
DisplayServer::get_singleton()->process_events(); // get rid of pending events
|
||||
#ifdef JOYDEV_ENABLED
|
||||
joypad->process_joypads();
|
||||
#endif
|
||||
if (Main::iteration())
|
||||
break;
|
||||
};
|
||||
|
||||
main_loop->finish();
|
||||
}
|
||||
|
||||
void OS_LinuxBSD::disable_crash_handler() {
|
||||
crash_handler.disable();
|
||||
}
|
||||
|
||||
bool OS_LinuxBSD::is_disable_crash_handler() const {
|
||||
return crash_handler.is_disabled();
|
||||
}
|
||||
|
||||
static String get_mountpoint(const String &p_path) {
|
||||
struct stat s;
|
||||
if (stat(p_path.utf8().get_data(), &s)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef HAVE_MNTENT
|
||||
dev_t dev = s.st_dev;
|
||||
FILE *fd = setmntent("/proc/mounts", "r");
|
||||
if (!fd) {
|
||||
return "";
|
||||
}
|
||||
|
||||
struct mntent mnt;
|
||||
char buf[1024];
|
||||
size_t buflen = 1024;
|
||||
while (getmntent_r(fd, &mnt, buf, buflen)) {
|
||||
if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) {
|
||||
endmntent(fd);
|
||||
return String(mnt.mnt_dir);
|
||||
}
|
||||
}
|
||||
|
||||
endmntent(fd);
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
Error OS_LinuxBSD::move_to_trash(const String &p_path) {
|
||||
String trash_can = "";
|
||||
String mnt = get_mountpoint(p_path);
|
||||
|
||||
// If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can.
|
||||
if (mnt != "") {
|
||||
String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
|
||||
struct stat s;
|
||||
if (!stat(path.utf8().get_data(), &s)) {
|
||||
trash_can = path;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can.
|
||||
if (trash_can == "") {
|
||||
char *dhome = getenv("XDG_DATA_HOME");
|
||||
if (dhome) {
|
||||
trash_can = String(dhome) + "/Trash/files";
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can.
|
||||
if (trash_can == "") {
|
||||
char *home = getenv("HOME");
|
||||
if (home) {
|
||||
trash_can = String(home) + "/.local/share/Trash/files";
|
||||
}
|
||||
}
|
||||
|
||||
// Issue an error if none of the previous locations is appropriate for the trash can.
|
||||
if (trash_can == "") {
|
||||
ERR_PRINT("move_to_trash: Could not determine the trash can location");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
// Create needed directories for decided trash can location.
|
||||
DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
Error err = dir_access->make_dir_recursive(trash_can);
|
||||
memdelete(dir_access);
|
||||
|
||||
// Issue an error if trash can is not created proprely.
|
||||
if (err != OK) {
|
||||
ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\"");
|
||||
return err;
|
||||
}
|
||||
|
||||
// The trash can is successfully created, now move the given resource to it.
|
||||
// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
|
||||
List<String> mv_args;
|
||||
mv_args.push_back(p_path);
|
||||
mv_args.push_back(trash_can);
|
||||
int retval;
|
||||
err = execute("mv", mv_args, true, NULL, NULL, &retval);
|
||||
|
||||
// Issue an error if "mv" failed to move the given resource to the trash can.
|
||||
if (err != OK || retval != 0) {
|
||||
ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\"");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
OS_LinuxBSD::OS_LinuxBSD() {
|
||||
|
||||
main_loop = NULL;
|
||||
force_quit = false;
|
||||
|
||||
#ifdef PULSEAUDIO_ENABLED
|
||||
AudioDriverManager::add_driver(&driver_pulseaudio);
|
||||
#endif
|
||||
|
||||
#ifdef ALSA_ENABLED
|
||||
AudioDriverManager::add_driver(&driver_alsa);
|
||||
#endif
|
||||
|
||||
#ifdef X11_ENABLED
|
||||
DisplayServerX11::register_x11_driver();
|
||||
#endif
|
||||
}
|
||||
106
platform/linuxbsd/os_linuxbsd.h
Normal file
106
platform/linuxbsd/os_linuxbsd.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*************************************************************************/
|
||||
/* os_linuxbsd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef OS_LINUXBSD_H
|
||||
#define OS_LINUXBSD_H
|
||||
|
||||
#include "core/input/input.h"
|
||||
#include "crash_handler_linuxbsd.h"
|
||||
#include "drivers/alsa/audio_driver_alsa.h"
|
||||
#include "drivers/alsamidi/midi_driver_alsamidi.h"
|
||||
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
|
||||
#include "drivers/unix/os_unix.h"
|
||||
#include "joypad_linux.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/visual/rasterizer.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
class OS_LinuxBSD : public OS_Unix {
|
||||
|
||||
virtual void delete_main_loop();
|
||||
|
||||
bool force_quit;
|
||||
|
||||
#ifdef JOYDEV_ENABLED
|
||||
JoypadLinux *joypad;
|
||||
#endif
|
||||
|
||||
#ifdef ALSA_ENABLED
|
||||
AudioDriverALSA driver_alsa;
|
||||
#endif
|
||||
|
||||
#ifdef ALSAMIDI_ENABLED
|
||||
MIDIDriverALSAMidi driver_alsamidi;
|
||||
#endif
|
||||
|
||||
#ifdef PULSEAUDIO_ENABLED
|
||||
AudioDriverPulseAudio driver_pulseaudio;
|
||||
#endif
|
||||
|
||||
CrashHandler crash_handler;
|
||||
|
||||
MainLoop *main_loop;
|
||||
|
||||
protected:
|
||||
virtual void initialize();
|
||||
virtual void finalize();
|
||||
|
||||
virtual void initialize_joypads();
|
||||
|
||||
virtual void set_main_loop(MainLoop *p_main_loop);
|
||||
|
||||
public:
|
||||
virtual String get_name() const;
|
||||
|
||||
virtual MainLoop *get_main_loop() const;
|
||||
|
||||
virtual String get_config_path() const;
|
||||
virtual String get_data_path() const;
|
||||
virtual String get_cache_path() const;
|
||||
|
||||
virtual String get_system_dir(SystemDir p_dir) const;
|
||||
|
||||
virtual Error shell_open(String p_uri);
|
||||
|
||||
virtual String get_unique_id() const;
|
||||
|
||||
virtual bool _check_internal_feature_support(const String &p_feature);
|
||||
|
||||
void run();
|
||||
|
||||
void disable_crash_handler();
|
||||
bool is_disable_crash_handler() const;
|
||||
|
||||
virtual Error move_to_trash(const String &p_path);
|
||||
|
||||
OS_LinuxBSD();
|
||||
};
|
||||
|
||||
#endif
|
||||
10
platform/linuxbsd/pck_embed.ld
Normal file
10
platform/linuxbsd/pck_embed.ld
Normal file
@@ -0,0 +1,10 @@
|
||||
SECTIONS
|
||||
{
|
||||
/* Add a zero-sized section; the exporter will patch it to enclose the data appended to the executable (embedded PCK) */
|
||||
pck 0 (INFO) :
|
||||
{
|
||||
/* binutils >= 2.30 allow it being zero-sized, but needs something between the braces to keep the section */
|
||||
. = ALIGN(8);
|
||||
}
|
||||
}
|
||||
INSERT AFTER .rodata;
|
||||
10
platform/linuxbsd/pck_embed.legacy.ld
Normal file
10
platform/linuxbsd/pck_embed.legacy.ld
Normal file
@@ -0,0 +1,10 @@
|
||||
SECTIONS
|
||||
{
|
||||
/* The exporter will patch this section to enclose the data appended to the executable (embedded PCK) */
|
||||
pck 0 (INFO) : AT ( ADDR (.rodata) + SIZEOF (.rodata) )
|
||||
{
|
||||
/* binutils < 2.30 need some actual content for the linker not to discard the section */
|
||||
BYTE(0);
|
||||
}
|
||||
}
|
||||
INSERT AFTER .rodata;
|
||||
39
platform/linuxbsd/platform_config.h
Normal file
39
platform/linuxbsd/platform_config.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*************************************************************************/
|
||||
/* platform_config.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef __linux__
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#include <stdlib.h>
|
||||
#define PTHREAD_BSD_SET_NAME
|
||||
#endif
|
||||
|
||||
#define GLES2_INCLUDE_H "thirdparty/glad/glad/glad.h"
|
||||
17
platform/linuxbsd/platform_linuxbsd_builders.py
Normal file
17
platform/linuxbsd/platform_linuxbsd_builders.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""Functions used to generate source files during build time
|
||||
|
||||
All such functions are invoked in a subprocess on Windows to prevent build flakiness.
|
||||
|
||||
"""
|
||||
import os
|
||||
from platform_methods import subprocess_main
|
||||
|
||||
|
||||
def make_debug_linuxbsd(target, source, env):
|
||||
os.system('objcopy --only-keep-debug {0} {0}.debugsymbols'.format(target[0]))
|
||||
os.system('strip --strip-debug --strip-unneeded {0}'.format(target[0]))
|
||||
os.system('objcopy --add-gnu-debuglink={0}.debugsymbols {0}'.format(target[0]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
subprocess_main(globals())
|
||||
57
platform/linuxbsd/vulkan_context_x11.cpp
Normal file
57
platform/linuxbsd/vulkan_context_x11.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*************************************************************************/
|
||||
/* vulkan_context_x11.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "vulkan_context_x11.h"
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
|
||||
const char *VulkanContextX11::_get_platform_surface_extension() const {
|
||||
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
|
||||
}
|
||||
|
||||
int VulkanContextX11::window_create(::Window p_window, Display *p_display, int p_width, int p_height) {
|
||||
|
||||
VkXlibSurfaceCreateInfoKHR createInfo;
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.dpy = p_display;
|
||||
createInfo.window = p_window;
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
VkResult err = vkCreateXlibSurfaceKHR(_get_instance(), &createInfo, NULL, &surface);
|
||||
ERR_FAIL_COND_V(err, -1);
|
||||
return _window_create(surface, p_width, p_height);
|
||||
}
|
||||
|
||||
VulkanContextX11::VulkanContextX11() {
|
||||
}
|
||||
|
||||
VulkanContextX11::~VulkanContextX11() {
|
||||
}
|
||||
48
platform/linuxbsd/vulkan_context_x11.h
Normal file
48
platform/linuxbsd/vulkan_context_x11.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*************************************************************************/
|
||||
/* vulkan_context_x11.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef VULKAN_DEVICE_X11_H
|
||||
#define VULKAN_DEVICE_X11_H
|
||||
|
||||
#include "drivers/vulkan/vulkan_context.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
class VulkanContextX11 : public VulkanContext {
|
||||
|
||||
virtual const char *_get_platform_surface_extension() const;
|
||||
|
||||
public:
|
||||
int window_create(::Window p_window, Display *p_display, int p_width, int p_height);
|
||||
|
||||
VulkanContextX11();
|
||||
~VulkanContextX11();
|
||||
};
|
||||
|
||||
#endif // VULKAN_DEVICE_X11_H
|
||||
Reference in New Issue
Block a user