This commit is contained in:
Relintai 2022-03-27 13:36:42 +02:00
parent 996d47081b
commit 09742a48b6
76 changed files with 10805 additions and 0 deletions

100
platform/frt/.clang-format Normal file
View File

@ -0,0 +1,100 @@
#### Quick patch adapting 3.9.1 for 3.5 (debian jessie)
#### (no SortIncludes regardless)
---
BasedOnStyle: LLVM
# Commented out parameters are those with the same value as base LLVM style
# We can uncomment them if we want to change their value, or enforce the
# chosen value in case the base style changes (initial sync: Clang 3.9.1).
...
Language: Cpp
AccessModifierOffset: -4
####AlignAfterOpenBracket: DontAlign
# AlignConsecutiveAssignments: false
# AlignConsecutiveDeclarations: false
# AlignEscapedNewlinesLeft: false
# AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
# AllowShortBlocksOnASingleLine: false
###AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: true
# AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: None
# AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: false
# AlwaysBreakTemplateDeclarations: false
# BinPackArguments: true
# BinPackParameters: true
# BraceWrapping:
# AfterClass: false
# AfterControlStatement: false
# AfterEnum: false
# AfterFunction: false
# AfterNamespace: false
# AfterObjCDeclaration: false
# AfterStruct: false
# AfterUnion: false
# BeforeCatch: false
# BeforeElse: false
# IndentBraces: false
# BreakBeforeBinaryOperators: None
# BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: false
# BreakConstructorInitializersBeforeComma: false
# BreakAfterJavaFieldAnnotations: false
# BreakStringLiterals: true
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
# ConstructorInitializerAllOnOneLineOrOnePerLine: false
# ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
# DerivePointerAlignment: false
# DisableFormat: false
# ExperimentalAutoDetectBinPacking: false
# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
####IncludeCategories:
#### - Regex: '".*"'
#### Priority: 1
#### - Regex: '^<.*\.h>'
#### Priority: 2
#### - Regex: '^<.*'
#### Priority: 3
# IncludeIsMainRegex: '$'
IndentCaseLabels: true
IndentWidth: 4
# IndentWrappedFunctionNames: false
# JavaScriptQuotes: Leave
# JavaScriptWrapImports: true
# KeepEmptyLinesAtTheStartOfBlocks: true
# MacroBlockBegin: ''
# MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1
# NamespaceIndentation: None
####ObjCBlockIndentWidth: 4
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
# PenaltyBreakBeforeFirstCallParameter: 19
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakString: 1000
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
# ReflowComments: true
####SortIncludes: true
# SpaceAfterCStyleCast: false
# SpaceBeforeAssignmentOperators: true
# SpaceBeforeParens: ControlStatements
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpacesInAngles: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
# SpacesInParentheses: false
# SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 4
UseTab: Always
...

8
platform/frt/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
*.o
*.swp
*.pyc
*.bin
a.out
logo.h
*.gen.*
private/

20
platform/frt/.travis.yml Normal file
View File

@ -0,0 +1,20 @@
dist: trusty
sudo: false
language: cpp
os:
- linux
addons:
apt:
packages:
- build-essential
- scons
- pkg-config
- libx11-dev
- libgles2-mesa-dev
- libasound2-dev
- libfreetype6-dev
- libudev-dev
- libpng12-dev
- zlib1g-dev
script:
- make ci

21
platform/frt/CREDITS.txt Normal file
View File

@ -0,0 +1,21 @@
Some code has been imported (almost) verbatim. See import/* from details.
The file os_frt.cpp has been written taking the Godot code base as a reference
(mostly platform/os_x11.cpp).
For other contributions, here is a snippet of the git history of FRT:
==============================================================================
commit a85b77e41ccc08f0e90fa958052c3ca551f6f37f
Author: pacoSan <psandoval@gmail.com>
Date: Wed Oct 16 20:01:41 2019 -0600
kmsdrm
commit f438afc7c5f12a991a5c37534aeec547972ef080
Author: Fabio Alessandrelli <fabio.alessandrelli@gmail.com>
Date: Wed Sep 20 21:29:08 2017 +0200
Add joystick support for RPI

21
platform/frt/LICENSE.txt Normal file
View File

@ -0,0 +1,21 @@
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2019 Emanuele Fornara
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.

View File

@ -0,0 +1,28 @@
GODOT ENGINE
http://www.godotengine.org
************************************************************************
Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.
Copyright (c) 2014-2019 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.
************************************************************************

11
platform/frt/Local.mk Normal file
View File

@ -0,0 +1,11 @@
all:
@echo
@echo FRT is not meant to be compiled stand alone out of the box.
@echo You need to put it in the \"platform\" directory of godot and use
@echo scons as usual.
@echo
@echo For example, from the main top level godot directory, type:
@echo
@echo " " scons platform=frt target=release tools=no frt_arch=pi3
@echo
@echo

16
platform/frt/Makefile Normal file
View File

@ -0,0 +1,16 @@
# Makefile
CLANG_FORMAT = clang-format-3.5
include Local.mk
clean:
rm -f *.o dl/*.gen.* import/*.o
format:
$(CLANG_FORMAT) -i *.cpp *.h bits/*.h import/*.h porting/*.cpp
ci:
git clone -b 3.0-gles2 --depth=1 https://github.com/efornara/godot
ln -s `pwd` godot/platform/frt
( cd godot ; scons platform=frt target=release warnings=no builtin_freetype=yes builtin_libpng=yes builtin_zlib=yes module_openssl_enabled=no module_websocket_enabled=no tools=no frt_arch=pc )

72
platform/frt/README.md Normal file
View File

@ -0,0 +1,72 @@
FRT 1.x
=======
patreon: efornaralabs
https://github.com/efornara/frt
https://github.com/efornara/frt/tree/1.x - 265ddf153c3350b10c4b4c1fd08ddf6cfb67be91
FRT
===
[Godot](https://godotengine.org) is a full 2D and 3D game engine with editor.
FRT is a Godot "platform" targeting single board computers. In plain English,
you can export a Godot game to most of them by using FRT binaries, *as long as
the game has been designed with the limitation of the hardware in mind*.
## When (not) to use FRT
Godot comes with a generic X11 platform that works very well on Pis, as long
as you enable the experimental OpenGL driver (not needed on a Pi 4, not
recommended on Pi 0-1).
So, in general, if you are only interested in exporting games for Pis starting
from the Pi 2, your best option is probably to compile an ARM export template
yourself starting from the official Godot source code.
## How to use FRT
Precompiled versions of FRT can be found here:
<https://sourceforge.net/projects/frt/files/>
And instructions of how to export a game from the Godot editor running on your
PC [here](doc/Usage.md).
If you have come across an FRT game and it is running on the console, you can
press *Win+Q* to close it.
This is the list of meta (Win) keys recognized by FRT when running on
the console (i.e. non on X11):
| Meta | Action |
| :---: | :--- |
| *Q* | *Quit* |
| F | Toggle fullscreen |
| W | Change window gravity |
| K | Grab / ungrab the keyboard |
| M | Grab / ungrab the mouse |
| Return | Mouse Left Button (virtual mouse) |
| Cursor Keys | Mouse Motion (virtual mouse) |
The virtual mouse keys are available only if a keyboard is found, but a
mouse is not.
## User Info
- [ReleaseNotes](doc/ReleaseNotes.md)
- [Usage](doc/Usage.md)
- [Environment](doc/Environment.md)
- [Extensions](doc/Extensions.md)
- [Bugs](doc/Bugs.md)
## Hardware Info
- [Utgard](doc/Utgard.md)
- [VC4](doc/VC4.md)
- [VC6](doc/VC6.md)
## Developer Info
- [Compile](doc/Compile.md)
- [Porting](doc/Porting.md)

28
platform/frt/SCsub Normal file
View File

@ -0,0 +1,28 @@
#! /usr/bin/env python
Import('env')
import sys
dl_path = './dl'
sys.path.append(dl_path)
import procdl
sys.path.remove(dl_path)
env.Append(BUILDERS={'DLH': env.Builder(action=procdl.build_h_action, suffix='.gen.h', src_suffix='.dl')})
env.Append(BUILDERS={'DLCPP': env.Builder(action=procdl.build_cpp_action, suffix='.gen.cpp', src_suffix='.dl')})
for dl in Glob('dl/*.dl'):
env.DLH(str(dl))
env.DLCPP(str(dl))
for libname in ['gles2', 'gles3']:
env.Depends('platform_config.h', 'dl/' + libname + '.gen.h')
frt_env = env.Clone()
import os
if os.path.isfile('/opt/vc/include/bcm_host.h'):
frt_env.Append(CCFLAGS=["-I/opt/vc/include/"])
if os.path.isfile('/usr/include/libdrm/drm.h'):
frt_env.Append(CCFLAGS=["-I/usr/include/libdrm"])
frt_env.Program('#bin/godot', ['godot_frt.cpp', 'os_frt.cpp', 'frt_options.cpp'] + env['FRT_MODULES'])

View File

@ -0,0 +1,116 @@
// egl_base_context.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "dl/egl.gen.h"
namespace frt {
class EGLBaseContext {
private:
void build_attr_list(EGLint *attr_list) {
App *app = App::instance();
int n = 0;
const int color_size = app->get_int_param("color_size");
attr_list[n++] = EGL_RED_SIZE;
attr_list[n++] = color_size;
attr_list[n++] = EGL_GREEN_SIZE;
attr_list[n++] = color_size;
attr_list[n++] = EGL_BLUE_SIZE;
attr_list[n++] = color_size;
const int alpha_size = app->get_int_param("alpha_size");
attr_list[n++] = EGL_ALPHA_SIZE;
attr_list[n++] = alpha_size >= 0 ? alpha_size : EGL_DONT_CARE;
const int depth_size = app->get_int_param("depth_size");
attr_list[n++] = EGL_DEPTH_SIZE;
attr_list[n++] = depth_size >= 0 ? depth_size : EGL_DONT_CARE;
if (app->get_bool_param("multisample")) {
attr_list[n++] = EGL_SAMPLE_BUFFERS;
attr_list[n++] = 1;
}
attr_list[n++] = EGL_SURFACE_TYPE;
attr_list[n++] = EGL_WINDOW_BIT;
attr_list[n++] = EGL_NONE;
}
protected:
EGLDisplay display;
EGLContext context;
EGLSurface surface;
EGLConfig config;
public:
void init(int version, EGLNativeDisplayType display_id = EGL_DEFAULT_DISPLAY) {
static EGLint attr_list[32];
static const EGLint ctx_attrs[] = {
EGL_CONTEXT_CLIENT_VERSION, version,
EGL_NONE
};
EGLBoolean result;
EGLint num_config;
display = eglGetDisplay(display_id);
if (display == EGL_NO_DISPLAY)
fatal("eglGetDisplay failed.");
result = eglInitialize(display, 0, 0);
if (result == EGL_FALSE)
fatal("eglInitialize failed.");
build_attr_list(attr_list);
result = eglChooseConfig(display, attr_list, &config, 1, &num_config);
if (result == EGL_FALSE)
fatal("eglChooseConfig failed.");
result = eglBindAPI(EGL_OPENGL_ES_API);
if (result == EGL_FALSE)
fatal("eglBindAPI failed.");
context = eglCreateContext(display, config, EGL_NO_CONTEXT, ctx_attrs);
if (context == EGL_NO_CONTEXT)
fatal("eglCreateContext failed.");
};
void create_simple_surface(EGLNativeWindowType window_id) {
surface = eglCreateWindowSurface(display, config, window_id, 0);
if (surface == EGL_NO_SURFACE)
fatal("eglCreateWindowSurface failed.");
}
void cleanup() {
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(display, context);
eglTerminate(display);
}
void destroy_surface() {
eglDestroySurface(display, surface);
}
void make_current() {
eglMakeCurrent(display, surface, surface, context);
}
void release_current() {
eglMakeCurrent(display, 0, 0, 0);
}
void swap_buffers() {
eglSwapBuffers(display, surface);
}
void swap_interval(int interval) {
eglSwapInterval(display, interval);
}
};
} // namespace frt

View File

@ -0,0 +1,114 @@
// frt_app_impl.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace frt {
void fatal(const char *format, ...) {
va_list ap;
va_start(ap, format);
fprintf(stderr, "frt: ");
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
}
void App::register_(Module *module) {
if (nm >= max_modules)
return;
m[nm++] = module;
}
Module *App::get(const char *id) const {
for (int i = 0; i < nm; i++)
if (!strcmp(id, m[i]->get_id()))
return m[i];
return 0;
}
Module *App::probe(const char *ids[]) {
for (int i = 0; ids[i]; i++) {
Module *module = get(ids[i]);
if (module && module->probe())
return module;
}
return 0;
}
Module *App::probe_single() {
if (nm != 1)
return 0;
if (!m[0]->probe())
return 0;
return m[0];
}
void **App::get_context(const char *key) {
for (int i = 0; i < nc; i++)
if (!strcmp(key, c[i].key))
return &c[i].value;
if (nc >= max_contexts)
return 0;
c[nc].key = key;
c[nc].value = 0;
return &c[nc++].value;
}
void App::add_dispatcher(EventDispatcher *dispatcher) {
if (nd >= max_dispatchers)
return;
d[nd++] = dispatcher;
}
void App::remove_dispatcher(EventDispatcher *dispatcher) {
int i;
for (i = 0; i < nd; i++)
if (d[i] == dispatcher)
break;
if (i == nd)
return;
nd--;
for (; i < nd; i++)
d[i] = d[i + 1];
}
void App::dispatch_events() {
for (int i = 0; i < nd; i++)
d[i]->dispatch_events();
}
App *App::instance() {
static App *a = 0;
if (!a)
a = new App();
return a;
}
} // namespace frt

View File

@ -0,0 +1,58 @@
// frt_load_gles.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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.
*/
// on pi, skip EGL/GLESv2 in /opt/vc/lib
static const char *lib(const char *s) {
#if defined(__arm__) || defined(__aarch64__)
static char buf[64]; // large enough
strcpy(buf, "/opt/vc/lib/");
strcat(buf, s);
if (access(buf, R_OK) != 0)
return s;
#if defined(__arm__)
strcpy(buf, "/usr/lib/arm-linux-gnueabihf/");
#else
strcpy(buf, "/usr/lib/aarch64-linux-gnu/");
#endif
strcat(buf, s);
return buf;
#else // !pi
return s;
#endif
}
#define FRT_DL_SKIP
#include "dl/gles2.gen.h"
#if FRT_GLES_VERSION == 3
#include "dl/gles3.gen.h"
#endif
static bool frt_load_gles(int version) {
#if FRT_GLES_VERSION == 3
if (version == 3)
return frt_load_gles3(lib("libGLESv2.so.2"));
#endif
return frt_load_gles2(lib("libGLESv2.so.2"));
}

View File

@ -0,0 +1,169 @@
// linux_input.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <linux/input.h>
namespace frt {
static const char *dev_input_id_dir = "/dev/input/by-id";
enum KeyValue { KV_Released,
KV_Pressed,
KV_Repeated };
class LinuxInput {
private:
int fd;
bool grabbed;
bool find_by_name(char *buf, int size, const char *name) {
const char *s_name = "N: Name=\"";
const char *s_handlers = "H: Handlers=";
const char *s_event = "event";
FILE *f = fopen("/proc/bus/input/devices", "r");
if (!f)
return false;
char s[1024];
bool found = false;
int state = 0, nn = strlen(name), ns;
while (fgets(s, sizeof(s), f) && !found) {
switch (state) {
case 0:
if (!strncmp(s_name, s, strlen(s_name))) {
ns = strlen(s);
if (((int)(ns - strlen(s_name) - strlen("\"\n")) == nn)
&& !memcmp(&s[strlen(s_name)], name, nn))
state = 1;
}
break;
case 1:
if (!strncmp(s_handlers, s, strlen(s_handlers))) {
state = 0;
char *event = strstr(s, s_event);
if (!event)
break;
int id = atoi(event + strlen(s_event));
snprintf(buf, size, "/dev/input/event%d", id);
found = true;
}
break;
}
}
fclose(f);
return found;
}
bool open_file(const char *file_name) {
fd = ::open(file_name, O_RDONLY | O_NONBLOCK);
if (fd == -1)
return false;
return true;
}
bool parse_dir(const char *pattern, char *buf, int size) {
bool found = false;
DIR *dirp = opendir(dev_input_id_dir);
if (!dirp)
return false;
while (1) {
struct dirent *dp;
if (!(dp = readdir(dirp)))
break;
const char *id = dp->d_name;
if (strstr(id, pattern)) {
snprintf(buf, size, "%s/%s", dev_input_id_dir, id);
buf[size - 1] = '\0';
found = true;
break;
}
}
closedir(dirp);
return found;
}
bool open_by_id_substr(const char *substr) {
char buf[512];
if (!parse_dir(substr, buf, sizeof(buf)))
return false;
return open_file(buf);
}
protected:
LinuxInput()
: fd(-1), grabbed(false) {}
bool open(const char *env_tag, const char *substr) {
char *id = getenv(env_tag);
if (id) {
char buf[512];
const char *s = 0;
if (id[0] == '/')
s = id;
else if (find_by_name(buf, sizeof(buf), id))
s = buf;
if (s)
return open_file(s);
} else {
return open_by_id_substr(substr);
}
return false;
}
bool grab(bool grab, int wait_ms) {
/*
HACK to let other clients get release keys at startup
TODO: better handling
*/
if (this->grabbed == grab)
return true;
usleep(wait_ms * 1000);
if (ioctl(fd, EVIOCGRAB, grab ? 1 : 0))
return false;
this->grabbed = grab;
return true;
}
void close() {
if (fd != -1) {
::close(fd);
fd = -1;
}
}
bool poll() {
input_event events[64];
while (1) {
int bytes = read(fd, events, sizeof(events));
if (bytes <= 0)
return false;
int n = bytes / sizeof(input_event);
for (int i = 0; i < n; i++)
handle(events[i]);
}
}
// LinuxInput
virtual void handle(const input_event &ev) = 0;
};
} // namespace frt

View File

@ -0,0 +1,110 @@
// mouse_virtual.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "../import/gdkeys.h"
namespace frt {
class MouseVirtual : public Mouse, public EventDispatcher {
private:
static const int speed = 2;
Handler *h;
Vec2 size;
Vec2 pos;
struct {
bool up;
bool down;
bool left;
bool right;
} st;
public:
MouseVirtual()
: h(0) {
st.up = false;
st.down = false;
st.left = false;
st.right = false;
}
// Module
const char *get_id() const { return "mouse_virtual"; }
bool probe() {
App::instance()->add_dispatcher(this);
return true;
}
void cleanup() {
App::instance()->remove_dispatcher(this);
}
bool handle_meta(int gd_code, bool pressed) {
switch (gd_code) {
case GD_KEY_UP:
st.up = pressed;
break;
case GD_KEY_DOWN:
st.down = pressed;
break;
case GD_KEY_LEFT:
st.left = pressed;
break;
case GD_KEY_RIGHT:
st.right = pressed;
break;
case GD_KEY_RETURN:
if (h)
h->handle_mouse_button(Left, pressed);
break;
default:
return false;
}
return true;
}
// EventDispatcher
void dispatch_events() {
if (!st.up && !st.down && !st.left && !st.right)
return;
if (st.up)
pos.y -= speed;
if (st.down)
pos.y += speed;
if (st.left)
pos.x -= speed;
if (st.right)
pos.x += speed;
if (h)
h->handle_mouse_motion(pos);
}
// Mouse
Vec2 get_pos() const { return pos; }
void set_size(Vec2 size) {
this->size = size;
pos.x = size.x - 1;
pos.y = size.y - 1;
}
void set_handler(Handler *handler) {
h = handler;
}
};
} // namespace frt

191
platform/frt/bits/x11.h Normal file
View File

@ -0,0 +1,191 @@
// x11.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <stdlib.h>
#include "dl/x11.gen.h"
namespace frt {
class X11Context;
struct X11User {
private:
friend class X11Context;
X11Context *ctx;
EventHandler *h;
long mask;
const int *types;
bool valid;
X11User()
: valid(false) {}
public:
inline Display *get_display();
inline Window create_window(int width, int height, const char *title);
inline void get_event(XEvent &ev);
inline void release();
};
class X11Context : public EventDispatcher {
private:
friend struct X11User;
static const int max_users = 10;
X11User users[max_users];
int n_users;
bool create_window;
Display *display;
Window window;
XEvent ev;
long current_mask;
long server_mask;
X11Context()
: n_users(0), create_window(true), display(0), window(0), current_mask(0), server_mask(0) {
display = XOpenDisplay(NULL);
}
virtual ~X11Context() {
if (!display)
return;
if (window)
XDestroyWindow(display, window);
XCloseDisplay(display);
}
Window create(int width, int height, const char *title) {
bool undecorated = getenv("FRT_X11_UNDECORATED");
Window root = DefaultRootWindow(display);
XSetWindowAttributes swa;
window = XCreateWindow(display, root, 0, 0,
width, height, 0, CopyFromParent,
InputOutput, CopyFromParent, 0, &swa);
XSizeHints sh;
sh.min_width = width;
sh.min_height = height;
sh.max_width = width;
sh.max_height = height;
sh.flags = PMinSize | PMaxSize;
if (undecorated) {
sh.x = 0;
sh.y = 0;
sh.flags |= PPosition;
}
XSetWMNormalHints(display, window, &sh);
XMapWindow(display, window);
XStoreName(display, window, title);
if (undecorated) {
Atom motif_wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
long hints[5] = { 2, 0, 0, 0, 0 };
XChangeProperty(display, window, motif_wm_hints, motif_wm_hints, 32, PropModeReplace, (unsigned char *)hints, 5);
}
XFlush(display);
return window;
}
X11User *acquire_(long mask, const int *types, EventHandler *handler, bool window_owner) {
for (int i = 0; i < max_users; i++) {
if (users[i].valid)
continue;
n_users++;
users[i].valid = true;
users[i].ctx = this;
users[i].mask = mask;
users[i].types = types;
users[i].h = handler;
if (window_owner)
create_window = false;
current_mask |= users[i].mask;
return &users[i];
}
return 0;
}
void release(X11User *u) {
u->valid = false;
if (--n_users == 0) {
App *app = App::instance();
app->remove_dispatcher(this);
delete this;
X11Context **ctx = (X11Context **)app->get_context("x11");
*ctx = 0;
}
}
// EventDispatcher
void dispatch_events() {
if (create_window && !window)
create(100, 100, FRT_WINDOW_TITLE);
if (current_mask != server_mask) {
XSelectInput(display, window, current_mask);
server_mask = current_mask;
}
while (XPending(display)) {
XNextEvent(display, &ev);
int i;
for (i = 0; i < max_users; i++) {
if (!users[i].valid || !users[i].types)
continue;
const int *t = users[i].types;
for (int j = 0; t[j] != 0; j++) {
if (t[j] == ev.type) {
if (users[i].h)
users[i].h->handle_event();
}
}
}
}
}
/*
Unfortunately, no RAII since users are driven by probe/cleanup.
Be careful: no safeguards here!
*/
public:
static X11User *acquire(long mask, const int *types, EventHandler *handler, bool window_owner = false) {
App *app = App::instance();
X11Context **ctx = (X11Context **)app->get_context("x11");
if (!*ctx) {
if (!frt_load_x11("libX11.so.6"))
return 0;
*ctx = new X11Context();
app->add_dispatcher(*ctx);
}
return (*ctx)->acquire_(mask, types, handler, window_owner);
}
};
inline Display *X11User::get_display() {
return ctx->display;
}
inline Window X11User::create_window(int width, int height, const char *title) {
return ctx->create(width, height, title);
}
inline void X11User::get_event(XEvent &ev) {
ev = ctx->ev;
}
inline void X11User::release() {
if (valid)
ctx->release(this);
}
} // namespace frt

207
platform/frt/detect.py Normal file
View File

@ -0,0 +1,207 @@
import os
import sys
import version
if version.major > 2:
yes = True
no = False
else:
yes = 'yes'
no = 'no'
def has_wrapper_for(lib):
if version.major == 2:
return False
if version.minor > 2:
return True
return False
def is_active():
return True
def get_name():
return 'FRT'
def can_build():
if os.name != 'posix':
return False
return True
def get_opts():
if version.major > 2:
from SCons.Variables import BoolVariable
else:
def BoolVariable(a,b,c): return (a,b,c)
return [
('frt_arch', 'Architecture (no/arm32v6/arm32v7/arm64v8)', 'no'),
('frt_cross', 'Cross compilation (no/auto/<triple>)', 'no'),
BoolVariable('use_llvm', 'Use llvm compiler', no),
BoolVariable('use_lto', 'Use link time optimization', no),
BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically', yes),
BoolVariable('pulseaudio', 'Detect and use pulseaudio', yes),
]
def get_flags():
return [
('tools', no),
]
def check(env, key):
if not (key in env):
return False
if version.major > 2:
return env[key]
else:
return env[key] == 'yes'
def configure(env):
import methods
env.Append(CPPPATH=['#platform/frt'])
if check(env, 'use_llvm'):
if 'clang++' not in env['CXX']:
env['CC'] = 'clang'
env['CXX'] = 'clang++'
env['LD'] = 'clang++'
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
env.extra_suffix += '.llvm'
if check(env, 'use_lto'):
if check(env, 'use_llvm'):
env.Append(CCFLAGS=['-flto=thin'])
env.Append(LINKFLAGS=['-fuse-ld=lld', '-flto=thin'])
env['AR'] = 'llvm-ar'
env['RANLIB'] = 'llvm-ranlib'
else:
env.Append(CCFLAGS=['-flto'])
env.Append(LINKFLAGS=['-flto'])
env.extra_suffix += '.lto'
if env['frt_cross'] != 'no':
if env['frt_cross'] == 'auto':
triple = {
'arm32v7': 'arm-linux-gnueabihf',
'arm64v8': 'aarch64-linux-gnu',
}[env['frt_arch']]
else:
triple = env['frt_cross']
if check(env, 'use_llvm'):
env.Append(CCFLAGS=['-target', triple])
env.Append(LINKFLAGS=['-target', triple])
else:
env['CC'] = triple + '-gcc'
env['CXX'] = triple + '-g++'
pkg_config = triple + '-pkg-config'
else:
pkg_config = 'pkg-config'
env.Append(CCFLAGS=['-pipe'])
env.Append(LINKFLAGS=['-pipe'])
if os.system(pkg_config + ' --exists alsa') == 0:
print('Enabling ALSA')
env.Append(CPPFLAGS=['-DALSA_ENABLED'])
if has_wrapper_for('alsa'):
env['alsa'] = True
else:
env.ParseConfig(pkg_config + ' alsa --cflags --libs')
else:
print('ALSA libraries not found, disabling driver')
if check(env, 'pulseaudio'):
if os.system(pkg_config + ' --exists libpulse') == 0:
print('Enabling PulseAudio')
env.Append(CPPDEFINES=['PULSEAUDIO_ENABLED'])
if version.major == 2:
env.ParseConfig(pkg_config + ' --cflags --libs libpulse-simple')
elif has_wrapper_for('libpulse'):
env.ParseConfig(pkg_config + ' --cflags libpulse')
else:
env.ParseConfig(pkg_config + ' --cflags --libs libpulse')
else:
print('PulseAudio libraries not found, disabling driver')
# pkg-config returns 0 when the lib exists...
found_udev = not os.system(pkg_config + ' --exists libudev')
if found_udev:
print('Enabling udev support')
env.Append(CPPFLAGS=['-DUDEV_ENABLED'])
if has_wrapper_for('udev'):
env.Append(FRT_MODULES=['include/libudev-so_wrap.c'])
else:
env.ParseConfig(pkg_config + ' libudev --cflags --libs')
env.Append(CPPFLAGS=['-DJOYDEV_ENABLED'])
env.Append(FRT_MODULES=['include/joypad_linux.cpp'])
else:
print('libudev development libraries not found, disabling udev support')
if version.major == 2:
if version.minor == 1 and version.patch >=4:
gen_suffix = 'glsl.gen.h'
else:
gen_suffix = 'glsl.h'
env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix=gen_suffix, src_suffix='.glsl')})
env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix=gen_suffix, src_suffix='.glsl')})
env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix=gen_suffix, src_suffix='.glsl')})
if env['target'] == 'release':
env.Append(CCFLAGS=['-O3', '-fomit-frame-pointer'])
elif env['target'] == 'release_debug':
env.Append(CCFLAGS=['-O3', '-DDEBUG_ENABLED'])
elif env['target'] == 'debug':
env.Append(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
if env['target'].startswith('release'):
if version.major == 2 or (version.major == 3 and version.minor == 0):
env.Append(CCFLAGS=['-ffast-math'])
if env['frt_arch'] == 'arm32v6':
env.Append(CCFLAGS=['-march=armv6', '-mfpu=vfp', '-mfloat-abi=hard'])
env.extra_suffix += '.arm32v6'
elif env['frt_arch'] == 'arm32v7':
env.Append(CCFLAGS=['-march=armv7-a', '-mfpu=neon-vfpv4', '-mfloat-abi=hard'])
env.extra_suffix += '.arm32v7'
elif env['frt_arch'] == 'arm64v8':
env.Append(CCFLAGS=['-march=armv8-a'])
env.extra_suffix += '.arm64v8'
env.Append(CFLAGS=['-std=gnu11']) # for libwebp (maybe more in the future)
env.Append(CPPFLAGS=['-DFRT_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DGLES_ENABLED'])
env.Append(LIBS=['pthread'])
if env['frt_arch'] == 'arm32v6' and version.major == 3 and version.minor >= 4: # TODO find out exact combination
env.Append(LIBS=['atomic'])
env.Append(FRT_MODULES=['envprobe.cpp'])
env.Append(FRT_MODULES=['video_fbdev.cpp', 'keyboard_linux_input.cpp', 'mouse_linux_input.cpp'])
env.Append(FRT_MODULES=['video_x11.cpp', 'keyboard_x11.cpp', 'mouse_x11.cpp'])
if version.major >= 3:
env.Append(FRT_MODULES=['import/key_mapping_x11_3.cpp'])
else:
env.Append(FRT_MODULES=['import/key_mapping_x11_2.cpp'])
env.Append(FRT_MODULES=['dl/x11.gen.cpp', 'dl/egl.gen.cpp'])
if os.path.isfile('/opt/vc/include/bcm_host.h'):
env.Append(FRT_MODULES=['video_bcm.cpp', 'dl/bcm.gen.cpp'])
if os.path.isfile('/usr/include/gbm.h'):
env.Append(FRT_MODULES=['video_kmsdrm.cpp', 'dl/gbm.gen.cpp', 'dl/drm.gen.cpp'])
env.Append(FRT_MODULES=['dl/gles2.gen.cpp'])
if version.major >= 3:
env.Append(FRT_MODULES=['dl/gles3.gen.cpp'])
env.Append(LIBS=['dl'])

41
platform/frt/dl/bcm.dl Normal file
View File

@ -0,0 +1,41 @@
// bcm.dl
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <bcm_host.h>
typedef void (*___bcm_host_init___)();
typedef int32_t (*___graphics_get_display_size___)(const uint16_t display_number, uint32_t *width, uint32_t *height);
typedef DISPMANX_DISPLAY_HANDLE_T (*___vc_dispmanx_display_open___)(uint32_t device);
typedef int (*___vc_dispmanx_display_close___)(DISPMANX_DISPLAY_HANDLE_T display);
typedef DISPMANX_RESOURCE_HANDLE_T (*___vc_dispmanx_resource_create___)(VC_IMAGE_TYPE_T type, uint32_t width, uint32_t height, uint32_t *native_image_handle);
typedef int (*___vc_dispmanx_resource_write_data___)(DISPMANX_RESOURCE_HANDLE_T res, VC_IMAGE_TYPE_T src_type, int src_pitch, void * src_address, const VC_RECT_T * rect);
typedef int (*___vc_dispmanx_resource_delete___)(DISPMANX_RESOURCE_HANDLE_T res);
typedef int (*___vc_dispmanx_rect_set___)(VC_RECT_T *rect, uint32_t x_offset, uint32_t y_offset, uint32_t width, uint32_t height);
typedef DISPMANX_ELEMENT_HANDLE_T (*___vc_dispmanx_element_add___)(DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display, int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src, const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection, VC_DISPMANX_ALPHA_T *alpha, DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform);
typedef int (*___vc_dispmanx_element_remove___)(DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element);
typedef int (*___vc_dispmanx_element_change_attributes___)(DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element, uint32_t change_flags, int32_t layer, uint8_t opacity, const VC_RECT_T *dest_rect, const VC_RECT_T *src_rect, DISPMANX_RESOURCE_HANDLE_T mask, DISPMANX_TRANSFORM_T transform);
typedef DISPMANX_UPDATE_HANDLE_T (*___vc_dispmanx_update_start___)(int32_t priority);
typedef int (*___vc_dispmanx_update_submit_sync___)(DISPMANX_UPDATE_HANDLE_T update);
typedef int (*___vc_dispmanx_update_submit___)(DISPMANX_UPDATE_HANDLE_T update, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg);

39
platform/frt/dl/drm.dl Normal file
View File

@ -0,0 +1,39 @@
// drm.dl
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <xf86drm.h>
#include <xf86drmMode.h>
typedef int (*___drmModeAddFB___)(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id);
typedef int (*___drmModeSetCrtc___)(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode);
typedef int (*___drmModeRmFB___)(int fd, uint32_t bufferId);
typedef void (*___drmModeFreeCrtc___)(drmModeCrtcPtr ptr);
typedef drmModeResPtr (*___drmModeGetResources___)(int fd);
typedef drmModeConnectorPtr (*___drmModeGetConnector___)(int fd, uint32_t connectorId);
typedef drmModeEncoderPtr (*___drmModeGetEncoder___)(int fd, uint32_t encoder_id);
typedef drmModeCrtcPtr (*___drmModeGetCrtc___)(int fd, uint32_t crtcId);
typedef void (*___drmModeFreeEncoder___)(drmModeEncoderPtr ptr);
typedef void (*___drmModeFreeConnector___)(drmModeConnectorPtr ptr);
typedef void (*___drmModeFreeResources___)(drmModeResPtr ptr);

42
platform/frt/dl/egl.dl Normal file
View File

@ -0,0 +1,42 @@
// egl.dl
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <EGL/egl.h>
typedef EGLContext (*___eglCreateContext___)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
typedef EGLBoolean (*___eglChooseConfig___)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
typedef EGLBoolean (*___eglGetConfigs___)(EGLDisplay dpy, EGLConfig * configs, EGLint config_size, EGLint * num_config);
typedef EGLBoolean (*___eglGetConfigAttrib___)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint * value);
typedef EGLSurface (*___eglCreateWindowSurface___)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
typedef EGLBoolean (*___eglDestroyContext___)(EGLDisplay dpy, EGLContext ctx);
typedef EGLBoolean (*___eglDestroySurface___)(EGLDisplay dpy, EGLSurface surface);
typedef EGLDisplay (*___eglGetDisplay___)(EGLNativeDisplayType display_id);
typedef EGLBoolean (*___eglInitialize___)(EGLDisplay dpy, EGLint *major, EGLint *minor);
typedef EGLBoolean (*___eglMakeCurrent___)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
typedef EGLBoolean (*___eglSwapBuffers___)(EGLDisplay dpy, EGLSurface surface);
typedef EGLBoolean (*___eglTerminate___)(EGLDisplay dpy);
typedef EGLBoolean (*___eglSwapInterval___)(EGLDisplay dpy, EGLint interval);
typedef EGLBoolean (*___eglBindAPI___)(EGLenum api);
typedef EGLint (*___eglGetError___)();

36
platform/frt/dl/gbm.dl Normal file
View File

@ -0,0 +1,36 @@
// gbm.dl
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <stddef.h>
#include <gbm.h>
typedef struct gbm_bo *(*___gbm_surface_lock_front_buffer___)(struct gbm_surface *surface);
typedef union gbm_bo_handle (*___gbm_bo_get_handle___)(struct gbm_bo *bo);
typedef uint32_t (*___gbm_bo_get_stride___)(struct gbm_bo *bo);
typedef void (*___gbm_surface_release_buffer___)(struct gbm_surface *surface, struct gbm_bo *bo);
typedef void (*___gbm_surface_destroy___)(struct gbm_surface *surface);
typedef void (*___gbm_device_destroy___)(struct gbm_device *gbm);
typedef struct gbm_device *(*___gbm_create_device___)(int fd);
typedef struct gbm_surface *(*___gbm_surface_create___)(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t flags);

171
platform/frt/dl/gles2.dl Normal file
View File

@ -0,0 +1,171 @@
// gles2.dl
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <GLES2/gl2.h>
typedef void (*___glActiveTexture___)(GLenum texture);
typedef void (*___glAttachShader___)(GLuint program, GLuint shader);
typedef void (*___glBindAttribLocation___)(GLuint program, GLuint index, const GLchar *name);
typedef void (*___glBindBuffer___)(GLenum target, GLuint buffer);
typedef void (*___glBindFramebuffer___)(GLenum target, GLuint framebuffer);
typedef void (*___glBindRenderbuffer___)(GLenum target, GLuint renderbuffer);
typedef void (*___glBindTexture___)(GLenum target, GLuint texture);
typedef void (*___glBlendColor___)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
typedef void (*___glBlendEquation___)(GLenum mode);
typedef void (*___glBlendEquationSeparate___)(GLenum modeRGB, GLenum modeAlpha);
typedef void (*___glBlendFunc___)(GLenum sfactor, GLenum dfactor);
typedef void (*___glBlendFuncSeparate___)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
typedef void (*___glBufferData___)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
typedef void (*___glBufferSubData___)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
typedef GLenum (*___glCheckFramebufferStatus___)(GLenum target);
typedef void (*___glClear___)(GLbitfield mask);
typedef void (*___glClearColor___)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
typedef void (*___glClearDepthf___)(GLfloat d);
typedef void (*___glClearStencil___)(GLint s);
typedef void (*___glColorMask___)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
typedef void (*___glCompileShader___)(GLuint shader);
typedef void (*___glCompressedTexImage2D___)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
typedef void (*___glCompressedTexSubImage2D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
typedef void (*___glCopyTexImage2D___)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
typedef void (*___glCopyTexSubImage2D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
typedef GLuint (*___glCreateProgram___)();
typedef GLuint (*___glCreateShader___)(GLenum type);
typedef void (*___glCullFace___)(GLenum mode);
typedef void (*___glDeleteBuffers___)(GLsizei n, const GLuint *buffers);
typedef void (*___glDeleteFramebuffers___)(GLsizei n, const GLuint *framebuffers);
typedef void (*___glDeleteProgram___)(GLuint program);
typedef void (*___glDeleteRenderbuffers___)(GLsizei n, const GLuint *renderbuffers);
typedef void (*___glDeleteShader___)(GLuint shader);
typedef void (*___glDeleteTextures___)(GLsizei n, const GLuint *textures);
typedef void (*___glDepthFunc___)(GLenum func);
typedef void (*___glDepthMask___)(GLboolean flag);
typedef void (*___glDepthRangef___)(GLfloat n, GLfloat f);
typedef void (*___glDetachShader___)(GLuint program, GLuint shader);
typedef void (*___glDisable___)(GLenum cap);
typedef void (*___glDisableVertexAttribArray___)(GLuint index);
typedef void (*___glDrawArrays___)(GLenum mode, GLint first, GLsizei count);
typedef void (*___glDrawElements___)(GLenum mode, GLsizei count, GLenum type, const void *indices);
typedef void (*___glEnable___)(GLenum cap);
typedef void (*___glEnableVertexAttribArray___)(GLuint index);
typedef void (*___glFinish___)();
typedef void (*___glFlush___)();
typedef void (*___glFramebufferRenderbuffer___)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
typedef void (*___glFramebufferTexture2D___)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
typedef void (*___glFrontFace___)(GLenum mode);
typedef void (*___glGenBuffers___)(GLsizei n, GLuint *buffers);
typedef void (*___glGenerateMipmap___)(GLenum target);
typedef void (*___glGenFramebuffers___)(GLsizei n, GLuint *framebuffers);
typedef void (*___glGenRenderbuffers___)(GLsizei n, GLuint *renderbuffers);
typedef void (*___glGenTextures___)(GLsizei n, GLuint *textures);
typedef void (*___glGetActiveAttrib___)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
typedef void (*___glGetActiveUniform___)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
typedef void (*___glGetAttachedShaders___)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
typedef GLint (*___glGetAttribLocation___)(GLuint program, const GLchar *name);
typedef void (*___glGetBooleanv___)(GLenum pname, GLboolean *data);
typedef void (*___glGetBufferParameteriv___)(GLenum target, GLenum pname, GLint *params);
typedef GLenum (*___glGetError___)();
typedef void (*___glGetFloatv___)(GLenum pname, GLfloat *data);
typedef void (*___glGetFramebufferAttachmentParameteriv___)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
typedef void (*___glGetIntegerv___)(GLenum pname, GLint *data);
typedef void (*___glGetProgramiv___)(GLuint program, GLenum pname, GLint *params);
typedef void (*___glGetProgramInfoLog___)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (*___glGetRenderbufferParameteriv___)(GLenum target, GLenum pname, GLint *params);
typedef void (*___glGetShaderiv___)(GLuint shader, GLenum pname, GLint *params);
typedef void (*___glGetShaderInfoLog___)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (*___glGetShaderPrecisionFormat___)(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
typedef void (*___glGetShaderSource___)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
typedef const GLubyte * (*___glGetString___)(GLenum name);
typedef void (*___glGetTexParameterfv___)(GLenum target, GLenum pname, GLfloat *params);
typedef void (*___glGetTexParameteriv___)(GLenum target, GLenum pname, GLint *params);
typedef void (*___glGetUniformfv___)(GLuint program, GLint location, GLfloat *params);
typedef void (*___glGetUniformiv___)(GLuint program, GLint location, GLint *params);
typedef GLint (*___glGetUniformLocation___)(GLuint program, const GLchar *name);
typedef void (*___glGetVertexAttribfv___)(GLuint index, GLenum pname, GLfloat *params);
typedef void (*___glGetVertexAttribiv___)(GLuint index, GLenum pname, GLint *params);
typedef void (*___glGetVertexAttribPointerv___)(GLuint index, GLenum pname, void **pointer);
typedef void (*___glHint___)(GLenum target, GLenum mode);
typedef GLboolean (*___glIsBuffer___)(GLuint buffer);
typedef GLboolean (*___glIsEnabled___)(GLenum cap);
typedef GLboolean (*___glIsFramebuffer___)(GLuint framebuffer);
typedef GLboolean (*___glIsProgram___)(GLuint program);
typedef GLboolean (*___glIsRenderbuffer___)(GLuint renderbuffer);
typedef GLboolean (*___glIsShader___)(GLuint shader);
typedef GLboolean (*___glIsTexture___)(GLuint texture);
typedef void (*___glLineWidth___)(GLfloat width);
typedef void (*___glLinkProgram___)(GLuint program);
typedef void (*___glPixelStorei___)(GLenum pname, GLint param);
typedef void (*___glPolygonOffset___)(GLfloat factor, GLfloat units);
typedef void (*___glReadPixels___)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
typedef void (*___glReleaseShaderCompiler___)();
typedef void (*___glRenderbufferStorage___)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (*___glSampleCoverage___)(GLfloat value, GLboolean invert);
typedef void (*___glScissor___)(GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (*___glShaderBinary___)(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
typedef void (*___glShaderSource___)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
typedef void (*___glStencilFunc___)(GLenum func, GLint ref, GLuint mask);
typedef void (*___glStencilFuncSeparate___)(GLenum face, GLenum func, GLint ref, GLuint mask);
typedef void (*___glStencilMask___)(GLuint mask);
typedef void (*___glStencilMaskSeparate___)(GLenum face, GLuint mask);
typedef void (*___glStencilOp___)(GLenum fail, GLenum zfail, GLenum zpass);
typedef void (*___glStencilOpSeparate___)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
typedef void (*___glTexImage2D___)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
typedef void (*___glTexParameterf___)(GLenum target, GLenum pname, GLfloat param);
typedef void (*___glTexParameterfv___)(GLenum target, GLenum pname, const GLfloat *params);
typedef void (*___glTexParameteri___)(GLenum target, GLenum pname, GLint param);
typedef void (*___glTexParameteriv___)(GLenum target, GLenum pname, const GLint *params);
typedef void (*___glTexSubImage2D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
typedef void (*___glUniform1f___)(GLint location, GLfloat v0);
typedef void (*___glUniform1fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform1i___)(GLint location, GLint v0);
typedef void (*___glUniform1iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniform2f___)(GLint location, GLfloat v0, GLfloat v1);
typedef void (*___glUniform2fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform2i___)(GLint location, GLint v0, GLint v1);
typedef void (*___glUniform2iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniform3f___)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
typedef void (*___glUniform3fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform3i___)(GLint location, GLint v0, GLint v1, GLint v2);
typedef void (*___glUniform3iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniform4f___)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
typedef void (*___glUniform4fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform4i___)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
typedef void (*___glUniform4iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniformMatrix2fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix3fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix4fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUseProgram___)(GLuint program);
typedef void (*___glValidateProgram___)(GLuint program);
typedef void (*___glVertexAttrib1f___)(GLuint index, GLfloat x);
typedef void (*___glVertexAttrib1fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttrib2f___)(GLuint index, GLfloat x, GLfloat y);
typedef void (*___glVertexAttrib2fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttrib3f___)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
typedef void (*___glVertexAttrib3fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttrib4f___)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (*___glVertexAttrib4fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttribPointer___)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (*___glViewport___)(GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (*___glRenderbufferStorageMultisample___)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);

273
platform/frt/dl/gles3.dl Normal file
View File

@ -0,0 +1,273 @@
// gles3.dl
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <GLES3/gl3.h>
typedef void (*___glActiveTexture___)(GLenum texture);
typedef void (*___glAttachShader___)(GLuint program, GLuint shader);
typedef void (*___glBindAttribLocation___)(GLuint program, GLuint index, const GLchar *name);
typedef void (*___glBindBuffer___)(GLenum target, GLuint buffer);
typedef void (*___glBindFramebuffer___)(GLenum target, GLuint framebuffer);
typedef void (*___glBindRenderbuffer___)(GLenum target, GLuint renderbuffer);
typedef void (*___glBindTexture___)(GLenum target, GLuint texture);
typedef void (*___glBlendColor___)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
typedef void (*___glBlendEquation___)(GLenum mode);
typedef void (*___glBlendEquationSeparate___)(GLenum modeRGB, GLenum modeAlpha);
typedef void (*___glBlendFunc___)(GLenum sfactor, GLenum dfactor);
typedef void (*___glBlendFuncSeparate___)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
typedef void (*___glBufferData___)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
typedef void (*___glBufferSubData___)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
typedef GLenum (*___glCheckFramebufferStatus___)(GLenum target);
typedef void (*___glClear___)(GLbitfield mask);
typedef void (*___glClearColor___)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
typedef void (*___glClearDepthf___)(GLfloat d);
typedef void (*___glClearStencil___)(GLint s);
typedef void (*___glColorMask___)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
typedef void (*___glCompileShader___)(GLuint shader);
typedef void (*___glCompressedTexImage2D___)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
typedef void (*___glCompressedTexSubImage2D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
typedef void (*___glCopyTexImage2D___)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
typedef void (*___glCopyTexSubImage2D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
typedef GLuint (*___glCreateProgram___)();
typedef GLuint (*___glCreateShader___)(GLenum type);
typedef void (*___glCullFace___)(GLenum mode);
typedef void (*___glDeleteBuffers___)(GLsizei n, const GLuint *buffers);
typedef void (*___glDeleteFramebuffers___)(GLsizei n, const GLuint *framebuffers);
typedef void (*___glDeleteProgram___)(GLuint program);
typedef void (*___glDeleteRenderbuffers___)(GLsizei n, const GLuint *renderbuffers);
typedef void (*___glDeleteShader___)(GLuint shader);
typedef void (*___glDeleteTextures___)(GLsizei n, const GLuint *textures);
typedef void (*___glDepthFunc___)(GLenum func);
typedef void (*___glDepthMask___)(GLboolean flag);
typedef void (*___glDepthRangef___)(GLfloat n, GLfloat f);
typedef void (*___glDetachShader___)(GLuint program, GLuint shader);
typedef void (*___glDisable___)(GLenum cap);
typedef void (*___glDisableVertexAttribArray___)(GLuint index);
typedef void (*___glDrawArrays___)(GLenum mode, GLint first, GLsizei count);
typedef void (*___glDrawElements___)(GLenum mode, GLsizei count, GLenum type, const void *indices);
typedef void (*___glEnable___)(GLenum cap);
typedef void (*___glEnableVertexAttribArray___)(GLuint index);
typedef void (*___glFinish___)();
typedef void (*___glFlush___)();
typedef void (*___glFramebufferRenderbuffer___)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
typedef void (*___glFramebufferTexture2D___)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
typedef void (*___glFrontFace___)(GLenum mode);
typedef void (*___glGenBuffers___)(GLsizei n, GLuint *buffers);
typedef void (*___glGenerateMipmap___)(GLenum target);
typedef void (*___glGenFramebuffers___)(GLsizei n, GLuint *framebuffers);
typedef void (*___glGenRenderbuffers___)(GLsizei n, GLuint *renderbuffers);
typedef void (*___glGenTextures___)(GLsizei n, GLuint *textures);
typedef void (*___glGetActiveAttrib___)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
typedef void (*___glGetActiveUniform___)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
typedef void (*___glGetAttachedShaders___)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
typedef GLint (*___glGetAttribLocation___)(GLuint program, const GLchar *name);
typedef void (*___glGetBooleanv___)(GLenum pname, GLboolean *data);
typedef void (*___glGetBufferParameteriv___)(GLenum target, GLenum pname, GLint *params);
typedef GLenum (*___glGetError___)();
typedef void (*___glGetFloatv___)(GLenum pname, GLfloat *data);
typedef void (*___glGetFramebufferAttachmentParameteriv___)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
typedef void (*___glGetIntegerv___)(GLenum pname, GLint *data);
typedef void (*___glGetProgramiv___)(GLuint program, GLenum pname, GLint *params);
typedef void (*___glGetProgramInfoLog___)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (*___glGetRenderbufferParameteriv___)(GLenum target, GLenum pname, GLint *params);
typedef void (*___glGetShaderiv___)(GLuint shader, GLenum pname, GLint *params);
typedef void (*___glGetShaderInfoLog___)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (*___glGetShaderPrecisionFormat___)(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
typedef void (*___glGetShaderSource___)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
typedef const GLubyte * (*___glGetString___)(GLenum name);
typedef void (*___glGetTexParameterfv___)(GLenum target, GLenum pname, GLfloat *params);
typedef void (*___glGetTexParameteriv___)(GLenum target, GLenum pname, GLint *params);
typedef void (*___glGetUniformfv___)(GLuint program, GLint location, GLfloat *params);
typedef void (*___glGetUniformiv___)(GLuint program, GLint location, GLint *params);
typedef GLint (*___glGetUniformLocation___)(GLuint program, const GLchar *name);
typedef void (*___glGetVertexAttribfv___)(GLuint index, GLenum pname, GLfloat *params);
typedef void (*___glGetVertexAttribiv___)(GLuint index, GLenum pname, GLint *params);
typedef void (*___glGetVertexAttribPointerv___)(GLuint index, GLenum pname, void **pointer);
typedef void (*___glHint___)(GLenum target, GLenum mode);
typedef GLboolean (*___glIsBuffer___)(GLuint buffer);
typedef GLboolean (*___glIsEnabled___)(GLenum cap);
typedef GLboolean (*___glIsFramebuffer___)(GLuint framebuffer);
typedef GLboolean (*___glIsProgram___)(GLuint program);
typedef GLboolean (*___glIsRenderbuffer___)(GLuint renderbuffer);
typedef GLboolean (*___glIsShader___)(GLuint shader);
typedef GLboolean (*___glIsTexture___)(GLuint texture);
typedef void (*___glLineWidth___)(GLfloat width);
typedef void (*___glLinkProgram___)(GLuint program);
typedef void (*___glPixelStorei___)(GLenum pname, GLint param);
typedef void (*___glPolygonOffset___)(GLfloat factor, GLfloat units);
typedef void (*___glReadPixels___)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
typedef void (*___glReleaseShaderCompiler___)();
typedef void (*___glRenderbufferStorage___)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (*___glSampleCoverage___)(GLfloat value, GLboolean invert);
typedef void (*___glScissor___)(GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (*___glShaderBinary___)(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
typedef void (*___glShaderSource___)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
typedef void (*___glStencilFunc___)(GLenum func, GLint ref, GLuint mask);
typedef void (*___glStencilFuncSeparate___)(GLenum face, GLenum func, GLint ref, GLuint mask);
typedef void (*___glStencilMask___)(GLuint mask);
typedef void (*___glStencilMaskSeparate___)(GLenum face, GLuint mask);
typedef void (*___glStencilOp___)(GLenum fail, GLenum zfail, GLenum zpass);
typedef void (*___glStencilOpSeparate___)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
typedef void (*___glTexImage2D___)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
typedef void (*___glTexParameterf___)(GLenum target, GLenum pname, GLfloat param);
typedef void (*___glTexParameterfv___)(GLenum target, GLenum pname, const GLfloat *params);
typedef void (*___glTexParameteri___)(GLenum target, GLenum pname, GLint param);
typedef void (*___glTexParameteriv___)(GLenum target, GLenum pname, const GLint *params);
typedef void (*___glTexSubImage2D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
typedef void (*___glUniform1f___)(GLint location, GLfloat v0);
typedef void (*___glUniform1fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform1i___)(GLint location, GLint v0);
typedef void (*___glUniform1iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniform2f___)(GLint location, GLfloat v0, GLfloat v1);
typedef void (*___glUniform2fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform2i___)(GLint location, GLint v0, GLint v1);
typedef void (*___glUniform2iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniform3f___)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
typedef void (*___glUniform3fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform3i___)(GLint location, GLint v0, GLint v1, GLint v2);
typedef void (*___glUniform3iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniform4f___)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
typedef void (*___glUniform4fv___)(GLint location, GLsizei count, const GLfloat *value);
typedef void (*___glUniform4i___)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
typedef void (*___glUniform4iv___)(GLint location, GLsizei count, const GLint *value);
typedef void (*___glUniformMatrix2fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix3fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix4fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUseProgram___)(GLuint program);
typedef void (*___glValidateProgram___)(GLuint program);
typedef void (*___glVertexAttrib1f___)(GLuint index, GLfloat x);
typedef void (*___glVertexAttrib1fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttrib2f___)(GLuint index, GLfloat x, GLfloat y);
typedef void (*___glVertexAttrib2fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttrib3f___)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
typedef void (*___glVertexAttrib3fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttrib4f___)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (*___glVertexAttrib4fv___)(GLuint index, const GLfloat *v);
typedef void (*___glVertexAttribPointer___)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (*___glViewport___)(GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (*___glReadBuffer___)(GLenum src);
typedef void (*___glDrawRangeElements___)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
typedef void (*___glTexImage3D___)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
typedef void (*___glTexSubImage3D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
typedef void (*___glCopyTexSubImage3D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (*___glCompressedTexImage3D___)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
typedef void (*___glCompressedTexSubImage3D___)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
typedef void (*___glGenQueries___)(GLsizei n, GLuint *ids);
typedef void (*___glDeleteQueries___)(GLsizei n, const GLuint *ids);
typedef GLboolean (*___glIsQuery___)(GLuint id);
typedef void (*___glBeginQuery___)(GLenum target, GLuint id);
typedef void (*___glEndQuery___)(GLenum target);
typedef void (*___glGetQueryiv___)(GLenum target, GLenum pname, GLint *params);
typedef void (*___glGetQueryObjectuiv___)(GLuint id, GLenum pname, GLuint *params);
typedef GLboolean (*___glUnmapBuffer___)(GLenum target);
typedef void (*___glGetBufferPointerv___)(GLenum target, GLenum pname, void **params);
typedef void (*___glDrawBuffers___)(GLsizei n, const GLenum *bufs);
typedef void (*___glUniformMatrix2x3fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix3x2fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix2x4fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix4x2fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix3x4fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glUniformMatrix4x3fv___)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*___glBlitFramebuffer___)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
typedef void (*___glRenderbufferStorageMultisample___)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (*___glFramebufferTextureLayer___)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
typedef void * (*___glMapBufferRange___)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
typedef void (*___glFlushMappedBufferRange___)(GLenum target, GLintptr offset, GLsizeiptr length);
typedef void (*___glBindVertexArray___)(GLuint array);
typedef void (*___glDeleteVertexArrays___)(GLsizei n, const GLuint *arrays);
typedef void (*___glGenVertexArrays___)(GLsizei n, GLuint *arrays);
typedef GLboolean (*___glIsVertexArray___)(GLuint array);
typedef void (*___glGetIntegeri_v___)(GLenum target, GLuint index, GLint *data);
typedef void (*___glBeginTransformFeedback___)(GLenum primitiveMode);
typedef void (*___glEndTransformFeedback___)();
typedef void (*___glBindBufferRange___)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
typedef void (*___glBindBufferBase___)(GLenum target, GLuint index, GLuint buffer);
typedef void (*___glTransformFeedbackVaryings___)(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
typedef void (*___glGetTransformFeedbackVarying___)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
typedef void (*___glVertexAttribIPointer___)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
typedef void (*___glGetVertexAttribIiv___)(GLuint index, GLenum pname, GLint *params);
typedef void (*___glGetVertexAttribIuiv___)(GLuint index, GLenum pname, GLuint *params);
typedef void (*___glVertexAttribI4i___)(GLuint index, GLint x, GLint y, GLint z, GLint w);
typedef void (*___glVertexAttribI4ui___)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
typedef void (*___glVertexAttribI4iv___)(GLuint index, const GLint *v);
typedef void (*___glVertexAttribI4uiv___)(GLuint index, const GLuint *v);
typedef void (*___glGetUniformuiv___)(GLuint program, GLint location, GLuint *params);
typedef GLint (*___glGetFragDataLocation___)(GLuint program, const GLchar *name);
typedef void (*___glUniform1ui___)(GLint location, GLuint v0);
typedef void (*___glUniform2ui___)(GLint location, GLuint v0, GLuint v1);
typedef void (*___glUniform3ui___)(GLint location, GLuint v0, GLuint v1, GLuint v2);
typedef void (*___glUniform4ui___)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
typedef void (*___glUniform1uiv___)(GLint location, GLsizei count, const GLuint *value);
typedef void (*___glUniform2uiv___)(GLint location, GLsizei count, const GLuint *value);
typedef void (*___glUniform3uiv___)(GLint location, GLsizei count, const GLuint *value);
typedef void (*___glUniform4uiv___)(GLint location, GLsizei count, const GLuint *value);
typedef void (*___glClearBufferiv___)(GLenum buffer, GLint drawbuffer, const GLint *value);
typedef void (*___glClearBufferuiv___)(GLenum buffer, GLint drawbuffer, const GLuint *value);
typedef void (*___glClearBufferfv___)(GLenum buffer, GLint drawbuffer, const GLfloat *value);
typedef void (*___glClearBufferfi___)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
typedef const GLubyte * (*___glGetStringi___)(GLenum name, GLuint index);
typedef void (*___glCopyBufferSubData___)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
typedef void (*___glGetUniformIndices___)(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
typedef void (*___glGetActiveUniformsiv___)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
typedef GLuint (*___glGetUniformBlockIndex___)(GLuint program, const GLchar *uniformBlockName);
typedef void (*___glGetActiveUniformBlockiv___)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
typedef void (*___glGetActiveUniformBlockName___)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
typedef void (*___glUniformBlockBinding___)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
typedef void (*___glDrawArraysInstanced___)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
typedef void (*___glDrawElementsInstanced___)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
typedef GLsync (*___glFenceSync___)(GLenum condition, GLbitfield flags);
typedef GLboolean (*___glIsSync___)(GLsync sync);
typedef void (*___glDeleteSync___)(GLsync sync);
typedef GLenum (*___glClientWaitSync___)(GLsync sync, GLbitfield flags, GLuint64 timeout);
typedef void (*___glWaitSync___)(GLsync sync, GLbitfield flags, GLuint64 timeout);
typedef void (*___glGetInteger64v___)(GLenum pname, GLint64 *data);
typedef void (*___glGetSynciv___)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
typedef void (*___glGetInteger64i_v___)(GLenum target, GLuint index, GLint64 *data);
typedef void (*___glGetBufferParameteri64v___)(GLenum target, GLenum pname, GLint64 *params);
typedef void (*___glGenSamplers___)(GLsizei count, GLuint *samplers);
typedef void (*___glDeleteSamplers___)(GLsizei count, const GLuint *samplers);
typedef GLboolean (*___glIsSampler___)(GLuint sampler);
typedef void (*___glBindSampler___)(GLuint unit, GLuint sampler);
typedef void (*___glSamplerParameteri___)(GLuint sampler, GLenum pname, GLint param);
typedef void (*___glSamplerParameteriv___)(GLuint sampler, GLenum pname, const GLint *param);
typedef void (*___glSamplerParameterf___)(GLuint sampler, GLenum pname, GLfloat param);
typedef void (*___glSamplerParameterfv___)(GLuint sampler, GLenum pname, const GLfloat *param);
typedef void (*___glGetSamplerParameteriv___)(GLuint sampler, GLenum pname, GLint *params);
typedef void (*___glGetSamplerParameterfv___)(GLuint sampler, GLenum pname, GLfloat *params);
typedef void (*___glVertexAttribDivisor___)(GLuint index, GLuint divisor);
typedef void (*___glBindTransformFeedback___)(GLenum target, GLuint id);
typedef void (*___glDeleteTransformFeedbacks___)(GLsizei n, const GLuint *ids);
typedef void (*___glGenTransformFeedbacks___)(GLsizei n, GLuint *ids);
typedef GLboolean (*___glIsTransformFeedback___)(GLuint id);
typedef void (*___glPauseTransformFeedback___)();
typedef void (*___glResumeTransformFeedback___)();
typedef void (*___glGetProgramBinary___)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
typedef void (*___glProgramBinary___)(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
typedef void (*___glProgramParameteri___)(GLuint program, GLenum pname, GLint value);
typedef void (*___glInvalidateFramebuffer___)(GLenum target, GLsizei numAttachments, const GLenum *attachments);
typedef void (*___glInvalidateSubFramebuffer___)(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (*___glTexStorage2D___)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (*___glTexStorage3D___)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
typedef void (*___glGetInternalformativ___)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);

11
platform/frt/dl/minidl.sh Executable file
View File

@ -0,0 +1,11 @@
#! /bin/sh
for filename in $* ; do
echo -n "Processing $filename... "
libname=`basename "$filename" .dl`
grep '^#include' <"$libname.dl" >"$libname.gen.h"
echo >>"$libname.gen.h" \
"static inline bool frt_load_$libname(const char *) { return true; }"
rm -f "$libname.gen.cpp"
echo "done."
done

141
platform/frt/dl/procdl.py Executable file
View File

@ -0,0 +1,141 @@
#! /usr/bin/python
# procdl.py
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017 Emanuele Fornara
#
# 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.
#
import re
def parse_dl(dl, suffix):
libname = 'unnamed'
head = ''
symbols = []
types = []
includes = []
f_dl = open(dl, 'r')
for line in f_dl.readlines():
line = line.replace('\n', '')
if libname == 'unnamed':
m = re.search(r'^//\s*(.*)\.dl\s*$', line)
if m:
libname = m.group(1)
head += '// ' + libname + suffix
head += ' - File generated by procdl.py - DO NOT EDIT\n'
continue
m = re.search(r'^.*___(.*)___.*$', line)
if not m:
if re.search(r'^#include', line):
includes.append(line)
else:
head += line + '\n'
continue
s = m.group(1)
symbols.append(s)
ls = libname + '_' + s
types.append(line.replace('___' + s + '___', 'FRT_FN_' + ls))
f_dl.close()
return (libname, head, symbols, types, includes)
def build_h(dl, h):
libname, head, symbols, types, includes = parse_dl(dl, '.gen.h')
f = open(h, 'w')
f.write(head)
def out(s=None):
if s:
f.write(s)
f.write('\n')
out('#ifndef FRT_DL_SKIP')
for s in includes:
out(s)
out()
for s in types:
out(s)
out()
for s in symbols:
ls = libname + '_' + s
out('#define ' + s + ' frt_fn_' + ls)
out()
for s in symbols:
ls = libname + '_' + s
out('extern FRT_FN_' + ls + ' frt_fn_' + ls + ';')
out()
out('#endif')
out('extern bool frt_load_' + libname + '(const char *filename);')
f.close()
def build_cpp(dl, cpp):
libname, head, symbols, types, includes = parse_dl(dl, '.gen.cpp')
f = open(cpp, 'w')
f.write(head)
assignments = ''
for s in symbols:
ls = libname + '_' + s
assignments += 'FRT_FN_' + ls + ' frt_fn_' + ls + ' = 0;\n'
resolutions = ''
for s in symbols:
ls = libname + '_' + s
resolutions += '\tfrt_fn_' + ls + ' = (FRT_FN_' + ls + ')'
resolutions += 'dlsym(lib, "' + s + '");\n'
f.write("""\
#include "%(libname)s.gen.h"
#include <stdio.h>
#include <dlfcn.h>
static void *lib = 0;
%(assignments)s
bool frt_load_%(libname)s(const char *filename) {
if (lib)
return true;
lib = dlopen(filename, RTLD_LAZY);
if (!lib) {
fprintf(stderr, "frt: dlopen failed for '%%s'.\\n", filename);
return false;
}
%(resolutions)s
return true;
}
""" % {
'libname': libname,
'assignments': assignments[:-1],
'resolutions': resolutions[:-1]
})
f.close()
def build_cpp_action(target, source, env):
build_cpp(str(source[0]), str(target[0]))
def build_h_action(target, source, env):
build_h(str(source[0]), str(target[0]))
if __name__ == '__main__':
import sys
for s in sys.argv[1:]:
sys.stdout.write('Processing ' + s + '... ')
build_cpp(s, s.replace('.dl', '.gen.cpp'))
build_h(s, s.replace('.dl', '.gen.h'))
sys.stdout.write('done.\n')

45
platform/frt/dl/x11.dl Normal file
View File

@ -0,0 +1,45 @@
// x11.dl
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <X11/Xlib.h>
#include <X11/Xutil.h>
typedef Display *(*___XOpenDisplay___)(_Xconst char *);
typedef int (*___XCloseDisplay___)(Display *);
typedef Window (*___XCreateWindow___)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *);
typedef int (*___XDestroyWindow___)(Display *, Window);
typedef int (*___XMapWindow___)(Display *, Window);
typedef int (*___XStoreName___)(Display *, Window, _Xconst char *);
typedef int (*___XFlush___)(Display *);
typedef int (*___XSelectInput___)(Display *, Window, long);
typedef int (*___XPending___)(Display *);
typedef int (*___XNextEvent___)(Display *, XEvent *);
typedef int (*___XPeekEvent___)(Display *, XEvent *);
typedef int (*___XWarpPointer___)(Display *, Window, Window, int, int, unsigned int, unsigned int, int, int);
typedef int (*___XLookupString___)(XKeyEvent *, char *, int, KeySym *, XComposeStatus *);
typedef void (*___XSetWMNormalHints___)(Display *, Window, XSizeHints *);
typedef Atom (*___XInternAtom___)(Display *, _Xconst char *, Bool);
typedef Status (*___XSetWMProtocols___)(Display *, Window, Atom *, int);
typedef int (*___XChangeProperty___)(Display *, Window, Atom, Atom, int, int, _Xconst unsigned char *, int);

38
platform/frt/doc/Bugs.md Normal file
View File

@ -0,0 +1,38 @@
Bugs
====
When reading the list of known bugs below, please keep this in mind:
- FRT has been written with the idea of treating SBCs as cheap and open game
consoles, so some features you can find on the official Godot x11 platform,
like cut and paste, drag and drop, or more in general proper desktop
integration, are out of scope for FRT.
- Apart from the now deprecated 3.0-gles2 version, most of the code, and the
rendering code in particular, is unpatched from the official Godot codebase.
However, the code-path used is roughly the one used on mobile phones. If you
find a bug, check upstream with similar bugs on phones with a similar SoC to
the one used in your board.
- There are different code-paths within FRT, so it can behave differently on
different hardware and even on different configurations of the same
hardware.
- Major refactoring work in the FRT codebase is on hold until Godot 4.0
reaches beta / release candidate stage.
## Common
- No proper fullscreen support
## Module: `video_bcm`
- Might panic the kernel if 3D is used in Godot 3.2
## Module: `video_kmsdms` and `video_fbdev`
- No mouse pointer
## Module: `keyboard_linux_input`
- Might provide the wrong key presses on some layouts

158
platform/frt/doc/Compile.md Normal file
View File

@ -0,0 +1,158 @@
Compile
=======
To compile the Godot templates on a Pi, start from the official
3.1-stable source tarball:
<https://github.com/godotengine/godot/releases/tag/3.1-stable>
These packages should be enough:
$ sudo apt-get install build-essential scons pkg-config libx11-dev libgles2-mesa-dev libasound2-dev libfreetype6-dev libudev-dev libpng12-dev zlib1g-dev clang
## Compile Godot (X11)
To compile the official X11 platform, this is, in theory, what you should do:
$ cd ~/godot-3.1-stable
$ scons platform=x11 target=release tools=no -j 4
In practice, it is better to give the compiler some flags to better target
the CPU of the Pi, and especially its FPU.
For example (Pi 2/3):
$ scons platform=x11 target=release tools=no CCFLAGS="-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -mlittle-endian -munaligned-access" -j 4
Or (Pi 1/Zero):
$ scons platform=x11 target=release tools=no CCFLAGS="-mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -mlittle-endian -munaligned-access" -j 4
You might need to use clang on some versions of debian. If so, add:
use_llvm=yes
You might also need to disable some modules, for example:
module_webm_enabled=no
See `release.sh` for the options that are used to generate the official
FRT release binaries, keeping in mind that they are generated on a
debian jessie chroot environment (gcc 4.9.2, so there is no need to use clang)
and that SSL is disabled (so you might want to omit the relevant options if
you want to enable it).
## Compile Godot (FRT)
FRT can be compiled against the Godot engine source as it is.
However there are some optional patches that you might want to apply
to the engine. See the `patches` directory. FRT release binaries are
generated applying the patches.
Go to the platform directory and clone this repository:
$ cd ~/godot-3.1-stable
$ cd platform
$ git clone https://github.com/efornara/frt
From the main directory, you now have a new "platform" available:
$ cd ~/godot-3.1-stable
$ scons platform=frt target=release frt_arch=pi3 -j 4
Unlike the X11 platform, FRT disables tools by default and preselect
some CPU-specific options according to frt\_arch.
When compiling on a real Pi, using an external Hard Disk is
strongly advised: everything is faster and more reliable, and you can
enable a swap partition without stressing the Memory Card.
Swap is hardly used, especially if you start Raspbian without the GUI,
but enabling it allows you to use `-j 4` and leave the compilation
unattended.
Compiling godot-3.1-stable + FRT from scratch on a non-overclocked
Pi 3 running Raspbian jessie should take about one hour.
## Compile Godot (FRT) to run on a PC
On some Linux systems, FRT can run on a desktop. This can be useful
to test the ES 2.0 rendering pipeline directly on a PC.
Intel IGPs are known to work.
Just repeat the steps above from your Linux PC and build FRT without
setting the architecture:
$ scons platform=frt target=release -j 8
## Cross compile (QEMU)
These are a few notes on how to cross-compile FRT on a PC running debian
stable (stretch). A standard armv7 debian is used as a target. See
below on tips on using Raspbian as a target.
There might be better ways, and compilation is quite slow
(around 5 hours to compile godot-2.1.4-stable from scratch on a,
quite slow, Acer C7 C710-2847).
The official FRT release binaries are not cross-compiled. They are generated
on a Pi.
Familiarity with the Linux environment is assumed.
Notes based on
<https://wiki.debian.org/EmDebian/CrossDebootstrap>
Install debootstrap and qemu:
[host] # apt-get install binfmt-support qemu qemu-user-static debootstrap
Download and install the base system:
[host] # cd /opt
[host] # mkdir arm7hf
[host] # qemu-debootstrap --arch armhf jessie arm7hf http://deb.debian.org/debian
Mount the proc filesystem:
[host] # mount -t proc proc /opt/arm7hf/proc
Chroot into the system and create a user (with uid/gid matching your main
user on the host; no action should be required if your main user is the
first user created):
[host] # LC_ALL=C chroot /opt/arm7hf bash
[chroot] # adduser user
...
Install the needed packages:
[chroot] # apt-get update
[chroot] # apt-get upgrade -y
[chroot] # apt-get install -y build-essential scons pkg-config libx11-dev libgles2-mesa-dev libasound2-dev libfreetype6-dev libudev-dev libpng12-dev zlib1g-dev
From another terminal, and using your main user on the host (note the `$`
prompt), clone the Godot and FRT repositories:
[host] $ cd /opt/arm7hf/home/user
[host] $ git clone https://github.com/efornara/godot 3.0-gles2
[host] $ cd 3.0-gles2/platform
[host] $ git clone https://github.com/efornara/frt
Back on the chroot environment, compile Godot:
[chroot] # su - user
[chroot] $ cd 3.0-gles2
[chroot] $ nice scons platform=frt target=release frt_arch=arm7hf module_webm_enabled=no builtin_freetype=yes -j 2
...
### Raspbian
- Download the Raspbian keyring and use it with qemu-debootstrap
- Check the chroot `/etc/apt/source.list` after debootstrap, and reset it
to the Raspbian repository if needed.
### BCM
- Download the raspberry firmware to compile BCM support. Only the
include directory (`/opt/vc/include`) is needed as the libraries are
dynamically loaded.

View File

@ -0,0 +1,68 @@
Environment
===========
Environment variables can be passed to FRT like this:
export FRT_KMSDRM_DEVICE=/dev/dri/renderD128
frt_096_216_pi2.bin -path ~/mygame
Or like this:
FRT_KMSDRM_DEVICE=/dev/dri/renderD128 frt_096_216_pi2.bin -path ~/mygame
In most cases, you shouldn't need to set environment variables to use FRT.
## `FRT_X11_UNDECORATED`
Ask the window manager not to decorate the window, and force its position
to be at 0,0.
Work around the lack of fullscreen support in the X11 module. Intended to be
used together with --resolution (or -r for Godot 2).
## `FRT_KEYBOARD_ID` and `FRT_MOUSE_ID`
If FRT fails to select the correct device for your keyboard and/or your mouse,
you can force it to by specifying either the full path of the device, or its
name as seen by the input bus. For example, to find out which name to use, you
can use the following command:
grep Name= /proc/bus/input/devices
`FRT_KEYBOARD_ID` can also be used to let FRT open a "virtual keyboard". For
example (GPIOnext):
FRT_KEYBOARD_ID="GPIOnext Keyboard"
or (Adafruit-Retrogame):
FRT_KEYBOARD_ID=retrogame
These variables are not relevant under X11.
## `FRT_KMSDRM_DEVICE`
Selection of the dri card to use is done by an heuristic tuned for the
Pis. For other devices, you might have to select it manually. For
example:
FRT_KMSDRM_DEVICE=/dev/dri/renderD128
## `FRT_MODULES`
This should be used as a last resort and only if you know what you are doing.
Forcing a module that cannot run is likely to result in FRT just crashing.
To override which modules are loaded by FRT, use the following pattern:
FRT_MODULES=<video>,<keyboard>,<mouse>
For example, this forces FRT to use the legacy fbdev module (Mali binary
driver for FBDEV):
FRT_MODULES=video_fbdev,keyboard_linux_input,mouse_linux_input
And this prevents FRT from grabbing/using the keyboard and the mouse:
FRT_MODULES=video_kmsdrm,,

View File

@ -0,0 +1,101 @@
Extensions
==========
FRT provides a few non-intrusive extensions compared to the official
godot platforms. Note that some of them might be removed in the future
if the official godot starts to provide other means to address the same
issues.
## Command Line
When you invoke godot, arguments starting from the option `--frt` are
intercepted by FRT. For example:
godot.frt.opt.pi1 myscene.tscn --frt -h
will not start godot. Instead, a message like the following is printed
to stdout:
usage: godot.frt.opt.pi1 [godot args] [--frt [options] [param=value...]]
options:
-v show version and exit
-h show this page and exit
-p perfmon.csv save performance monitor data
-e resource extract resource
params:
color_size
alpha_size
depth_size
multisample
disable_meta_keys
blacklist_video_bcm
exit_on_shiftenter
The performance monitor data has been added because I have found that a
non-optimized build of godot/frt is much slower than an optimized build,
so letting the optimized build dump data to be analyzed later is a
better alternative than to try to connect to an editor from a
non-optimized build.
Resource extraction makes it easy to embed small files in single-file
games. For example, if you export a standard 2.1.3 project as an EXE
using the Linux template, but giving the editor `godot.frt.opt.pi1` as a
custom binary, you end up with a single file, say `mygame` that you can
gzip and distribute.
Users should be able to just run the game, but they could also type:
mygame --frt -e README.md
to extract a README file.
Only resources in the res://frt/ folder can be extracted this way, and
there are strict limits on the characters that you can use for the name
of the resource (the first character must be alphanumeric - the
following ones can also be '.', '-' and '\_').
## Parameters
You can add some options in the custom section "frt" of the project
settings. The section is not required and is in any case ignored by the
standard godot platforms.
For example, adding this:
[frt]
depth_size = 24
multisample = true
to `engine.cfg` will allow you to tune the engine.
You can also override or set the values from the command line. For
example, if you have a third-party game that shows some artifacts that
you suspect might be due to godot/frt using a 16-bit depth buffer by
default, you can try running it like this:
godot.frt.opt.pi1 --frt depth_size=24
### Disabling the meta keys
If you already provide a way to close the game (for example, using an
in-game menu), you might prefer to disable the handling of meta keys
by FRT.
Be careful that, since FRT grabs the keyboard when running without X11,
the user might not be able to quit the game in any other way.
### Blacklisting the bcm driver
The Godot 3.x rendering engine might have problems with some 3D games running
with the bcm video driver. In some cases, the Linux kernel could crash.
Unless you can test extensively, it is probably safer to blacklist the bcm
driver when releasing 3D games using Godot 3.x.
The game will run normally when running with other drivers, but will exit
suggesting to switch to the vc4 driver when running with the bcm driver.
### Exit the game when pressing Shift+Enter
Provides a universal way to terminate the process that matches the default
key configuration in RetroPie.

View File

@ -0,0 +1,82 @@
Porting
=======
FRT is a modular system, and FRT modules can be developed and tested mostly in
isolation, without compiling them as part of Godot. The idea is that
developing and testing a module can be done on a real board with a very quick
test cycle. Once the module is tested, it can be compiled as part of Godot.
As an example, compiling and linking every FRT module from scratch takes less
than 5 seconds on a Pi 2. Relinking them takes less than 1 second.
As another example, compiling and linking the `video_fbdev` module on a
A10-based board takes less than 3 seconds.
Modules don't need to be generic. For example, you could access a custom
device via GPIO and make a custom module implementing the `frt::Keyboard`
interface. You can then use it instead of one of the standard keyboard
modules.
## Compiling and Testing a Module
To get familiar with the process, here is how to compile and test the
`mouse_x11` module on a Linux debian desktop. Either clone the repository
or uncompress the FRT source tarball:
$ git clone https://github.com/efornara/frt
$ cd frt
The X11 FRT modules can dynamically load the `libX11.so` library. The loading
code is not included in the repository and it is generated by a python script.
If you have python available, you can generate the loading code like this:
$ cd dl
$ ./procdl.py x11.dl
You will then have to compile and link the generated `x11.gen.cpp` file.
If you don't have python available, you can use a shell script that generates
a mock `x11.gen.h` file instead:
$ ./minidl.py x11.dl
In this case, there is no 'x11.gen.cpp` file to compile and link.
In the `porting` directory, there is a sample `Makefile`. It has been written
so that there shouldn't be a need to change it. Instead, changes can be made
to the `Local.mk` file. If you are using git, you don't need to commit the
file to the repository and you can just soft-link the real one to it:
$ cd ../porting
$ make local
git update-index --assume-unchanged Local.mk
$ touch Test.mk
$ ln -sf Test.mk Local.mk
Here is an example `Test.mk` for the python-generated dynamic loading code.
OBJS += test_mouse.o mouse_x11.o x11.gen.o
LIBS += -ldl
And here is an example `Test.mk` for the mock dynamic loading header:
OBJS += test_mouse.o mouse_x11.o
LIBS += -lX11
You can then compile and test the module like this:
$ make run
## Tips
- If you have a powerful board, consider starting the Godot compilation in
background, making sure to choose compilation options carefully as changing
them later can trigger a full recompile. Also, make sure that ALSA and udev
are enabled (if you need them).
- If you don't have a powerful board, consider cross compiling.
- If you need to add preprocessor definitions or special include directories to
the compiler command line, add them in the cloned `frt_env` environment
defined in `SCsub`. This way, they will only be used when compiling the files
in `platform/frt` and changing them will not trigger a full recompile.

View File

@ -0,0 +1,40 @@
Release Notes
=============
## FRT 1.1.0
The code itself is unchanged compared to FRT 1.0.0. However:
- Backported cross compilation support from the 2.0 branch.
- New architecture tags (arm32v6, arm32v7 and arm64v8) replace the old
ones (pi1, pi2 and arm64).
- The official binaries are now compiled on buster instead of jessie.
For Godot 2, clang is used, and for Godot 3, gcc is used. arm32v6
builds are compiled on an arm device (Pi 3B+), and arm32v7/arm64v8
builds are cross-compiled using a docker container on a PC.
See efornara/crossbuild.
## FRT 1.0.0
- Released additional binaries that link against pulseaudio. Godot 3.3 is
able to dynamically load alsa or pulseaudio, so a single binary without
hard dependencies on either is provided starting with Godot 3.3.
- Not really about FRT, but the way Godot 3.3 allocates the shadow buffer
has changed, and might cause problems on some low-end devices.
If you are developing a 2D game, make sure to state your intent by
setting Framebuffer Allocation to 2D in the Project Settings (Rendering /
Quality / Intended Usage) and, if you use Viewports, by setting Usage
to 2D in the their properties (Rendering).
- Added the `FRT_X11_UNDECORATED` environment variable, to work around the
lack of fullscreen support in the x11 module.
- Added the `exit_on_shiftenter` parameter, to provide a universal way to
terminate the process that matches the default key configuration in
RetroPie.
- Fixed a Physics initialization bug.

117
platform/frt/doc/Usage.md Normal file
View File

@ -0,0 +1,117 @@
Usage
=====
FRT focuses on the runtime / export template only (i.e. not on the editor).
You can use the official editor on Windows, Linux or MacOS to package a game.
Compile FRT, or download and uncompress a binary from:
<https://sourceforge.net/projects/frt/files>
## Picking a version
### Platform: X11 vs FRT
Export templates for the official X11 platform can be easily generated and
they work on a Pi, *provided that you switch to the new GL driver*.
If this limitation is acceptable to you, there is no reason to use FRT.
Also, the X11 platform supports the X11 environment far better than FRT.
Nowadays, the main reason to use FRT is to run Godot on a KMS/DRM-based
distro like RetroPie.
## Exporting a game
### Godot 2.1
To pack a game, use the Linux X11 Platform. Uncheck "64 Bits",
uncheck "Debugging Enabled" and point the Custom Binary / Release file to
the uncompressed FRT binary.
### Godot 3.0 / 3.1
You can generally use the Linux X11 Platform as for Godot 2.
However, if you use compressed textures (e.g. 3D Games), you need to
select the appropriate texture format (Etc). Since this combination
(Etc for X11) might not be well tested upstream, you might need
to use the Android export template and generate a PCK/ZIP file instead.
## Binary Releases
Starting from FRT 0.9.3, binary releases follow the following naming
convention:
frt\_*frt-version*\_*godot-version*\_*arch-tag*.bin
For example:
frt\_110\_342\_arm32v7.bin
is FRT 1.1.0 compiled against Godot 3.4.2-stable. It is compiled for
a 32-bit distro.
The architecture tags have been changed in FRT 1.1.0. The change of
naming reflects different compilation flags being used.
- *arm32v6* and *arm32v7*. For 32-bit distros. Most users would want arm32v7.
The arm32v6 versions are provided to support older Pis.
- *arm64v8*. For 64-bit distros. I hardly test them myself, but they are
increasingly popular, so they are quite tested by users.
## Demos
A few exported demo projects are available for testing:
<https://sourceforge.net/projects/frt/files/demos>
For ease of notation, this page assumes that the chosen binary has been
renamed to `godot2.frt.bin` (for Godot 2.1) or `godot3.frt.bin`
(for Godot 3.0 - 3.2) and it has been installed somewhere in `$PATH`.
### Godot 2.1
You can unzip a demo and run it by either switching to its directory
or giving its directory as a command line option:
~ $ mkdir demo
~ $ cd demo
~/demo $ unzip ~/Downloads/21_2d_platformer.zip
~/demo $ godot2.frt.bin
~/demo $ cd
~ $ godot2.frt.bin -path demo
You cal also run a demo PCK/ZIP directly:
~ $ godot2.frt.bin -main_pack ~/Downloads/21_2d_platformer.zip
You can finally put the demo PCK/ZIP in the same directory as the
binary and give them the same base name:
~ $ mkdir tmp
~ $ cd tmp
~/tmp $ cp ~/Downloads/21_2d_platformer.zip platformer.zip
~/tmp $ cp /usr/local/bin/godot2.frt.bin platformer.bin
~/tmp $ ./platformer.bin
### Godot 3.0 - 3.2
Just like for Godot 2, you can unzip a demo (just use `--path`),
rename it, or run it directly (just use `--main-pack`).
The version of Godot 3.0 supported by FRT (3.0-gles2) defaults to GLES2.
If your board supports GLES3, you can run a GLES3 demo on it, but
you have to select the GLES3 renderer explicitly:
~ $ godot3.frt.bin --video-driver GLES3 --main-pack ~/Downloads/30_2d_platformer.zip
GPU Particles should now be working. GLES3 has only been tested on a PC with
an Intel Graphics Card (Sandybridge Mobile) running debian stretch.
For a (quite heavy) 3D demo you can try:
~ $ godot3.frt.bin --video-driver GLES3 --main-pack ~/Downloads/30_3d_material_testers.pck
Please note that the above Intel GPU can only render a few frames per seconds
of this demo. It might be helpful to add an option like `--resolution 320x240`
to the command line.

View File

@ -0,0 +1,42 @@
Utgard
======
Utgard is an old architecture, but it is the architecture of very cheap and
popular boards.
There are two drivers for it: an open-source one (Lima) and a closed-source,
legacy one.
## Lima Driver
One way to install the Lima driver is to start from the armbian buster
"server" image appropriate to your board, install the -dev version of the
Linux kernel and compile the latest mesa yourself.
On my test A10-based board, I have to use the following environment variables:
export FRT_KMSDRM_DEVICE=/dev/dri/renderD128
export LD_LIBRARY_PATH=/usr/local/lib
Some 2.1 demos don't work (among others, IIRC, one of the two 3D materials and
the 2D isometric light one), but most 2D demos, and the 2D platformer in
particular, run well.
## Legacy Driver
If you ever wondered why the official FRT binaries are compiled on a jessie
debootstrap chroot, this driver is the reason.
It is a pain to use because it only supports old versions of the Linux kernel,
but it is full-featured. The Lima driver is already useable and it is the one
I would personally use, but for some use cases, the legacy driver is still the
way to go.
I recommend that you use a X11-based image.
In theory, you could start from a server image and compile a couple of
libraries to go along with the proprietary blob, but you are basically on your
own. FRT includes a fbdev video module, but it is more of starting point /
proof of concept than an useable module. It works but it flickers badly, and I
no longer maintain it. Anyway, if you have one of these boards, and you are up
for a challenge, patches are welcome.

31
platform/frt/doc/VC4.md Normal file
View File

@ -0,0 +1,31 @@
VC4
===
Used on Pis 0-3 and very well documented.
There are two drivers for it: an open-source one (vc4) and a closed-source,
legacy one (bcm).
## New Driver (vc4)
As of today, users have to enable it manually on Raspbian,
Usually, too slow to be used on Pis 0-1.
Very good integration with the Linux standard ecosystem, both X11 and KMS/DRM.
## Legacy Driver (bcm)
As of today, the default driver on Raspbian.
The only realistic option for Pis 0-1: it uses a coprocessor (other than the
main CPU and the main 3D core), and so it can offload some of the work from
the CPU.
No interaction with the X11 desktop.
## Known Limitations
- 3D on Godot 3.x only works with the vc4 driver.
- 2D particles on Godot 3.x don't work.

10
platform/frt/doc/VC6.md Normal file
View File

@ -0,0 +1,10 @@
VC6
===
Used on Pi 4. Not as well documented as VC4, but with a well maintained open
source driver.
It has been reported to work.
As of today, the driver exposes OpenGL ES 3.x but not desktop OpenGL 3.x, so
to use the GLES3 renderer you have to use FRT.

202
platform/frt/envprobe.cpp Normal file
View File

@ -0,0 +1,202 @@
// envprobe.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <dlfcn.h>
using namespace frt;
#define FRT_ENV_ERROR 0
#define FRT_ENV_BCM 1
#define FRT_ENV_X11 2
#define FRT_ENV_KMSDRM 3
#define FRT_ENV_BCM_NOLIB 4
static bool bcm_installed() {
#if defined(__arm__) || defined(__aarch64__)
return access("/opt/vc/lib/libbrcmEGL.so", R_OK) == 0;
#else
return false;
#endif
}
static bool find(const char *filename, bool (*pred)(const char *)) {
FILE *f = fopen(filename, "r");
if (!f)
return false;
char s[1024];
bool found = false;
while (fgets(s, sizeof(s), f)) {
if (pred(s)) {
found = true;
break;
}
}
fclose(f);
return found;
}
static bool pi_predicate(const char *line) {
return !strncmp("Hardware", line, 8) && strstr(line, "BCM2835");
}
static bool pi() {
return find("/proc/cpuinfo", pi_predicate);
}
static bool pi4_predicate(const char *line) {
return (bool)strstr(line, "aspberry Pi 4");
}
static bool pi4() {
return find("/sys/firmware/devicetree/base/model", pi4_predicate);
}
static bool has_vc4_predicate(const char *line) {
return !strncmp("vc4 ", line, 4);
}
static bool has_vc4() {
return find("/proc/modules", has_vc4_predicate);
}
static bool has_x11() {
void *lib = 0;
if (!(lib = dlopen("libX11.so.6", RTLD_LAZY)))
return false;
typedef void *(*FN_XOpenDisplay)(const char *);
typedef int (*FN_XCloseDisplay)(void *);
FN_XOpenDisplay fn_XOpenDisplay = (FN_XOpenDisplay)dlsym(lib, "XOpenDisplay");
FN_XCloseDisplay fn_XCloseDisplay = (FN_XCloseDisplay)dlsym(lib, "XCloseDisplay");
void *display = fn_XOpenDisplay(NULL);
if (display)
fn_XCloseDisplay(display);
dlclose(lib);
return (bool)display;
}
static int probe_environment() {
if (pi() && !pi4()) {
if (has_vc4()) {
if (has_x11())
return FRT_ENV_X11;
else
return FRT_ENV_KMSDRM;
} else {
if (bcm_installed())
return FRT_ENV_BCM;
else
return FRT_ENV_BCM_NOLIB;
}
} else {
if (has_x11())
return FRT_ENV_X11;
else
return FRT_ENV_KMSDRM;
}
}
static const char *next_module(char **state) {
char *s = *state;
if (!s)
return 0;
for (int i = 0; s[i]; i++)
if (s[i] == ',') {
s[i] = '\0';
*state = &s[i + 1];
return s;
}
*state = 0;
return s;
}
static bool probe_environment_override(Env *env) {
char *modules = getenv("FRT_MODULES");
if (!modules)
return false;
char *s = strdup(modules);
char *state = s;
const char *video = next_module(&state);
const char *keyboard = next_module(&state);
const char *mouse = next_module(&state);
const char *guard = next_module(&state);
if (guard || !mouse) {
printf("frt: expected FRT_MODULES=<video>,<keyboard>,<mouse>\n");
exit(1);
}
App *app = App::instance();
env->video = (Video *)app->probe(video);
env->keyboard = (Keyboard *)app->probe(keyboard);
env->mouse = (Mouse *)app->probe(mouse);
free(s);
return true;
}
namespace frt {
class EnvProbeImpl : public EnvProbe {
public:
// Module
const char *get_id() const { return "envprobe"; }
bool probe() { return true; }
void cleanup() {}
// EnvProbe
void probe_env(Env *env) {
if (probe_environment_override(env))
return;
App *app = App::instance();
switch (probe_environment()) {
case FRT_ENV_BCM:
env->video = (Video *)app->probe("video_bcm");
env->keyboard = (Keyboard *)app->probe("keyboard_linux_input");
env->mouse = (Mouse *)app->probe("mouse_linux_input");
break;
case FRT_ENV_X11:
env->video = (Video *)app->probe("video_x11");
env->keyboard = (Keyboard *)app->probe("keyboard_x11");
env->mouse = (Mouse *)app->probe("mouse_x11");
break;
case FRT_ENV_KMSDRM:
env->video = (Video *)app->probe("video_kmsdrm");
env->keyboard = (Keyboard *)app->probe("keyboard_linux_input");
env->mouse = (Mouse *)app->probe("mouse_linux_input");
break;
case FRT_ENV_BCM_NOLIB:
printf("frt: no libbrcmEGL.so found.\n");
exit(1);
}
}
};
FRT_REGISTER(EnvProbeImpl)
} // namespace frt

245
platform/frt/frt.h Normal file
View File

@ -0,0 +1,245 @@
// frt.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 FRT_H
#define FRT_H
#define FRT_WINDOW_TITLE "Godot / FRT"
#define FRT_VERSION "1.1.0"
#include <stdint.h>
struct InputModifierState;
namespace frt {
void fatal(const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 1, 2)))
#endif
;
struct Module {
virtual const char *get_id() const = 0;
virtual bool probe() = 0;
virtual void cleanup() = 0;
virtual bool handle_meta(int gd_code, bool pressed) { return false; }
};
struct EventDispatcher {
virtual void dispatch_events() = 0;
};
struct EventHandler {
virtual void handle_event() = 0;
};
struct Value {
enum Type {
Bool,
Int,
Float,
String,
} t;
union {
bool b;
int i;
float f;
const char *s;
} u;
Value(bool v)
: t(Bool) { u.b = v; }
Value(int v)
: t(Int) { u.i = v; }
Value(float v)
: t(Float) { u.f = v; }
Value(const char *v)
: t(String) { u.s = v; }
};
struct Param {
const char *name;
Value value;
enum Source {
Default,
CommandLine,
ProjectSettings,
} source;
Param(const char *name_, Value value_)
: name(name_), value(value_), source(Default) {}
};
class App {
public:
static const int max_modules = 30;
static const int max_contexts = 10;
static const int max_dispatchers = 10;
void register_(Module *module);
int size() const { return nm; }
Module *get(int i) const { return m[i]; }
Module *get(const char *id) const;
Module *probe(const char *ids[]);
Module *probe_single();
Module *probe(const char *id) {
const char *ids[] = { id, 0 };
return probe(ids);
}
void **get_context(const char *key);
void add_dispatcher(EventDispatcher *dispatcher);
void remove_dispatcher(EventDispatcher *dispatcher);
void dispatch_events();
void quit() { running = false; }
bool is_running() const { return running; }
void parse_args(int *argc, char ***argv);
int get_n_of_params() const;
Param *get_param(int i) const;
Param *get_param(const char *name) const;
bool get_bool_param(const char *name) const {
return get_param(name)->value.u.b;
}
int get_int_param(const char *name) const {
return get_param(name)->value.u.i;
}
float get_float_param(const char *name) const {
return get_param(name)->value.u.f;
}
const char *get_string_param(const char *name) const {
return get_param(name)->value.u.s;
}
static App *instance();
private:
App()
: nm(0), nc(0), nd(0), running(true) {}
Module *m[max_modules];
struct {
const char *key;
void *value;
} c[max_contexts];
EventDispatcher *d[max_dispatchers];
int nm, nc, nd;
bool running;
};
struct RegisterModule {
RegisterModule(Module *module) {
App::instance()->register_(module);
}
};
#define FRT_REGISTER(C) \
static C C##_instance; \
static frt::RegisterModule C##_helper(&C##_instance);
struct Vec2 {
int x;
int y;
Vec2(int x_ = 0, int y_ = 0)
: x(x_), y(y_) {}
};
struct ContextGL {
virtual void release_current() = 0;
virtual void make_current() = 0;
virtual void swap_buffers() = 0;
virtual int get_window_width() = 0;
virtual int get_window_height() = 0;
virtual bool initialize() = 0;
virtual void set_use_vsync(bool use) = 0;
virtual bool is_using_vsync() const = 0;
};
struct Video : public Module {
virtual Vec2 get_screen_size() const = 0;
virtual Vec2 get_view_size() const = 0;
virtual void set_title(const char *title) = 0;
virtual Vec2 move_pointer(const Vec2 &screen) = 0;
virtual void show_pointer(bool enable) = 0;
virtual ContextGL *create_the_gl_context(int version, Vec2 view) = 0;
virtual bool provides_quit() = 0;
};
struct Keyboard : public Module {
struct Handler {
virtual void handle_keyboard_key(int gd_code, bool pressed, uint32_t unicode, bool echo) = 0;
};
virtual void set_handler(Handler *handler) = 0;
virtual void get_modifier_state(InputModifierState &state) const = 0;
};
struct Mouse : public Module {
enum Button {
Left,
Middle,
Right,
WheelUp,
WheelDown
};
struct Handler {
virtual void handle_mouse_button(Button button, bool pressed) = 0;
virtual void handle_mouse_motion(Vec2 pos) = 0;
};
virtual Vec2 get_pos() const = 0;
virtual void set_size(Vec2 size) = 0;
virtual void set_handler(Handler *handler) = 0;
};
struct Env {
Video *video;
Keyboard *keyboard;
Mouse *mouse;
};
struct EnvProbe : public Module {
virtual void probe_env(Env *env) = 0;
};
struct Runnable : public Module {
virtual void setup_env(Env *env) = 0;
virtual void run_() = 0;
virtual int get_exit_code_() = 0;
};
} // namespace frt
#ifdef FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
struct InputModifierState {
bool shift;
bool alt;
bool control;
bool meta;
};
#endif // FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#ifdef FRT_TEST
#define FRT_GLES_VERSION 2
#else
#include "core/version.h"
#define FRT_GLES_VERSION VERSION_MAJOR
#endif // FRT_TEST
#endif // FRT_H

View File

@ -0,0 +1,156 @@
// frt_options.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace frt {
const char *perfmon_filename = 0;
const char *extract_resource_name = 0;
struct Param params[] = {
Param("color_size", 8),
Param("alpha_size", 8),
Param("depth_size", 16),
Param("multisample", false),
Param("disable_meta_keys", false),
Param("blacklist_video_bcm", false),
Param("exit_on_shiftenter", false),
};
#define N_OF_PARAMS (sizeof(params) / sizeof(Param))
void show_param_list() {
printf("params:\n");
for (unsigned i = 0; i < N_OF_PARAMS; i++)
printf(" %s\n", params[i].name);
printf("\n");
}
void usage(const char *program_name, int code = 1) {
printf("\n"
"usage: %s [godot args] [--frt [options] [param=value...]]\n"
"\n"
"options:\n"
" -v show version and exit\n"
" -h show this page and exit\n"
" -p perfmon.csv save performance monitor data\n"
" -e resource extract resource\n"
"\n",
program_name);
show_param_list();
exit(code);
}
void parse_frt_param(const char *name, const char *value) {
Param *p = App::instance()->get_param(name);
if (!p) {
printf("frt: unknown param '%s'\n\n", name);
show_param_list();
exit(1);
}
Value &v = p->value;
switch (v.t) {
case Value::Bool:
if (!strcmp(value, "true")) {
v.u.b = true;
} else if (!strcmp(value, "false")) {
v.u.b = false;
} else {
printf("frt: invalid boolean for '%s' (true, false)\n", name);
exit(1);
}
break;
case Value::Int:
v.u.i = atoi(value);
break;
case Value::Float:
v.u.f = (float)atof(value);
break;
case Value::String:
v.u.s = value;
break;
}
p->source = Param::CommandLine;
}
void parse_frt_args(int argc, char **argv) {
const char *program_name = argv[0];
for (int i = 1; i < argc; i++) {
const char *s = argv[i];
if (!strcmp(s, "-v")) {
printf("frt " FRT_VERSION "\n");
exit(0);
} else if (!strcmp(s, "-h")) {
usage(program_name, 0);
} else if (!strcmp(s, "-p")) {
if (++i == argc)
usage(program_name);
perfmon_filename = argv[i];
} else if (!strcmp(s, "-e")) {
if (++i == argc)
usage(program_name);
extract_resource_name = argv[i];
} else {
char *sep = strchr(argv[i], '=');
if (!sep)
usage(program_name);
*sep = '\0';
parse_frt_param(argv[i], sep + 1);
}
}
}
int App::get_n_of_params() const {
return N_OF_PARAMS;
}
Param *App::get_param(int i) const {
return &params[i];
}
Param *App::get_param(const char *name) const {
for (unsigned i = 0; i < N_OF_PARAMS; i++)
if (!strcmp(name, params[i].name))
return &params[i];
return 0;
}
void App::parse_args(int *argc, char ***argv) {
for (int i = 1; i < *argc; i++)
if (!strcmp((*argv)[i], "--frt")) {
(*argv)[i] = (*argv)[0];
int frt_argc = *argc - i;
char **frt_argv = &(*argv)[i];
parse_frt_args(frt_argc, frt_argv);
*argc = i;
break;
}
}
} // namespace frt

32
platform/frt/gles2_egl.h Normal file
View File

@ -0,0 +1,32 @@
// gles2_egl.h
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "dl/gles2.gen.h"
// Hack to make the GLES2 driver happy and prevent it from including EGL.
// No dl/egl.gen.h because indirectly including X11 causes name clashes.
#define __egl_h_
#define __eglext_h_
#define eglGetProcAddress(x) (0)

116
platform/frt/godot_frt.cpp Normal file
View File

@ -0,0 +1,116 @@
// godot_frt.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "main/main.h"
#include "frt.h"
#include "bits/frt_app_impl.h"
using namespace frt;
static Env env;
static Runnable *runnable;
static void probe_modules_fallback() {
App *app = App::instance();
Module *module;
const char *video_modules[] = {
"video_x11",
"video_fbdev",
"video_bcm",
"video_kmsdrm",
0
};
if (!env.video) {
module = app->probe(video_modules);
env.video = (Video *)module;
}
const char *keyboard_modules[] = {
"keyboard_x11",
"keyboard_linux_input",
0
};
if (!env.keyboard) {
module = app->probe(keyboard_modules);
env.keyboard = (Keyboard *)module;
}
const char *mouse_modules[] = {
"mouse_x11",
"mouse_linux_input",
0
};
if (!env.mouse) {
module = app->probe(mouse_modules);
env.mouse = (Mouse *)module;
}
}
static void probe_modules() {
App *app = App::instance();
EnvProbe *env_probe = (EnvProbe *)app->probe("envprobe");
if (env_probe)
env_probe->probe_env(&env);
else
probe_modules_fallback();
runnable = (Runnable *)app->probe("frt_os_unix");
}
static void cleanup_modules() {
if (env.mouse)
env.mouse->cleanup();
if (env.keyboard)
env.keyboard->cleanup();
if (env.video)
env.video->cleanup();
if (runnable)
runnable->cleanup();
}
int main(int argc, char *argv[]) {
int ret_code = 255;
bool started = false;
App::instance()->parse_args(&argc, &argv);
probe_modules();
if (!runnable)
goto quit_with_ret_code;
runnable->setup_env(&env);
if (Main::setup(argv[0], argc - 1, &argv[1]) != OK)
goto quit_with_ret_code;
if (!Main::start())
goto quit;
started = true;
runnable->run_();
quit:
if (started)
Main::cleanup();
ret_code = runnable->get_exit_code_();
quit_with_ret_code:
cleanup_modules();
return ret_code;
}

View File

@ -0,0 +1,11 @@
// imported from /usr/include/X11/bitmaps/left_ptr
// and /usr/include/X11/bitmaps/left_ptrmsk
#define left_ptr_width 16
#define left_ptr_height 16
#define left_ptr_x_hot 3
#define left_ptr_y_hot 1
static uint8_t left_ptr_bits[] = { 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00 };
#define left_ptrmsk_width 16
#define left_ptrmsk_height 16
static uint8_t left_ptrmsk_bits[] = { 0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01, 0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x01, 0xdc, 0x03, 0xcc, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x03 };

View File

@ -0,0 +1,122 @@
// imported from godot (core/os/keyboard.h), adding prefixes to avoid
// clashes with the linux input api
#ifndef IMPORT_GDKEYS_H
#define IMPORT_GDKEYS_H
enum { GD_SPKEY = (1 << 24) };
enum GdKeyList {
/* CURSOR/FUNCTION/BROWSER/MULTIMEDIA/MISC KEYS */
GD_KEY_ESCAPE = GD_SPKEY | 0x01,
GD_KEY_TAB = GD_SPKEY | 0x02,
GD_KEY_BACKTAB = GD_SPKEY | 0x03,
GD_KEY_BACKSPACE = GD_SPKEY | 0x04,
GD_KEY_RETURN = GD_SPKEY | 0x05,
GD_KEY_ENTER = GD_SPKEY | 0x06,
GD_KEY_INSERT = GD_SPKEY | 0x07,
GD_KEY_DELETE = GD_SPKEY | 0x08,
GD_KEY_PAUSE = GD_SPKEY | 0x09,
GD_KEY_PRINT = GD_SPKEY | 0x0A,
GD_KEY_SYSREQ = GD_SPKEY | 0x0B,
GD_KEY_CLEAR = GD_SPKEY | 0x0C,
GD_KEY_HOME = GD_SPKEY | 0x0D,
GD_KEY_END = GD_SPKEY | 0x0E,
GD_KEY_LEFT = GD_SPKEY | 0x0F,
GD_KEY_UP = GD_SPKEY | 0x10,
GD_KEY_RIGHT = GD_SPKEY | 0x11,
GD_KEY_DOWN = GD_SPKEY | 0x12,
GD_KEY_PAGEUP = GD_SPKEY | 0x13,
GD_KEY_PAGEDOWN = GD_SPKEY | 0x14,
GD_KEY_SHIFT = GD_SPKEY | 0x15,
GD_KEY_CONTROL = GD_SPKEY | 0x16,
GD_KEY_META = GD_SPKEY | 0x17,
GD_KEY_ALT = GD_SPKEY | 0x18,
GD_KEY_CAPSLOCK = GD_SPKEY | 0x19,
GD_KEY_NUMLOCK = GD_SPKEY | 0x1A,
GD_KEY_SCROLLLOCK = GD_SPKEY | 0x1B,
GD_KEY_F1 = GD_SPKEY | 0x1C,
GD_KEY_F2 = GD_SPKEY | 0x1D,
GD_KEY_F3 = GD_SPKEY | 0x1E,
GD_KEY_F4 = GD_SPKEY | 0x1F,
GD_KEY_F5 = GD_SPKEY | 0x20,
GD_KEY_F6 = GD_SPKEY | 0x21,
GD_KEY_F7 = GD_SPKEY | 0x22,
GD_KEY_F8 = GD_SPKEY | 0x23,
GD_KEY_F9 = GD_SPKEY | 0x24,
GD_KEY_F10 = GD_SPKEY | 0x25,
GD_KEY_F11 = GD_SPKEY | 0x26,
GD_KEY_F12 = GD_SPKEY | 0x27,
GD_KEY_F13 = GD_SPKEY | 0x28,
GD_KEY_F14 = GD_SPKEY | 0x29,
GD_KEY_F15 = GD_SPKEY | 0x2A,
GD_KEY_F16 = GD_SPKEY | 0x2B,
GD_KEY_KP_ENTER = GD_SPKEY | 0x80,
GD_KEY_KP_MULTIPLY = GD_SPKEY | 0x81,
GD_KEY_KP_DIVIDE = GD_SPKEY | 0x82,
GD_KEY_KP_SUBTRACT = GD_SPKEY | 0x83,
GD_KEY_KP_PERIOD = GD_SPKEY | 0x84,
GD_KEY_KP_ADD = GD_SPKEY | 0x85,
GD_KEY_KP_0 = GD_SPKEY | 0x86,
GD_KEY_KP_1 = GD_SPKEY | 0x87,
GD_KEY_KP_2 = GD_SPKEY | 0x88,
GD_KEY_KP_3 = GD_SPKEY | 0x89,
GD_KEY_KP_4 = GD_SPKEY | 0x8A,
GD_KEY_KP_5 = GD_SPKEY | 0x8B,
GD_KEY_KP_6 = GD_SPKEY | 0x8C,
GD_KEY_KP_7 = GD_SPKEY | 0x8D,
GD_KEY_KP_8 = GD_SPKEY | 0x8E,
GD_KEY_KP_9 = GD_SPKEY | 0x8F,
GD_KEY_SUPER_L = GD_SPKEY | 0x2C,
GD_KEY_SUPER_R = GD_SPKEY | 0x2D,
GD_KEY_MENU = GD_SPKEY | 0x2E,
GD_KEY_HYPER_L = GD_SPKEY | 0x2F,
GD_KEY_HYPER_R = GD_SPKEY | 0x30,
GD_KEY_HELP = GD_SPKEY | 0x31,
GD_KEY_DIRECTION_L = GD_SPKEY | 0x32,
GD_KEY_DIRECTION_R = GD_SPKEY | 0x33,
GD_KEY_BACK = GD_SPKEY | 0x40,
GD_KEY_FORWARD = GD_SPKEY | 0x41,
GD_KEY_STOP = GD_SPKEY | 0x42,
GD_KEY_REFRESH = GD_SPKEY | 0x43,
GD_KEY_VOLUMEDOWN = GD_SPKEY | 0x44,
GD_KEY_VOLUMEMUTE = GD_SPKEY | 0x45,
GD_KEY_VOLUMEUP = GD_SPKEY | 0x46,
GD_KEY_BASSBOOST = GD_SPKEY | 0x47,
GD_KEY_BASSUP = GD_SPKEY | 0x48,
GD_KEY_BASSDOWN = GD_SPKEY | 0x49,
GD_KEY_TREBLEUP = GD_SPKEY | 0x4A,
GD_KEY_TREBLEDOWN = GD_SPKEY | 0x4B,
GD_KEY_MEDIAPLAY = GD_SPKEY | 0x4C,
GD_KEY_MEDIASTOP = GD_SPKEY | 0x4D,
GD_KEY_MEDIAPREVIOUS = GD_SPKEY | 0x4E,
GD_KEY_MEDIANEXT = GD_SPKEY | 0x4F,
GD_KEY_MEDIARECORD = GD_SPKEY | 0x50,
GD_KEY_HOMEPAGE = GD_SPKEY | 0x51,
GD_KEY_FAVORITES = GD_SPKEY | 0x52,
GD_KEY_SEARCH = GD_SPKEY | 0x53,
GD_KEY_STANDBY = GD_SPKEY | 0x54,
GD_KEY_OPENURL = GD_SPKEY | 0x55,
GD_KEY_LAUNCHMAIL = GD_SPKEY | 0x56,
GD_KEY_LAUNCHMEDIA = GD_SPKEY | 0x57,
GD_KEY_LAUNCH0 = GD_SPKEY | 0x58,
GD_KEY_LAUNCH1 = GD_SPKEY | 0x59,
GD_KEY_LAUNCH2 = GD_SPKEY | 0x5A,
GD_KEY_LAUNCH3 = GD_SPKEY | 0x5B,
GD_KEY_LAUNCH4 = GD_SPKEY | 0x5C,
GD_KEY_LAUNCH5 = GD_SPKEY | 0x5D,
GD_KEY_LAUNCH6 = GD_SPKEY | 0x5E,
GD_KEY_LAUNCH7 = GD_SPKEY | 0x5F,
GD_KEY_LAUNCH8 = GD_SPKEY | 0x60,
GD_KEY_LAUNCH9 = GD_SPKEY | 0x61,
GD_KEY_LAUNCHA = GD_SPKEY | 0x62,
GD_KEY_LAUNCHB = GD_SPKEY | 0x63,
GD_KEY_LAUNCHC = GD_SPKEY | 0x64,
GD_KEY_LAUNCHD = GD_SPKEY | 0x65,
GD_KEY_LAUNCHE = GD_SPKEY | 0x66,
GD_KEY_LAUNCHF = GD_SPKEY | 0x67,
GD_KEY_UNKNOWN = GD_SPKEY | 0xFFFFFF,
};
#endif // IMPORT_GDKEYS_H

View File

@ -0,0 +1,55 @@
/*************************************************************************/
/* key_mapping_x11.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 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
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#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 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
// joypad_linux.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2021 Emanuele Fornara
*
* 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 "core/version.h"
#if VERSION_MAJOR == 2
#include "platform/x11/joystick_linux.cpp"
#else
#include "platform/x11/joypad_linux.cpp"
#endif

View File

@ -0,0 +1,26 @@
/* libudev-so_wrap.c */
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2021 Emanuele Fornara
*
* 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 "platform/x11/libudev-so_wrap.c"

View File

@ -0,0 +1,240 @@
// keyboard_linux_input.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 FRT_TEST
#define FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#else
#include "core/version.h"
#if VERSION_MAJOR == 3
#define FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#endif
#include "core/os/input_event.h"
#endif
#include "frt.h"
#include <stdio.h>
#include <string.h>
#include "bits/linux_input.h"
#include "import/gdkeys.h"
namespace frt {
static struct KeyMap {
int kernel_code;
int gd_code;
} keymap[] = {
{ KEY_SPACE, ' ' },
{ KEY_A, 'A' },
{ KEY_B, 'B' },
{ KEY_C, 'C' },
{ KEY_D, 'D' },
{ KEY_E, 'E' },
{ KEY_F, 'F' },
{ KEY_G, 'G' },
{ KEY_H, 'H' },
{ KEY_I, 'I' },
{ KEY_J, 'J' },
{ KEY_K, 'K' },
{ KEY_L, 'L' },
{ KEY_M, 'M' },
{ KEY_N, 'N' },
{ KEY_O, 'O' },
{ KEY_P, 'P' },
{ KEY_Q, 'Q' },
{ KEY_R, 'R' },
{ KEY_S, 'S' },
{ KEY_T, 'T' },
{ KEY_U, 'U' },
{ KEY_V, 'V' },
{ KEY_W, 'W' },
{ KEY_X, 'X' },
{ KEY_Y, 'Y' },
{ KEY_Z, 'Z' },
{ KEY_0, '0' },
{ KEY_1, '1' },
{ KEY_2, '2' },
{ KEY_3, '3' },
{ KEY_4, '4' },
{ KEY_5, '5' },
{ KEY_6, '6' },
{ KEY_7, '7' },
{ KEY_8, '8' },
{ KEY_9, '9' },
{ KEY_F1, GD_KEY_F1 },
{ KEY_F2, GD_KEY_F2 },
{ KEY_F3, GD_KEY_F3 },
{ KEY_F4, GD_KEY_F4 },
{ KEY_F5, GD_KEY_F5 },
{ KEY_F6, GD_KEY_F6 },
{ KEY_F7, GD_KEY_F7 },
{ KEY_F8, GD_KEY_F8 },
{ KEY_F9, GD_KEY_F9 },
{ KEY_F10, GD_KEY_F10 },
{ KEY_F11, GD_KEY_F11 },
{ KEY_F12, GD_KEY_F12 },
{ KEY_UP, GD_KEY_UP },
{ KEY_DOWN, GD_KEY_DOWN },
{ KEY_LEFT, GD_KEY_LEFT },
{ KEY_RIGHT, GD_KEY_RIGHT },
{ KEY_TAB, GD_KEY_TAB },
{ KEY_BACKSPACE, GD_KEY_BACKSPACE },
{ KEY_INSERT, GD_KEY_INSERT },
{ KEY_DELETE, GD_KEY_DELETE },
{ KEY_HOME, GD_KEY_HOME },
{ KEY_END, GD_KEY_END },
{ KEY_PAGEUP, GD_KEY_PAGEUP },
{ KEY_PAGEDOWN, GD_KEY_PAGEDOWN },
{ KEY_ENTER, GD_KEY_RETURN },
{ KEY_ESC, GD_KEY_ESCAPE },
{ KEY_LEFTCTRL, GD_KEY_CONTROL },
{ KEY_RIGHTCTRL, GD_KEY_CONTROL },
{ KEY_LEFTALT, GD_KEY_ALT },
{ KEY_RIGHTALT, GD_KEY_ALT },
{ KEY_LEFTSHIFT, GD_KEY_SHIFT },
{ KEY_RIGHTSHIFT, GD_KEY_SHIFT },
{ KEY_LEFTMETA, GD_KEY_META },
{ KEY_RIGHTMETA, GD_KEY_META },
{ KEY_KP0, GD_KEY_KP_0 },
{ KEY_KP1, GD_KEY_KP_1 },
{ KEY_KP2, GD_KEY_KP_2 },
{ KEY_KP3, GD_KEY_KP_3 },
{ KEY_KP4, GD_KEY_KP_4 },
{ KEY_KP5, GD_KEY_KP_5 },
{ KEY_KP6, GD_KEY_KP_6 },
{ KEY_KP7, GD_KEY_KP_7 },
{ KEY_KP8, GD_KEY_KP_8 },
{ KEY_KP9, GD_KEY_KP_9 },
{ KEY_KPASTERISK, GD_KEY_KP_MULTIPLY },
{ KEY_KPMINUS, GD_KEY_KP_SUBTRACT },
{ KEY_KPPLUS, GD_KEY_KP_ADD },
{ KEY_KPDOT, GD_KEY_KP_PERIOD },
{ KEY_KPENTER, GD_KEY_KP_ENTER },
{ KEY_KPSLASH, GD_KEY_KP_DIVIDE },
{ 0, 0 },
};
class KeyboardLinuxInput : public Keyboard, public EventDispatcher, public LinuxInput {
private:
static const int left_mask = 0x01;
static const int right_mask = 0x02;
static const int wait_ms = 100;
bool valid;
Handler *h;
bool grabbed;
InputModifierState st;
struct {
int shift;
int alt;
int control;
int meta;
} left_right_mask;
void update_modifier(int in_code, int left_code, int right_code, bool pressed, int &mask, bool &state) {
if (in_code != left_code && in_code != right_code)
return;
if (in_code == left_code) {
if (pressed)
mask |= left_mask;
else
mask &= ~left_mask;
} else if (in_code == right_code) {
if (pressed)
mask |= right_mask;
else
mask &= ~right_mask;
}
state = mask;
}
public:
KeyboardLinuxInput()
: valid(false), h(0), grabbed(false) {
st.shift = false;
st.alt = false;
st.control = false;
st.meta = false;
left_right_mask.shift = 0;
left_right_mask.alt = 0;
left_right_mask.control = 0;
left_right_mask.meta = 0;
}
// Module
const char *get_id() const { return "keyboard_linux_input"; }
bool probe() {
valid = open("FRT_KEYBOARD_ID", "event-kbd");
if (valid)
App::instance()->add_dispatcher(this);
return valid;
}
void cleanup() {
close();
if (valid)
App::instance()->remove_dispatcher(this);
valid = false;
}
bool handle_meta(int gd_code, bool pressed) {
if (pressed)
return false;
switch (gd_code) {
case 'K':
if (LinuxInput::grab(!grabbed, wait_ms))
grabbed = !grabbed;
return true;
default:
return false;
}
}
// LinuxInput
void handle(const input_event &ev) {
if (ev.type != EV_KEY || (ev.value != KV_Pressed && ev.value != KV_Released))
return;
bool pressed = (ev.value == KV_Pressed);
update_modifier(ev.code, KEY_LEFTSHIFT, KEY_RIGHTSHIFT, pressed, left_right_mask.shift, st.shift);
update_modifier(ev.code, KEY_LEFTALT, KEY_RIGHTALT, pressed, left_right_mask.alt, st.alt);
update_modifier(ev.code, KEY_LEFTCTRL, KEY_RIGHTCTRL, pressed, left_right_mask.control, st.control);
update_modifier(ev.code, KEY_LEFTMETA, KEY_RIGHTMETA, pressed, left_right_mask.meta, st.meta);
for (int i = 0; keymap[i].kernel_code; i++) {
if (keymap[i].kernel_code == ev.code) {
if (h)
h->handle_keyboard_key(keymap[i].gd_code, pressed, 0, false);
break;
}
}
}
// EventDispatcher
void dispatch_events() { poll(); }
// Keyboard
void set_handler(Handler *handler) {
h = handler;
grabbed = LinuxInput::grab(true, wait_ms);
}
void get_modifier_state(InputModifierState &state) const { state = st; }
};
FRT_REGISTER(KeyboardLinuxInput)
} // namespace frt

View File

@ -0,0 +1,144 @@
// keyboard_x11.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 FRT_TEST
#define FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#else
#include "core/version.h"
#if VERSION_MAJOR == 3
#define FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#endif
#include "core/os/input_event.h"
#endif
#include "frt.h"
#include "bits/x11.h"
#include "import/gdkeys.h"
#ifndef FRT_MOCK_KEY_MAPPING_X11
#include "import/key_mapping_x11.h"
#endif
namespace frt {
static const long handled_mask = KeyPressMask | KeyReleaseMask;
static const int handled_types[] = {
KeyPress,
KeyRelease,
0,
};
class KeyboardX11 : public Keyboard, public EventHandler {
private:
X11User *x11;
Display *display;
Handler *h;
InputModifierState st;
public:
KeyboardX11()
: x11(0), h(0) {
st.shift = false;
st.alt = false;
st.control = false;
st.meta = false;
}
// Module
const char *get_id() const { return "keyboard_x11"; }
bool probe() {
if (!x11) {
x11 = X11Context::acquire(handled_mask, handled_types, this);
display = x11->get_display();
}
return true;
}
void cleanup() {
if (x11) {
x11->release();
x11 = 0;
}
}
// Keyboard
void set_handler(Handler *handler) {
h = handler;
}
void get_modifier_state(InputModifierState &state) const { state = st; }
// EventHandler
void handle_event() {
// modelled after platform/x11/os_x11.cpp, see there for rationale
XEvent ev;
x11->get_event(ev);
st.shift = ev.xkey.state & ShiftMask;
st.alt = ev.xkey.state & Mod1Mask;
st.control = ev.xkey.state & ControlMask;
st.meta = ev.xkey.state & Mod4Mask;
KeySym keysym_keycode = 0;
char str[256 + 1];
XLookupString(&ev.xkey, str, 256, &keysym_keycode, 0);
uint32_t unicode = 0;
#ifndef FRT_MOCK_KEY_MAPPING_X11
int keycode = KeyMappingX11::get_keycode(keysym_keycode);
// just the simple case: on my system, using keysym_keycode is fine
unicode = KeyMappingX11::get_unicode_from_keysym(keysym_keycode);
#else
int keycode = str[0];
if (!keycode)
return;
#endif
if (keycode >= 'a' && keycode <= 'z')
keycode -= 'a' - 'A';
bool pressed = ev.type == KeyPress;
if (!pressed) { // echo?
do {
if (XPending(display) < 1)
break;
XEvent next_ev;
XPeekEvent(display, &next_ev);
if (next_ev.type != KeyPress)
break;
const int threshold = 5;
int dt = (int)next_ev.xkey.time - (int)ev.xkey.time;
if (dt < -threshold || dt > threshold)
break;
KeySym next_keysym;
XLookupString(&next_ev.xkey, str, 256, &next_keysym, 0);
if (next_keysym != keysym_keycode)
break;
XNextEvent(display, &next_ev);
if (h)
h->handle_keyboard_key(keycode, true, unicode, true);
return;
} while (false);
}
if (h)
h->handle_keyboard_key(keycode, pressed, unicode, false);
}
};
FRT_REGISTER(KeyboardX11)
} // namespace frt

BIN
platform/frt/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

View File

@ -0,0 +1,138 @@
// mouse_linux_input.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <stdio.h>
#include <string.h>
#include "bits/linux_input.h"
namespace frt {
inline void clamp(int &v, const int max) {
if (v < 0)
v = 0;
if (v >= max)
v = max - 1;
}
class MouseLinuxInput : public Mouse, public EventDispatcher, public LinuxInput {
private:
static const int wait_ms = 100;
bool valid;
Handler *h;
bool grabbed;
Vec2 size;
Vec2 pos;
public:
MouseLinuxInput()
: valid(false), h(0), grabbed(false) {}
// Module
const char *get_id() const { return "mouse_linux_input"; }
bool probe() {
valid = open("FRT_MOUSE_ID", "event-mouse");
if (valid)
App::instance()->add_dispatcher(this);
return valid;
}
void cleanup() {
close();
if (valid)
App::instance()->remove_dispatcher(this);
valid = false;
}
bool handle_meta(int gd_code, bool pressed) {
if (pressed)
return false;
switch (gd_code) {
case 'M':
if (LinuxInput::grab(!grabbed, wait_ms))
grabbed = !grabbed;
return true;
default:
return false;
}
}
// LinuxInput
void handle(const input_event &ev) {
if (ev.type == EV_REL) {
if (ev.code == ABS_X) {
pos.x += ev.value;
clamp(pos.x, size.x);
} else if (ev.code == ABS_Y) {
pos.y += ev.value;
clamp(pos.y, size.y);
} else if (ev.code == ABS_WHEEL) {
Button button = ev.value > 0 ? WheelUp : WheelDown;
if (h) {
h->handle_mouse_button(button, true);
h->handle_mouse_button(button, false); // TODO: needed?
}
return;
}
if (h)
h->handle_mouse_motion(pos);
} else {
if (ev.type != EV_KEY || (ev.value != KV_Pressed && ev.value != KV_Released))
return;
bool pressed = (ev.value == KV_Pressed);
Button button;
switch (ev.code) {
case BTN_LEFT:
button = Left;
break;
case BTN_RIGHT:
button = Right;
break;
case BTN_MIDDLE:
button = Middle;
break;
default:
return;
}
if (h)
h->handle_mouse_button(button, pressed);
}
}
// EventDispatcher
void dispatch_events() { poll(); }
// Mouse
Vec2 get_pos() const { return pos; }
void set_size(Vec2 size) {
this->size = size;
pos.x = size.x - 1;
pos.y = size.y - 1;
}
void set_handler(Handler *handler) {
h = handler;
grabbed = LinuxInput::grab(true, wait_ms);
}
};
FRT_REGISTER(MouseLinuxInput)
} // namespace frt

110
platform/frt/mouse_x11.cpp Normal file
View File

@ -0,0 +1,110 @@
// mouse_x11.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include "bits/x11.h"
namespace frt {
static const long handled_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask | ButtonMotionMask;
static const int handled_types[] = {
MotionNotify,
ButtonPress,
ButtonRelease,
0,
};
class MouseX11 : public Mouse, public EventHandler {
private:
X11User *x11;
Handler *h;
Vec2 pos;
public:
MouseX11()
: x11(0), h(0) {}
// Module
const char *get_id() const { return "mouse_x11"; }
bool probe() {
if (!x11)
x11 = X11Context::acquire(handled_mask, handled_types, this);
return true;
}
void cleanup() {
if (x11) {
x11->release();
x11 = 0;
}
}
// Mouse
Vec2 get_pos() const { return pos; }
void set_size(Vec2 size) {}
void set_handler(Handler *handler) { h = handler; }
// EventHandler
void handle_event() {
XEvent ev;
x11->get_event(ev);
Button button;
bool unhandled = false;
switch (ev.type) {
case MotionNotify:
pos.x = ev.xmotion.x;
pos.y = ev.xmotion.y;
if (h)
h->handle_mouse_motion(pos);
break;
case ButtonPress:
case ButtonRelease:
switch (ev.xbutton.button) {
case 1:
button = Left;
break;
case 2:
button = Middle;
break;
case 3:
button = Right;
break;
case 4:
button = WheelUp;
break;
case 5:
button = WheelDown;
break;
default:
unhandled = true;
break;
}
if (h && !unhandled)
h->handle_mouse_button(button, ev.type == ButtonPress);
break;
}
}
};
FRT_REGISTER(MouseX11)
} // namespace frt

828
platform/frt/os_frt.cpp Normal file
View File

@ -0,0 +1,828 @@
// os_frt.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include "core/version.h"
#include "core/os/os.h"
#include "core/os/input.h"
#include "core/os/file_access.h"
#include "drivers/unix/os_unix.h"
#include "servers/visual_server.h"
#include "servers/visual/rasterizer.h"
#include "servers/audio/audio_driver_dummy.h"
#include "servers/visual/visual_server_raster.h"
#include "drivers/alsa/audio_driver_alsa.h"
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
#include "main/main.h"
#include "main/input_default.h"
#include "main/performance.h"
#include "core/print_string.h"
#define VIDEO_DRIVER_GLES2 0
#define VIDEO_DRIVER_GLES3 1
#if VERSION_MAJOR == 2
#define VIDEO_DRIVER_COUNT 1
#include "platform/x11/joystick_linux.h"
#include "servers/visual/visual_server_wrap_mt.h"
#include "servers/audio/audio_server_sw.h"
#include "servers/audio/sample_manager_sw.h"
#include "servers/spatial_sound/spatial_sound_server_sw.h"
#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
#include "servers/physics_server.h"
#include "servers/physics/physics_server_sw.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
#include "drivers/gles2/rasterizer_gles2.h"
static int event_id = 0;
class InputModifierStateSetter {
private:
InputModifierState &mod;
public:
InputModifierStateSetter(InputModifierState &m)
: mod(m) {}
void set_shift(bool v) { mod.shift = v; }
void set_control(bool v) { mod.control = v; }
void set_alt(bool v) { mod.alt = v; }
void set_metakey(bool v) { mod.meta = v; }
};
class InputEventKeySetter : public InputModifierStateSetter {
private:
InputEvent &event;
public:
InputEventKeySetter(InputEvent &ev)
: InputModifierStateSetter(ev.key.mod), event(ev) {
event.type = InputEvent::KEY;
event.device = 0;
}
void set_pressed(bool v) { event.key.pressed = v; }
void set_scancode(uint32_t v) { event.key.scancode = v; }
void set_unicode(uint32_t v) { event.key.unicode = v; }
void set_echo(bool v) { event.key.echo = v; }
};
class InputEventMouseMotionSetter : public InputModifierStateSetter {
private:
InputEvent &event;
public:
InputEventMouseMotionSetter(InputEvent &ev)
: InputModifierStateSetter(ev.mouse_motion.mod), event(ev) {
event.type = InputEvent::MOUSE_MOTION;
event.device = 0;
}
void set_button_mask(int v) { event.mouse_motion.button_mask = v; }
void set_position(const Vector2 &v) {
event.mouse_motion.x = v.x;
event.mouse_motion.y = v.y;
}
void set_global_position(const Vector2 &v) {
event.mouse_motion.global_x = v.x;
event.mouse_motion.global_y = v.y;
}
void set_speed(const Vector2 &v) {
event.mouse_motion.speed_x = v.x;
event.mouse_motion.speed_y = v.y;
}
void set_relative(const Vector2 &v) {
event.mouse_motion.relative_x = v.x;
event.mouse_motion.relative_y = v.y;
}
};
class InputEventMouseButtonSetter : public InputModifierStateSetter {
private:
InputEvent &event;
public:
InputEventMouseButtonSetter(InputEvent &ev)
: InputModifierStateSetter(ev.mouse_button.mod), event(ev) {
event.type = InputEvent::MOUSE_BUTTON;
event.device = 0;
}
void set_button_mask(int v) { event.mouse_button.button_mask = v; }
void set_position(const Vector2 &v) {
event.mouse_button.x = v.x;
event.mouse_button.y = v.y;
}
void set_global_position(const Vector2 &v) {
event.mouse_button.global_x = v.x;
event.mouse_button.global_y = v.y;
}
void set_pressed(bool v) { event.mouse_button.pressed = v; }
void set_button_index(int v) { event.mouse_button.button_index = v; }
void set_doubleclick(bool v) { event.mouse_button.doubleclick = v; }
};
class InputModifierRef {
private:
InputModifierStateSetter setter;
public:
InputModifierRef(InputModifierStateSetter &s)
: setter(s) {}
InputModifierStateSetter *operator->() { return &setter; }
};
template <typename T>
class InputEventRef {
private:
InputEvent event;
T setter;
InputModifierRef mod;
public:
InputEventRef()
: setter(event), mod(setter) { event.ID = ++event_id; };
void instance() {}
operator InputEvent() { return event; }
operator InputModifierRef() { return mod; }
T *operator->() { return &setter; }
};
#define INPUT_MODIFIER_REF InputModifierRef
#define INPUT_EVENT_REF(t) InputEventRef<t##Setter>
#include "core/globals.h"
#define PROJECT_SETTINGS \
Globals *project_settings = Globals::get_singleton();
#elif VERSION_MAJOR == 3
#define VIDEO_DRIVER_COUNT 2
#include "platform/x11/joypad_linux.h"
#include "drivers/gles3/rasterizer_gles3.h"
#define FRT_DL_SKIP
#include "drivers/gles2/rasterizer_gles2.h"
typedef AudioDriverManager AudioDriverManagerSW;
typedef AudioDriver AudioDriverSW;
#define set_mouse_pos set_mouse_position
#define get_mouse_pos get_mouse_position
#define get_mouse_speed get_last_mouse_speed
#define has has_setting
#define FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#define INPUT_MODIFIER_REF Ref<InputEventWithModifiers>
#define INPUT_EVENT_REF(t) Ref<t>
#define joystick_linux JoypadLinux
#include "core/project_settings.h"
#define PROJECT_SETTINGS \
ProjectSettings *project_settings = ProjectSettings::get_singleton();
#else
#error "unhandled godot version"
#endif
#include "frt.h"
#include "bits/mouse_virtual.h"
using namespace frt;
namespace frt {
extern const char *perfmon_filename;
extern const char *extract_resource_name;
}
static class PerfMon {
private:
FILE *f;
char sep;
void init_separator() {
char s[32];
snprintf(s, sizeof(s), "%f", 2.5);
s[sizeof(s) - 1] = '\0';
sep = strchr(s, ',') ? ';' : ',';
}
public:
PerfMon()
: f(0) {}
~PerfMon() { cleanup(); }
bool is_valid() { return f; }
void init() {
if (!perfmon_filename)
return;
if (!(f = fopen(perfmon_filename, "w")))
return;
init_separator();
Performance *p = Performance::get_singleton();
fprintf(f, "time/ticks_ms");
for (int i = 0; i < Performance::MONITOR_MAX; i++)
fprintf(f, "%c%s", sep,
p->get_monitor_name(Performance::Monitor(i)).ascii().get_data());
fprintf(f, "\n");
}
void iteration(uint32_t t) {
if (!f)
return;
Performance *p = Performance::get_singleton();
fprintf(f, "%u", (unsigned int)t);
for (int i = 0; i < Performance::MONITOR_MAX; i++)
fprintf(f, "%c%f", sep,
p->get_monitor(Performance::Monitor(i)));
fprintf(f, "\n");
}
void cleanup() {
if (f)
fclose(f);
f = 0;
}
} perfmon;
class OS_FRT : public OS_Unix, public Runnable {
private:
App *app;
Param *disable_meta_keys_param;
Param *exit_on_shiftenter_param;
Env *env;
Vec2 screen_size;
ContextGL *context_gl;
VisualServer *visual_server;
VideoMode current_videomode;
int current_video_driver;
List<String> args;
MainLoop *main_loop;
#ifdef PULSEAUDIO_ENABLED
AudioDriverPulseAudio driver_pulseaudio;
#endif
#ifdef ALSA_ENABLED
AudioDriverALSA driver_alsa;
#endif
AudioDriverDummy driver_dummy;
int audio_driver_index;
Point2 mouse_pos;
Point2 last_mouse_pos;
bool last_mouse_pos_valid;
MouseMode mouse_mode;
int mouse_state;
bool grab;
#if VERSION_MAJOR == 2
PhysicsServer *physics_server;
Physics2DServer *physics_2d_server;
Rasterizer *rasterizer;
AudioServerSW *audio_server;
SampleManagerMallocSW *sample_manager;
SpatialSoundServerSW *spatial_sound_server;
SpatialSound2DServerSW *spatial_sound_2d_server;
#endif
int event_id;
InputDefault *input;
#ifdef JOYDEV_ENABLED
joystick_linux *joystick;
#endif
MouseVirtual mouse_virtual;
uint64_t last_click;
public:
int get_video_driver_count() const { return VIDEO_DRIVER_COUNT; }
int get_current_video_driver() const { return current_video_driver; }
const char *get_video_driver_name(int driver) const {
if (driver == VIDEO_DRIVER_GLES3)
return "GLES3";
else
return "GLES2";
}
OS::VideoMode get_default_video_mode() const {
return OS::VideoMode(screen_size.x, screen_size.y, true, false, true);
}
int get_audio_driver_count() const {
return AudioDriverManagerSW::get_driver_count();
}
const char *get_audio_driver_name(int driver) const {
AudioDriverSW *driver_ = AudioDriverManagerSW::get_driver(driver);
ERR_FAIL_COND_V(!driver_, "");
return driver_->get_name();
}
bool _check_internal_feature_support(const String &feature) {
if (current_video_driver == VIDEO_DRIVER_GLES3 && feature == "etc2")
return true;
return feature == "pc" || feature == "etc";
}
#if VERSION_MAJOR >= 3
String get_config_path() const {
if (has_environment("XDG_CONFIG_HOME"))
return get_environment("XDG_CONFIG_HOME");
if (has_environment("HOME"))
return get_environment("HOME").plus_file(".config");
return ".";
}
String get_data_path() const {
if (has_environment("XDG_DATA_HOME"))
return get_environment("XDG_DATA_HOME");
if (has_environment("HOME"))
return get_environment("HOME").plus_file(".local/share");
return get_config_path();
}
String get_cache_path() const {
if (has_environment("XDG_CACHE_HOME"))
return get_environment("XDG_CACHE_HOME");
if (has_environment("HOME"))
return get_environment("HOME").plus_file(".cache");
return get_config_path();
}
#endif
void extract_resource_fatal(const char *msg) {
fatal("failed extracting resource '%s': %s.",
extract_resource_name, msg);
}
void extract_resource_if_requested() {
const char *s = extract_resource_name;
if (!s)
return;
if (!isalnum(*s))
extract_resource_fatal("invalid name");
for (int i = 0; s[i]; i++)
if (!isalnum(*s) && !strchr(".-_", *s))
extract_resource_fatal("invalid name");
String name = "res://frt/";
name += s;
if (!FileAccess::exists(name))
extract_resource_fatal("not found");
FileAccess *in = FileAccess::open(name, FileAccess::READ);
if (!in)
extract_resource_fatal("failed opening resource");
int len = in->get_len();
uint8_t *buf = new uint8_t[len]; // memory "leak" is fine here
if (!buf)
extract_resource_fatal("failed allocating memory");
int n = in->get_buffer(buf, len);
if (n != len)
extract_resource_fatal("failed reading resource");
in->close();
FileAccess *out = FileAccess::open(s, FileAccess::WRITE);
if (!out)
extract_resource_fatal("failed opening output file");
out->store_buffer(buf, len);
out->close();
exit(0);
}
void get_project_frt_params() {
PROJECT_SETTINGS
String name;
const int n = app->get_n_of_params();
for (int i = 0; i < n; i++) {
Param *p = app->get_param(i);
if (p->source == Param::CommandLine)
continue;
name = "frt/";
name += p->name;
if (!project_settings->has(name))
continue;
p->source = Param::ProjectSettings;
Value &v = p->value;
switch (v.t) {
case Value::Bool:
v.u.b = bool(project_settings->get(name));
break;
case Value::Int:
v.u.i = int(project_settings->get(name));
break;
case Value::Float:
v.u.f = float(project_settings->get(name));
break;
case Value::String: {
String s = String(project_settings->get(name));
v.u.s = strdup(s.ascii());
// TODO: keep track and dealloc string copy
} break;
}
}
}
bool disable_meta_keys() {
return disable_meta_keys_param->value.u.b;
}
bool exit_on_shiftenter() {
return exit_on_shiftenter_param->value.u.b;
}
#if VERSION_MAJOR == 2
void
#else
Error
#endif
initialize(const VideoMode &desired, int video_driver, int audio_driver) {
get_project_frt_params();
extract_resource_if_requested();
args = OS::get_singleton()->get_cmdline_args();
current_videomode = desired;
main_loop = 0;
Vec2 view(current_videomode.width, current_videomode.height);
int gl_version = video_driver == VIDEO_DRIVER_GLES3 ? 3 : 2;
context_gl = env->video->create_the_gl_context(gl_version, view);
context_gl->initialize();
#if VERSION_MAJOR == 2
rasterizer = memnew(RasterizerGLES2);
visual_server = memnew(VisualServerRaster(rasterizer));
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE)
visual_server = memnew(VisualServerWrapMT(
visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
#else
if (video_driver == VIDEO_DRIVER_GLES3) {
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
current_video_driver = VIDEO_DRIVER_GLES3;
} else {
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
current_video_driver = VIDEO_DRIVER_GLES2;
}
visual_server = memnew(VisualServerRaster);
#endif
// TODO: Audio Module
AudioDriverManagerSW::get_driver(audio_driver)->set_singleton();
audio_driver_index = audio_driver;
if (AudioDriverManagerSW::get_driver(audio_driver)->init() != OK) {
audio_driver_index = -1;
for (int i = 0; i < AudioDriverManagerSW::get_driver_count(); i++) {
if (i == audio_driver)
continue;
AudioDriverManagerSW::get_driver(i)->set_singleton();
if (AudioDriverManagerSW::get_driver(i)->init() == OK) {
audio_driver_index = i;
break;
}
}
}
#if VERSION_MAJOR == 2
sample_manager = memnew(SampleManagerMallocSW);
audio_server = memnew(AudioServerSW(sample_manager));
audio_server->init();
spatial_sound_server = memnew(SpatialSoundServerSW);
spatial_sound_server->init();
spatial_sound_2d_server = memnew(SpatialSound2DServerSW);
spatial_sound_2d_server->init();
ERR_FAIL_COND(!visual_server);
#else
if (!visual_server)
return FAILED;
#endif
visual_server->init();
#if VERSION_MAJOR == 2
physics_server = memnew(PhysicsServerSW);
physics_server->init();
physics_2d_server = memnew(Physics2DServerSW);
physics_2d_server->init();
#endif
input = memnew(InputDefault);
#ifdef JOYDEV_ENABLED
joystick = memnew(joystick_linux(input));
#endif
last_click = 0;
#if VERSION_MAJOR == 2
_ensure_data_dir();
#else
#if VERSION_MINOR < 3
_ensure_user_data_dir();
#endif
return OK;
#endif
}
void finalize() {
if (main_loop)
memdelete(main_loop);
main_loop = NULL;
#if VERSION_MAJOR == 2
spatial_sound_server->finish();
memdelete(spatial_sound_server);
spatial_sound_2d_server->finish();
memdelete(spatial_sound_2d_server);
memdelete(sample_manager);
audio_server->finish();
memdelete(audio_server);
visual_server->finish();
#else // VERSION_MAJOR == 3
for (int i = 0; i < get_audio_driver_count(); i++)
AudioDriverManager::get_driver(i)->finish();
#endif
memdelete(visual_server);
#if VERSION_MAJOR == 2
memdelete(rasterizer);
physics_server->finish();
memdelete(physics_server);
physics_2d_server->finish();
memdelete(physics_2d_server);
#endif
#ifdef JOYDEV_ENABLED
memdelete(joystick);
#endif
memdelete(input);
args.clear();
}
void set_mouse_show(bool show) {}
void set_mouse_grab(bool grab) { this->grab = grab; }
bool is_mouse_grab_enabled() const { return grab; }
int get_mouse_button_state() const { return mouse_state; }
Point2 get_mouse_pos() const { return mouse_pos; }
void set_mouse_mode(MouseMode mode) { mouse_mode = mode; }
OS::MouseMode get_mouse_mode() const { return mouse_mode; }
void set_window_title(const String &title) {
env->video->set_title(title.utf8().get_data());
}
void set_video_mode(const VideoMode &video_mode, int screen) {}
OS::VideoMode get_video_mode(int screen) const {
return current_videomode;
}
Size2 get_window_size() const {
return Vector2(current_videomode.width, current_videomode.height);
}
void get_fullscreen_mode_list(List<VideoMode> *list, int screen) const {}
MainLoop *get_main_loop() const { return main_loop; }
void delete_main_loop() {
if (main_loop)
memdelete(main_loop);
main_loop = 0;
}
void set_main_loop(MainLoop *main_loop) {
this->main_loop = main_loop;
input->set_main_loop(main_loop);
}
bool can_draw() const { return true; };
String get_name()
#if (VERSION_MAJOR == 3) && (VERSION_MINOR >= 2)
const
#endif
{ return "FRT"; }
void move_window_to_foreground() {}
void set_cursor_shape(CursorShape shape) {}
void set_custom_mouse_cursor(const RES&, OS::CursorShape, const Vector2&) {}
void release_rendering_thread() { context_gl->release_current(); }
void make_rendering_thread() { context_gl->make_current(); }
void swap_buffers() { context_gl->swap_buffers(); }
uint32_t unicode_fallback(int gd_code, bool pressed,
const InputModifierState &st) {
if (st.alt || st.control || st.meta || !pressed)
return 0;
if (gd_code >= 'A' && gd_code <= 'Z')
return st.shift ? gd_code : gd_code + ('a' - 'A');
if (gd_code >= ' ' && gd_code <= '~')
return gd_code;
return 0;
}
void get_key_modifier_state(INPUT_MODIFIER_REF mod,
InputModifierState *st = 0) {
InputModifierState state;
if (env->keyboard) {
env->keyboard->get_modifier_state(state);
} else {
state.shift = false;
state.control = false;
state.alt = false;
state.meta = false;
}
mod->set_shift(state.shift);
mod->set_control(state.control);
mod->set_alt(state.alt);
mod->set_metakey(state.meta);
if (st)
*st = state;
}
void process_keyboard_event(int key, bool pressed, uint32_t unicode, bool echo) {
INPUT_EVENT_REF(InputEventKey) k;
k.instance();
InputModifierState st;
get_key_modifier_state(k, &st);
k->set_pressed(pressed);
k->set_scancode(key);
if (unicode)
k->set_unicode(unicode);
else
k->set_unicode(unicode_fallback(key, pressed, st));
k->set_echo(echo);
input->parse_input_event(k);
}
void process_mouse_motion(int x, int y) {
mouse_pos.x = x;
mouse_pos.y = y;
if (!last_mouse_pos_valid) {
last_mouse_pos = mouse_pos;
last_mouse_pos_valid = true;
}
Vector2 rel = mouse_pos - last_mouse_pos;
last_mouse_pos = mouse_pos;
INPUT_EVENT_REF(InputEventMouseMotion) mm;
mm.instance();
get_key_modifier_state(mm);
mm->set_button_mask(mouse_state);
mm->set_position(mouse_pos);
mm->set_global_position(mouse_pos);
mm->set_speed(input->get_mouse_speed());
mm->set_relative(rel);
input->set_mouse_pos(mouse_pos);
input->parse_input_event(mm);
}
void process_mouse_button(int index, bool pressed) {
int bit = (1 << (index - 1));
if (pressed)
mouse_state |= bit;
else
mouse_state &= ~bit;
INPUT_EVENT_REF(InputEventMouseButton) mb;
mb.instance();
get_key_modifier_state(mb);
mb->set_button_mask(mouse_state);
mb->set_position(mouse_pos);
mb->set_global_position(mouse_pos);
mb->set_button_index(index);
mb->set_pressed(pressed);
if (index == 1 && pressed) {
const uint64_t t = get_ticks_usec();
const uint64_t dt = t - last_click;
if (dt < 300000) {
last_click = 0;
mb->set_doubleclick(true);
} else {
last_click = t;
}
}
input->parse_input_event(mb);
}
struct KeyboardHandler : Keyboard::Handler {
OS_FRT *instance;
Keyboard *keyboard;
void handle_keyboard_key(int gd_code, bool pressed, uint32_t unicode, bool echo) {
if (!instance->disable_meta_keys()) {
InputModifierState st;
keyboard->get_modifier_state(st);
if (st.meta && instance->handle_meta(gd_code, pressed))
return;
}
if (instance->exit_on_shiftenter()) {
InputModifierState st;
keyboard->get_modifier_state(st);
if (st.shift && pressed && (gd_code == GD_KEY_RETURN || gd_code == GD_KEY_ENTER))
App::instance()->quit();
}
instance->process_keyboard_event(gd_code, pressed, unicode, echo);
}
} keyboard_handler;
struct MouseHandler : Mouse::Handler {
OS_FRT *instance;
Video *video;
void handle_mouse_button(Mouse::Button button, bool pressed) {
int index;
switch (button) {
case Mouse::Left:
index = 1;
break;
case Mouse::Middle:
index = 3;
break;
case Mouse::Right:
index = 2;
break;
case Mouse::WheelUp:
index = BUTTON_WHEEL_UP;
break;
case Mouse::WheelDown:
index = BUTTON_WHEEL_DOWN;
break;
default:
return;
}
instance->process_mouse_button(index, pressed);
}
void handle_mouse_motion(Vec2 pos) {
Vec2 view = video->move_pointer(pos);
instance->process_mouse_motion(view.x, view.y);
}
} mouse_handler;
bool dispatch_handle_meta(int gd_code, bool pressed) {
// keep it simple: hard-coded order should be fine
if (env->mouse && env->mouse->handle_meta(gd_code, pressed))
return true;
if (env->keyboard && env->keyboard->handle_meta(gd_code, pressed))
return true;
if (env->video && env->video->handle_meta(gd_code, pressed))
return true;
return false;
}
void run() {
if (!main_loop)
return;
disable_meta_keys_param = app->get_param("disable_meta_keys");
exit_on_shiftenter_param = app->get_param("exit_on_shiftenter");
keyboard_handler.instance = this;
keyboard_handler.keyboard = env->keyboard;
mouse_handler.instance = this;
mouse_handler.video = env->video;
if (env->keyboard && !env->mouse) {
mouse_virtual.probe();
env->mouse = &mouse_virtual;
}
if (env->mouse) {
env->mouse->set_size(screen_size);
Vec2 pos = env->mouse->get_pos();
env->video->move_pointer(pos);
}
// mouse set_handler first to increase the chances of RETURN release
if (env->mouse) {
env->mouse->set_handler(&mouse_handler);
}
if (env->keyboard) {
env->keyboard->set_handler(&keyboard_handler);
}
main_loop->init();
perfmon.init();
while (app->is_running()) {
app->dispatch_events();
#ifdef JOYDEV_ENABLED
#if VERSION_MAJOR == 2
event_id = joystick->process_joysticks(event_id);
#else
joystick->process_joypads();
#endif
#endif
if (Main::iteration() == true)
break;
if (perfmon.is_valid())
perfmon.iteration(get_ticks_msec());
};
perfmon.cleanup();
main_loop->finish();
}
bool is_joy_known(int p_device) {
return input->is_joy_mapped(p_device);
}
String get_joy_guid(int p_device) const {
return input->get_joy_guid_remapped(p_device);
}
OS_FRT() {
current_video_driver = VIDEO_DRIVER_GLES2;
#ifdef PULSEAUDIO_ENABLED
AudioDriverManagerSW::add_driver(&driver_pulseaudio);
#endif
#ifdef ALSA_ENABLED
AudioDriverManagerSW::add_driver(&driver_alsa);
#endif
if (AudioDriverManagerSW::get_driver_count() == 0)
AudioDriverManagerSW::add_driver(&driver_dummy);
mouse_mode = MOUSE_MODE_VISIBLE;
mouse_state = 0;
grab = false;
};
// Module
const char *get_id() const { return "frt_os_unix"; }
bool probe() { return true; }
void cleanup() {}
bool handle_meta(int gd_code, bool pressed) {
switch (gd_code) {
case 'Q':
if (env->video->provides_quit())
return false;
else
app->quit();
break;
default:
return dispatch_handle_meta(gd_code, pressed);
}
return true;
}
// Runnable
void setup_env(Env *env) {
app = App::instance();
this->env = env;
if (!env->video)
fatal("no video module available.");
screen_size = env->video->get_screen_size();
}
void run_() { run(); }
int get_exit_code_() { return get_exit_code(); }
};
FRT_REGISTER(OS_FRT)

View File

@ -0,0 +1,14 @@
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index b7204f9239..e3bedca676 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -158,7 +158,8 @@ void AudioDriverALSA::thread_func(void *p_udata) {
while (todo) {
if (ad->exit_thread)
break;
- uint8_t *src = (uint8_t *)ad->samples_out;
+ // FRT_PATCH_ALSA fix by charasyn (PR 43928)
+ uint16_t *src = (uint16_t *)ad->samples_out;
int wrote = snd_pcm_writei(ad->pcm_handle, (void *)(src + (total * ad->channels)), todo);
if (wrote < 0) {

View File

@ -0,0 +1,14 @@
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 1e17e7253..f4bf4fbdb 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -190,7 +190,8 @@ void AudioDriverALSA::thread_func(void *p_udata) {
while (todo) {
if (ad->exit_thread)
break;
- uint8_t *src = (uint8_t *)ad->samples_out.ptr();
+ // FRT_PATCH_ALSA fix by charasyn (PR 43928)
+ uint16_t *src = (uint16_t *)ad->samples_out.ptr();
int wrote = snd_pcm_writei(ad->pcm_handle, (void *)(src + (total * ad->channels)), todo);
if (wrote < 0) {

View File

@ -0,0 +1,14 @@
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 07b6cc441f..78f4590591 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -187,7 +187,8 @@ void AudioDriverALSA::thread_func(void *p_udata) {
int total = 0;
while (todo && !ad->exit_thread) {
- uint8_t *src = (uint8_t *)ad->samples_out.ptr();
+ // FRT_PATCH_ALSA fix by charasyn (PR 43928)
+ uint16_t *src = (uint16_t *)ad->samples_out.ptr();
int wrote = snd_pcm_writei(ad->pcm_handle, (void *)(src + (total * ad->channels)), todo);
if (wrote > 0) {

View File

@ -0,0 +1,13 @@
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index a61d227217..35c0e8f55e 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -51,7 +51,7 @@
#define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \
static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type), ""); \
static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type), ""); \
- static_assert(std::is_trivially_destructible<std::atomic<m_type> >::value, "");
+ // FRT_PATCH_GCC492A std::is_trivially_destructible not supported
#if defined(DEBUG_ENABLED)
void check_lockless_atomics();

View File

@ -0,0 +1,38 @@
/*************************************************************************/
/* platform_config.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef __linux__
#include <alloca.h>
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__)
#include <stdlib.h>
#define PTHREAD_BSD_SET_NAME
#endif
#define GLES2_INCLUDE_H "gles2_egl.h"
#define GLES3_INCLUDE_H "dl/gles3.gen.h"

View File

@ -0,0 +1,43 @@
# Setup:
# $ make local
# $ ln -sf All.mk Local.mk
# Test:
# $ make run
# Done:
# $ make restore
OBJS += \
test_all.o \
video_x11.o \
keyboard_x11.o \
mouse_x11.o \
video_fbdev.o \
keyboard_linux_input.o \
mouse_linux_input.o \
envprobe.o \
frt_options.o \
x11.gen.o \
egl.gen.o \
gles2.gen.o
ifdef HAS_GODOT
OBJS += key_mapping_x11_2.o
CXXFLAGS += -I../../..
else
CXXFLAGS += -DFRT_MOCK_KEY_MAPPING_X11
endif
ifdef HAS_BCM
OBJS += video_bcm.o bcm.gen.o
CXXFLAGS += -I/opt/vc/include
endif
ifdef HAS_KMSDRM
OBJS += video_kmsdrm.o
CXXFLAGS += -I/usr/include/libdrm
LIBS += -ldrm -lgbm
endif
LIBS += -ldl

View File

@ -0,0 +1,20 @@
# Setup:
# $ make local
# $ ln -sf BCM.mk Local.mk
# Test:
# $ make run
# Done:
# $ make restore
OBJS += \
test_video.o \
video_bcm.o \
frt_options.o \
bcm.gen.o \
egl.gen.o \
gles2.gen.o
CXXFLAGS += -I/opt/vc/include
LIBS += -ldl

View File

@ -0,0 +1,16 @@
# Setup:
# $ make local
# $ ln -sf FBDev.mk Local.mk
# Test:
# $ make run
# Done:
# $ make restore
OBJS += \
test_video.o \
video_fbdev.o \
frt_options.o
LIBS += -lEGL -lGLESv2

View File

@ -0,0 +1,18 @@
# Setup:
# $ make local
# $ ln -sf BCM.mk Local.mk
# Test:
# $ make run
# Done:
# $ make restore
OBJS += \
test_video.o \
video_kmsdrm.o \
frt_options.o \
egl.gen.o \
gles2.gen.o
LIBS += -ldl -ldrm -lgbm -lEGL -lGLESv2

View File

@ -0,0 +1,6 @@
all:
@echo
@echo This directory can be helpful in testing modules in isolation.
@echo See BCM.mk as an example.
@echo
@echo

View File

@ -0,0 +1,26 @@
# Makefile
VPATH = . .. ../import ../dl
CXXFLAGS = -I.. -DFRT_TEST -std=c++98 -Wall -ggdb
LDFLAGS = -ggdb
OBJS =
LIBS =
include Local.mk
test.bin: $(OBJS)
$(CXX) $(LDFLAGS) -o test.bin $(OBJS) $(LIBS)
run: test.bin
./test.bin
local:
git update-index --assume-unchanged Local.mk
restore:
git checkout Local.mk
git update-index --no-assume-unchanged Local.mk
clean:
rm -f a.out *.bin *.o

View File

@ -0,0 +1,25 @@
# Setup:
# $ make local
# $ ln -sf X11.mk Local.mk
# Test:
# $ make run
# Done:
# $ make restore
OBJS += \
test_all.o \
video_x11.o \
keyboard_x11.o \
mouse_x11.o \
frt_options.o
ifdef HAS_GODOT
OBJS += key_mapping_x11_2.o
CXXFLAGS += -I../../..
else
CXXFLAGS += -DFRT_MOCK_KEY_MAPPING_X11
endif
LIBS += -lEGL -lGLESv2 -lX11

View File

@ -0,0 +1,111 @@
// test_all.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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.
*/
#define FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#include "frt.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include "dl/gles2.gen.h"
#include "bits/frt_app_impl.h"
using namespace frt;
App *app;
Env env;
ContextGL *gl;
static struct Handler : public Keyboard::Handler, public Mouse::Handler {
void handle_keyboard_key(int gd_code, bool pressed, uint32_t unicode, bool echo) {
InputModifierState st;
env.keyboard->get_modifier_state(st);
printf("%c%c%c%c '%c' %010x %10d %08X %c %-10s\n",
st.shift ? 'S' : '-',
st.alt ? 'A' : '-',
st.control ? 'C' : '-',
st.meta ? 'M' : '-',
gd_code < 128 && isprint(gd_code) ? gd_code : '.', gd_code,
gd_code,
unicode,
echo ? '+' : '.',
pressed ? "pressed" : "released");
if (st.meta && gd_code == 'Q')
app->quit();
}
const char *button2string(Mouse::Button button) {
switch (button) {
case Mouse::Left:
return "left";
case Mouse::Middle:
return "middle";
case Mouse::Right:
return "right";
case Mouse::WheelUp:
return "wheel_up";
case Mouse::WheelDown:
return "wheel_down";
default:
assert(0);
}
}
void handle_mouse_button(Mouse::Button button, bool pressed) {
Vec2 pos = env.mouse->get_pos();
printf("%-10s %-10s (%d,%d)\n", button2string(button),
pressed ? "pressed" : "released", pos.x, pos.y);
}
void handle_mouse_motion(Vec2 pos) {
printf("%4d %4d motion\n", pos.x, pos.y);
}
} handler;
int main(int argc, char *argv[]) {
app = App::instance();
EnvProbe *env_probe = (EnvProbe *)app->probe("envprobe");
assert(env_probe);
env_probe->probe_env(&env);
assert(env.video);
assert(env.keyboard);
assert(env.mouse);
env.keyboard->set_handler(&handler);
env.mouse->set_handler(&handler);
Vec2 size(640, 480);
gl = env.video->create_the_gl_context(2, size);
assert(gl);
gl->initialize();
gl->make_current();
glClearColor(0.0, 0.0, 0.5, 1.0);
while (app->is_running()) {
glClear(GL_COLOR_BUFFER_BIT);
app->dispatch_events();
gl->swap_buffers();
}
env.mouse->cleanup();
env.keyboard->cleanup();
env.video->cleanup();
}

View File

@ -0,0 +1,71 @@
// test_keyboard.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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.
*/
#define FRT_MOCK_GODOT_INPUT_MODIFIER_STATE
#include "frt.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include "bits/frt_app_impl.h"
using namespace frt;
static struct KeyboardHandler : public Keyboard::Handler {
Keyboard *keyboard;
void handle_keyboard_key(int gd_code, bool pressed, uint32_t unicode, bool echo) {
InputModifierState st;
keyboard->get_modifier_state(st);
printf("%c%c%c%c '%c' %010x %10d %08X %c %-10s\n",
st.shift ? 'S' : '-',
st.alt ? 'A' : '-',
st.control ? 'C' : '-',
st.meta ? 'M' : '-',
gd_code < 128 && isprint(gd_code) ? gd_code : '.', gd_code,
gd_code,
unicode,
echo ? '+' : '.',
pressed ? "pressed" : "released");
if (st.meta && gd_code == 'Q')
exit(0);
}
} handler;
int main(int argc, char *argv[]) {
App *app = App::instance();
Keyboard *keyboard = (Keyboard *)App::instance()->probe_single();
assert(keyboard);
handler.keyboard = keyboard;
keyboard->set_handler(&handler);
while (app->is_running()) {
app->dispatch_events();
usleep(20000);
}
keyboard->cleanup();
}

View File

@ -0,0 +1,70 @@
// test_modules.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "frt.h"
struct Type1 : public frt::Module {
virtual void hello() = 0;
};
struct Type1Impl1 : public Type1 {
// Module
const char *get_id() const { return "type1_impl1"; }
bool probe() { return true; }
void cleanup() {}
// Type1
void hello() { printf("Hello, World!\n"); }
};
FRT_REGISTER(Type1Impl1)
#include "bits/frt_app_impl.h"
int main(int argc, char *argv[]) {
frt::App *app = frt::App::instance();
const char *type1_modules[] = {
"missing",
"type1_impl1",
"not_probed",
0
};
void **ctx;
ctx = app->get_context("type1");
assert(ctx);
*ctx = malloc(10);
ctx = app->get_context("type1");
free(*ctx);
*ctx = 0;
frt::Module *module = app->probe(type1_modules);
assert(module);
assert(!strcmp(module->get_id(), "type1_impl1"));
Type1 *type1 = (Type1 *)module;
type1->hello();
type1->cleanup();
}

View File

@ -0,0 +1,77 @@
// test_mouse.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include "bits/frt_app_impl.h"
using namespace frt;
static struct MouseHandler : public Mouse::Handler {
Mouse *mouse;
const char *button2string(Mouse::Button button) {
switch (button) {
case Mouse::Left:
return "left";
case Mouse::Middle:
return "middle";
case Mouse::Right:
return "right";
case Mouse::WheelUp:
return "wheel_up";
case Mouse::WheelDown:
return "wheel_down";
default:
assert(0);
}
}
void handle_mouse_button(Mouse::Button button, bool pressed) {
Vec2 pos = mouse->get_pos();
printf("%-10s %-10s (%d,%d)\n", button2string(button),
pressed ? "pressed" : "released", pos.x, pos.y);
}
void handle_mouse_motion(Vec2 pos) {
printf("%4d %4d motion\n", pos.x, pos.y);
}
} handler;
int main(int argc, char *argv[]) {
App *app = App::instance();
Mouse *mouse = (Mouse *)app->probe_single();
assert(mouse);
mouse->set_size(Vec2(640, 480));
mouse->set_handler(&handler);
handler.mouse = mouse;
while (app->is_running()) {
app->dispatch_events();
usleep(20000);
}
mouse->cleanup();
}

View File

@ -0,0 +1,122 @@
// test_video.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <math.h>
#include <assert.h>
#include "dl/gles2.gen.h"
#include "bits/frt_app_impl.h"
using namespace frt;
App *app;
Video *video;
ContextGL *gl;
int y;
bool repeat = false;
#ifdef __unix__
#include <ctype.h>
#include <unistd.h>
#include <sys/select.h>
static void dispatch_meta() {
struct timeval tv = { 0, 0 };
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
if (select(1, &fds, NULL, NULL, &tv) == 1) {
char buf[64];
int r = read(STDIN_FILENO, buf, sizeof(buf));
for (int i = 0; i < r; i++) {
int c = buf[i];
if (c == '1') {
repeat = true;
} else if (c == '0') {
repeat = false;
} else if (isalpha(c)) {
video->handle_meta(toupper(c), true);
video->handle_meta(toupper(c), false);
}
}
}
}
#else
static void dispatch_meta() {
}
static void usleep(int us) {
}
#endif
void iteration(bool vsync) {
const int position_period = 300;
const int visibility_period = 100;
gl->set_use_vsync(vsync);
for (int i = 0; i < position_period; i++, y++) {
video->move_pointer(Vec2(y, y));
if (vsync)
glClearColor(0., 0., sin((M_PI * i) / position_period), 1.);
else
glClearColor(sin((M_PI * i) / position_period), 0., 0., 1.);
glClear(GL_COLOR_BUFFER_BIT);
switch (i % visibility_period) {
case 0:
video->show_pointer(true);
break;
case visibility_period / 2:
video->show_pointer(false);
break;
default:
break;
}
app->dispatch_events();
gl->swap_buffers();
dispatch_meta();
if (!vsync)
usleep(2000); // too fast otherwise
}
}
int main(int argc, char *argv[]) {
app = App::instance();
video = (Video *)app->probe_single();
assert(video);
Vec2 size(640, 480);
gl = video->create_the_gl_context(2, size);
assert(gl);
gl->initialize();
gl->make_current();
do {
y = 0;
iteration(true);
iteration(false);
} while (repeat);
video->cleanup();
}

111
platform/frt/release.sh Executable file
View File

@ -0,0 +1,111 @@
#! /bin/sh
set -e
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2019 Emanuele Fornara
#
# 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.
#
die() {
echo $1
exit 1
}
usage() {
die "usage: release.sh arch tag..."
}
print_header() {
echo "Building frt:$fver tag:$tag arch:$arch..."
}
release() {
local bin
[ -d releases ] || return
bin=releases/frt_${fver}_${tag}_${arch}.bin
cp tag_$tag/bin/godot.frt.opt$extrasuffix.$arch $bin
$stripcmd $bin
}
build_common="platform=frt tools=no target=release -j 4"
build() {
local patch
print_header
if [ $arch = arm64v8 -a $fver = 216 ] ; then patch="CCFLAGS=-DNO_THREADS" ; fi
( cd tag_$tag ; nice scons frt_arch=$arch \
$archopts \
$gveropts \
$patch \
$build_common )
release
}
[ $# -gt 1 ] || usage
arch=$1
case $arch in
arm32v6)
stripcmd="arm-linux-gnueabihf-strip"
archopts="frt_cross=no"
;;
arm32v7)
stripcmd="arm-linux-gnueabihf-strip"
archopts="frt_cross=auto"
;;
arm64v8)
stripcmd="aarch64-linux-gnu-strip"
archopts="frt_cross=auto"
;;
*) die "release.sh: invalid arch: $arch."
esac
shift
[ -d releases ] || die "release.sh: no releases directory."
while [ $# -gt 0 ] ; do
case $1 in
tag_*)
[ -d $1 ] || die "release.sh: tag directory $1 not found."
tag=`echo $1 | cut -b 5- | sed 's/\///g'`
frth="tag_$tag/platform/frt/frt.h"
[ -f $frth ] || die "release.sh: $frth not found."
gver=`echo $tag | cut -b -2`
case $gver in
2*)
gveropts="use_llvm=yes"
extrasuffix=".llvm"
;;
3*)
gveropts="use_llvm=no module_webm_enabled=no"
extrasuffix=""
;;
*) die "release.sh: unsupported godot version: $gver."
esac
fver=`grep FRT_VERSION $frth \
| grep -o '".*"' \
| sed 's/[\."]//g'`
build
;;
*) die "release.sh: invalid tag $tag."
esac
shift
done

512
platform/frt/video_bcm.cpp Normal file
View File

@ -0,0 +1,512 @@
// video_bcm.cc
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <stdio.h>
#include <sys/time.h>
#include "dl/bcm.gen.h"
#include "dl/gles2.gen.h"
#include "bits/egl_base_context.h"
#define ELEMENT_CHANGE_DEST_RECT (1 << 2)
#define NULL_ALPHA NULL
#define NULL_CLAMP NULL
namespace frt {
class Display {
private:
static const int lcd = 0;
DISPMANX_DISPLAY_HANDLE_T handle;
Vec2 size;
bool initialized;
public:
Display()
: initialized(false) {}
DISPMANX_DISPLAY_HANDLE_T get_handle() const { return handle; }
Vec2 get_size() const { return size; }
bool init() {
if (initialized)
return size.x;
bcm_host_init();
initialized = true;
uint32_t width, height;
if (graphics_get_display_size(lcd, &width, &height) >= 0) {
size.x = (int)width;
size.y = (int)height;
}
return size.x;
}
bool open() {
handle = vc_dispmanx_display_open(lcd);
// TODO: 0 for error?
return true;
}
void cleanup() {
vc_dispmanx_display_close(handle);
}
};
class Element {
private:
bool has_resource;
bool added;
protected:
DISPMANX_RESOURCE_HANDLE_T resource;
DISPMANX_ELEMENT_HANDLE_T element;
VC_RECT_T src;
VC_RECT_T dst;
int layer;
void create_resource(VC_IMAGE_TYPE_T type, int width, int height, int pitch, uint8_t *data) {
uint32_t ptr;
resource = vc_dispmanx_resource_create(type, width, height, &ptr);
VC_RECT_T rect;
vc_dispmanx_rect_set(&rect, 0, 0, width, height);
vc_dispmanx_resource_write_data(resource, type, pitch, data, &rect);
has_resource = true;
}
public:
Element(int layer_)
: has_resource(false), added(false), layer(layer_) {}
DISPMANX_ELEMENT_HANDLE_T get_element() const { return element; }
void add(DISPMANX_UPDATE_HANDLE_T update, const Display &display) {
element = vc_dispmanx_element_add(
update, display.get_handle(), layer, &dst, resource, &src,
DISPMANX_PROTECTION_NONE, NULL_ALPHA, NULL_CLAMP,
DISPMANX_NO_ROTATE);
added = true;
}
void remove(DISPMANX_UPDATE_HANDLE_T update) {
if (!added)
return;
vc_dispmanx_element_remove(update, element);
added = false;
}
void delete_resource() {
if (!has_resource)
return;
vc_dispmanx_resource_delete(resource);
has_resource = false;
}
void show(DISPMANX_UPDATE_HANDLE_T update, const Display &display, bool enable) {
if (added_to_display() && !enable)
remove(update);
else if (!added_to_display() && enable)
add(update, display);
}
bool added_to_display() const { return added; }
};
class Background : public Element {
private:
static const VC_IMAGE_TYPE_T type = VC_IMAGE_RGB565;
static const int pixel_size = 2;
static const int width = 16;
static const int height = 16;
static const int pitch = width * pixel_size;
uint8_t data[width * height * pixel_size];
public:
Background()
: Element(100) {
memset(data, 0, sizeof(data));
}
void create_resource() {
vc_dispmanx_rect_set(&src, 0, 0, width << 16, height << 16);
Element::create_resource(type, width, height, pitch, data);
}
void set_metrics(const Display &display) {
Vec2 dpy_size = display.get_size();
vc_dispmanx_rect_set(&dst, 0, 0, dpy_size.x, dpy_size.y);
}
};
static void update_cb(DISPMANX_UPDATE_HANDLE_T u, void *arg) {
}
class View : public Element {
private:
enum Gravity {
Center,
TopLeft,
TopRight,
BottomRight,
BottomLeft,
};
friend class Pointer;
Vec2 size;
Vec2 dpy_size;
int ox, oy;
float scalex, scaley;
bool fullscreen;
Gravity gravity;
void set_dst_fullscreen() {
Vec2 win;
double req_aspect = (double)size.x / size.y;
double scr_aspect = (double)dpy_size.x / dpy_size.y;
if (req_aspect >= scr_aspect) {
win.x = dpy_size.x;
win.y = (int)(dpy_size.x / req_aspect);
} else {
win.x = (int)(dpy_size.y * req_aspect);
win.y = dpy_size.y;
}
ox = (dpy_size.x - win.x) / 2;
oy = (dpy_size.y - win.y) / 2;
scalex = (float)size.x / win.x;
scaley = (float)size.y / win.y;
vc_dispmanx_rect_set(&dst, ox, oy, win.x, win.y);
}
void set_dst_window() {
switch (gravity) {
case Center:
ox = (dpy_size.x - size.x) / 2;
break;
case TopLeft:
case BottomLeft:
ox = 0;
break;
case TopRight:
case BottomRight:
ox = dpy_size.x - size.x;
break;
}
switch (gravity) {
case Center:
oy = (dpy_size.y - size.y) / 2;
break;
case TopLeft:
case TopRight:
oy = 0;
break;
case BottomLeft:
case BottomRight:
oy = dpy_size.y - size.y;
break;
}
scalex = 1.0f;
scaley = 1.0f;
vc_dispmanx_rect_set(&dst, ox, oy, size.x, size.y);
}
void set_dst() {
if (fullscreen)
set_dst_fullscreen();
else
set_dst_window();
}
void schedule_update(DISPMANX_UPDATE_HANDLE_T update) {
vc_dispmanx_element_change_attributes(
update, element, ELEMENT_CHANGE_DEST_RECT, 0, 255, &dst,
&src, 0, DISPMANX_NO_ROTATE);
}
public:
View()
: Element(101), fullscreen(true), gravity(Center) {}
Vec2 get_size() const { return size; }
void set_metrics(const Display &display, const Vec2 &size) {
this->size = size;
vc_dispmanx_rect_set(&src, 0, 0, size.x << 16, size.y << 16);
dpy_size = display.get_size();
set_dst();
}
bool toggle_fullscreen(DISPMANX_UPDATE_HANDLE_T update) {
fullscreen = !fullscreen;
set_dst();
schedule_update(update);
return fullscreen;
}
bool toggle_window(DISPMANX_UPDATE_HANDLE_T update) {
if (fullscreen)
fullscreen = false;
else if (gravity == BottomLeft)
gravity = Center;
else
gravity = (Gravity)((int)gravity + 1);
set_dst();
schedule_update(update);
return fullscreen;
}
};
#include "import/cursor.h"
class Pointer : public Element {
private:
static const VC_IMAGE_TYPE_T type = VC_IMAGE_RGBA32;
static const int pixel_size = 4;
static const int width = 16;
static const int height = 16;
static const int pitch = width * pixel_size;
static const uint32_t shape_color = 0xff000000;
static const uint32_t mask_color = 0xffffffff;
static const uint32_t transparent_color = 0x00000000;
static const int layer_visible = 102;
static const int min_dt_us = 16667;
uint8_t data[width * height * pixel_size];
int x, y;
bool visible, need_updating;
struct timeval last_update;
inline uint8_t *fill_byte(uint8_t *p, int shape, int mask) {
uint32_t color;
int bitmask = 0x01;
for (int i = 0; i < 8; i++) {
if (shape & bitmask)
color = shape_color;
else if (mask & bitmask)
color = mask_color;
else
color = transparent_color;
memcpy(p, &color, 4);
p += 4;
bitmask <<= 1;
}
return p;
}
void convert_bitmaps(const uint8_t *shape, const uint8_t *mask) {
uint8_t *p = data;
for (int y = 0; y < 32; y++)
p = fill_byte(p, *shape++, *mask++);
}
void fill_dst() {
vc_dispmanx_rect_set(&dst, x - left_ptr_x_hot, y - left_ptr_y_hot,
width, height);
}
public:
Pointer()
: Element(layer_visible), visible(true) {
convert_bitmaps(left_ptr_bits, left_ptrmsk_bits);
}
void create_resource() {
vc_dispmanx_rect_set(&src, 0, 0, width << 16, height << 16);
Element::create_resource(type, width, height, pitch, data);
}
void set_metrics(const Display &display) {
Vec2 dpy_size = display.get_size();
x = dpy_size.x - 1;
y = dpy_size.y - 1;
fill_dst();
gettimeofday(&last_update, 0);
}
Vec2 set_pos(const View &view, const Vec2 &screen) {
Vec2 res;
res.x = (int)((screen.x - view.ox) * view.scalex);
res.y = (int)((screen.y - view.oy) * view.scaley);
x = screen.x;
y = screen.y;
fill_dst();
if (visible)
need_updating = true;
return res;
}
void set_visible(const Display &display, bool visible) {
if (this->visible == visible)
return;
this->visible = visible;
DISPMANX_UPDATE_HANDLE_T update;
update = vc_dispmanx_update_start(1);
show(update, display, visible);
vc_dispmanx_update_submit_sync(update);
}
void schedule_update_if_needed(bool vsync) {
if (!need_updating || !visible)
return;
if (!vsync) {
struct timeval now;
struct timeval dt;
gettimeofday(&now, 0);
timersub(&now, &last_update, &dt);
if (dt.tv_sec == 0 && dt.tv_usec < min_dt_us)
return;
last_update = now;
}
DISPMANX_UPDATE_HANDLE_T update;
update = vc_dispmanx_update_start(1);
vc_dispmanx_element_change_attributes(
update, element, ELEMENT_CHANGE_DEST_RECT, 0, 255, &dst,
&src, 0, DISPMANX_NO_ROTATE);
vc_dispmanx_update_submit(update, update_cb, 0);
need_updating = false;
}
};
class EGLDispmanxContext : public EGLBaseContext {
private:
EGL_DISPMANX_WINDOW_T nativewindow;
public:
void create_surface(const View &view) {
nativewindow.element = view.get_element();
Vec2 size = view.get_size();
nativewindow.width = size.x;
nativewindow.height = size.y;
surface = eglCreateWindowSurface(display, config,
(EGLNativeWindowType)&nativewindow, 0);
if (surface == EGL_NO_SURFACE)
fatal("video_bcm: eglCreateWindowSurface failed.");
}
};
class VideoBCM : public Video, public ContextGL {
private:
Display dpymnx;
EGLDispmanxContext egl;
Background background;
View view;
Pointer pointer;
bool initialized;
Vec2 screen_size;
Vec2 view_size;
bool vsync;
void init_egl_and_dpymnx(Vec2 size) {
egl.init(2);
dpymnx.open();
background.create_resource();
pointer.create_resource();
background.set_metrics(dpymnx);
view.set_metrics(dpymnx, size);
pointer.set_metrics(dpymnx);
DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
background.add(update, dpymnx);
view.add(update, dpymnx);
pointer.add(update, dpymnx);
vc_dispmanx_update_submit_sync(update);
egl.create_surface(view);
egl.make_current();
initialized = true;
}
void cleanup_egl_and_dpymnx() {
if (!initialized)
return;
egl.destroy_surface();
DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
background.remove(update);
view.remove(update);
pointer.remove(update);
vc_dispmanx_update_submit_sync(update);
background.delete_resource();
pointer.delete_resource();
dpymnx.cleanup();
egl.cleanup();
initialized = false;
}
public:
// Module
VideoBCM()
: initialized(false), vsync(true) {}
const char *get_id() const { return "video_bcm"; }
bool probe() {
if (!frt_load_bcm("libbcm_host.so"))
return false;
if (!frt_load_gles2("libbrcmGLESv2.so"))
return false;
if (!frt_load_egl("libbrcmEGL.so"))
return false;
if (!dpymnx.init())
return false;
screen_size = dpymnx.get_size();
return true;
}
void cleanup() {
cleanup_egl_and_dpymnx();
}
bool handle_meta(int gd_code, bool pressed) {
DISPMANX_UPDATE_HANDLE_T update;
bool fullscreen;
if (!pressed)
return false;
switch (gd_code) {
case 'F':
update = vc_dispmanx_update_start(1);
fullscreen = view.toggle_fullscreen(update);
background.show(update, dpymnx, fullscreen);
vc_dispmanx_update_submit(update, update_cb, 0);
return true;
case 'W':
update = vc_dispmanx_update_start(1);
fullscreen = view.toggle_window(update);
background.show(update, dpymnx, fullscreen);
vc_dispmanx_update_submit(update, update_cb, 0);
return true;
default:
return false;
}
}
// Video
Vec2 get_screen_size() const { return screen_size; }
Vec2 get_view_size() const { return view_size; }
void set_title(const char *title) {}
Vec2 move_pointer(const Vec2 &screen) {
return pointer.set_pos(view, screen);
}
void show_pointer(bool enable) {
pointer.set_visible(dpymnx, enable);
}
ContextGL *create_the_gl_context(int version, Vec2 size) {
if (App::instance()->get_bool_param("blacklist_video_bcm"))
fatal("video_bcm: this game requires the vc4 driver.");
if (version != 2)
return 0;
view_size = size;
return this;
}
bool provides_quit() { return false; }
// ContextGL
void release_current() {
egl.release_current();
}
void make_current() {
egl.make_current();
}
void swap_buffers() {
pointer.schedule_update_if_needed(vsync);
egl.swap_buffers();
}
int get_window_width() { return view_size.x; }
int get_window_height() { return view_size.y; }
bool initialize() {
init_egl_and_dpymnx(view_size);
return true;
}
void set_use_vsync(bool use) {
egl.swap_interval(use ? 1 : 0);
vsync = use;
}
bool is_using_vsync() const { return vsync; }
};
FRT_REGISTER(VideoBCM)
} // namespace frt

View File

@ -0,0 +1,167 @@
// video_fbdev.cc
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <stdio.h>
#include "bits/egl_base_context.h"
#define FRT_DL_SKIP
#include "dl/gles2.gen.h"
#if FRT_GLES_VERSION == 3
#include "dl/gles3.gen.h"
#endif
static bool frt_load_gles(int version) {
#if FRT_GLES_VERSION == 3
if (version == 3)
return frt_load_gles3("libGLESv2.so.2");
#endif
return frt_load_gles2("libGLESv2.so.2");
}
#define FRT_FBDEV_MALI 1
static int probe_fbdev() {
return FRT_FBDEV_MALI;
}
namespace frt {
class EGLFBDevContext : public EGLBaseContext {
public:
virtual void create_surface(const Vec2 &size) = 0;
virtual ~EGLFBDevContext() {}
};
class EGLMaliContext : public EGLFBDevContext {
private:
struct {
uint16_t width;
uint16_t height;
} nativewindow;
public:
void create_surface(const Vec2 &size) {
nativewindow.width = size.x;
nativewindow.height = size.y;
surface = eglCreateWindowSurface(display, config,
(EGLNativeWindowType)&nativewindow, 0);
if (surface == EGL_NO_SURFACE)
fatal("video_fbdev: eglCreateWindowSurface failed.");
}
};
class VideoFBDev : public Video, public ContextGL {
private:
bool initialized;
Vec2 screen_size;
Vec2 view_size;
EGLFBDevContext *egl;
int gl_version;
bool vsync;
void gles_init() {
egl->init(gl_version);
egl->create_surface(view_size);
egl->make_current();
initialized = true;
}
public:
// Module
VideoFBDev()
: initialized(false), egl(0), gl_version(2), vsync(true) {}
const char *get_id() const { return "video_fbdev"; }
bool probe() {
if (egl)
return true;
switch (probe_fbdev()) {
case FRT_FBDEV_MALI:
egl = new EGLMaliContext();
break;
default:
fatal("video_fbdev: internal error.");
}
if (!frt_load_egl("libEGL.so.1")) {
delete egl;
egl = 0;
return false;
}
screen_size.x = 720;
screen_size.y = 480;
return true;
}
void cleanup() {
if (initialized) {
egl->destroy_surface();
egl->cleanup();
initialized = false;
}
if (egl) {
delete egl;
egl = 0;
}
}
// Video
Vec2 get_screen_size() const { return screen_size; }
Vec2 get_view_size() const { return view_size; }
void set_title(const char *title) {}
Vec2 move_pointer(const Vec2 &screen) { return screen; }
void show_pointer(bool enable) {}
ContextGL *create_the_gl_context(int version, Vec2 size) {
if (!frt_load_gles(version))
return 0;
gl_version = version;
view_size = size;
return this;
}
bool provides_quit() { return false; }
// ContextGL
void release_current() {
egl->release_current();
}
void make_current() {
egl->make_current();
}
void swap_buffers() {
egl->swap_buffers();
}
int get_window_width() { return view_size.x; }
int get_window_height() { return view_size.y; }
bool initialize() {
gles_init();
return true;
}
void set_use_vsync(bool use) {
egl->swap_interval(use ? 1 : 0);
vsync = use;
}
bool is_using_vsync() const { return vsync; }
};
FRT_REGISTER(VideoFBDev)
} // namespace frt

View File

@ -0,0 +1,313 @@
// video_kmsdrm.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 "frt.h"
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "dl/drm.gen.h"
#include "dl/gbm.gen.h"
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include "bits/egl_base_context.h"
#include "bits/frt_load_gles.h"
namespace frt {
class EGLKMSDRMContext : public EGLBaseContext {
private:
int device;
drmModeRes *resources;
drmModeConnector *connector;
uint32_t connector_id;
drmModeEncoder *encoder;
drmModeModeInfo mode_info;
drmModeCrtc *crtc;
struct gbm_device *gbm_device;
struct gbm_surface *gbm_surface;
struct gbm_bo *previous_bo = NULL;
uint32_t previous_fb;
struct gbm_bo *bo;
uint32_t handle;
uint32_t pitch;
uint32_t fb;
uint64_t modifier;
EGLConfig configs[32];
int config_index;
drmModeConnector *find_connector(drmModeRes *resources) {
for (int i = 0; i < resources->count_connectors; i++) {
drmModeConnector *connector = drmModeGetConnector(device, resources->connectors[i]);
if (connector->connection == DRM_MODE_CONNECTED)
return connector;
drmModeFreeConnector(connector);
}
return NULL;
}
drmModeEncoder *find_encoder(drmModeRes *resources, drmModeConnector *connector) {
if (connector->encoder_id)
return drmModeGetEncoder(device, connector->encoder_id);
return NULL;
}
int match_config_to_visual(EGLDisplay egl_display, EGLint visual_id, EGLConfig *configs, int count) {
EGLint id;
for (int i = 0; i < count; ++i) {
if (!eglGetConfigAttrib(egl_display, configs[i], EGL_NATIVE_VISUAL_ID, &id)) continue;
if (id == visual_id)
return i;
}
return -1;
}
public:
void init(int version) {
EGLBoolean result;
EGLint num_config;
EGLint count = 0;
static const EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, version,
EGL_NONE
};
static EGLint attributes[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, EGL_DONT_CARE,
EGL_NONE
};
//! Try and get the correct card to use from the env
const char *s = getenv("FRT_KMSDRM_DEVICE");
if (s) {
if (access(s, R_OK) == 0)
device = open(s, O_RDWR);
else
fatal("couldn't open %s.", s);
}
//! No env var found, try card1 (rpi4)
else if (access("/dev/dri/card1", R_OK) == 0)
device = open("/dev/dri/card1", O_RDWR);
//! That didn't work, fall back to card0 (pc, pi3, others)
else if (access("/dev/dri/card0", R_OK) == 0)
device = open("/dev/dri/card0", O_RDWR);
else
fatal("no /dev/dri/card found.");
if (device < 0)
fatal("open returned an invalid device.");
else {
resources = drmModeGetResources(device);
if (resources == 0)
fatal("failed to get resources.");
connector = find_connector(resources);
if (connector == 0)
fatal("failed to get connector. no fb?");
}
connector_id = connector->connector_id;
mode_info = connector->modes[0];
encoder = find_encoder(resources, connector);
crtc = drmModeGetCrtc(device, encoder->crtc_id);
drmModeFreeEncoder(encoder);
drmModeFreeConnector(connector);
drmModeFreeResources(resources);
gbm_device = gbm_create_device(device);
gbm_surface = gbm_surface_create(gbm_device, mode_info.hdisplay, mode_info.vdisplay, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
display = eglGetDisplay(gbm_device);
result = eglInitialize(display, NULL, NULL);
if (result == EGL_FALSE)
fatal("eglInitialize failed.");
result = eglBindAPI(EGL_OPENGL_ES_API);
if (result == EGL_FALSE)
fatal("eglBindAPI failed.");
eglGetConfigs(display, NULL, 0, &count);
result = eglChooseConfig(display, attributes, &configs[0], count, &num_config);
if (result == EGL_FALSE)
fatal("eglChooseConfig failed.");
config_index = match_config_to_visual(display, GBM_FORMAT_XRGB8888, &configs[0], num_config);
context = eglCreateContext(display, configs[config_index], EGL_NO_CONTEXT, context_attribs);
if (context == EGL_NO_CONTEXT)
fatal("eglCreateContext failed.");
}
void create_surface() {
surface = eglCreateWindowSurface(display, configs[config_index], gbm_surface, NULL);
if (surface == EGL_NO_SURFACE)
fatal("eglCreateWindowSurface failed.");
}
void swap_buffers() {
eglSwapBuffers(display, surface);
bo = gbm_surface_lock_front_buffer(gbm_surface);
handle = gbm_bo_get_handle(bo).u32;
pitch = gbm_bo_get_stride(bo);
drmModeAddFB(device, mode_info.hdisplay, mode_info.vdisplay, 24, 32, pitch, handle, &fb);
drmModeSetCrtc(device, crtc->crtc_id, fb, 0, 0, &connector_id, 1, &mode_info);
if (previous_bo != 0) {
drmModeRmFB(device, previous_fb);
gbm_surface_release_buffer(gbm_surface, previous_bo);
}
previous_bo = bo;
previous_fb = fb;
}
int getDevice() { return device; }
drmModeCrtc *getCrtc() { return crtc; }
uint32_t *getConnector_id() { return &connector_id; }
struct gbm_bo *getPrevious_bo() {
return previous_bo;
}
uint32_t getPrevious_fb() { return previous_fb; }
struct gbm_surface *getGbm_surface() {
return gbm_surface;
}
struct gbm_device *getGbm_device() {
return gbm_device;
}
};
class VideoKMSDRM : public Video, public ContextGL {
private:
EGLKMSDRMContext egl;
bool initialized;
Vec2 screen_size;
bool vsync;
drmModeCrtc *crtc;
int gl_version;
void init_egl(Vec2 size) {
egl.init(gl_version);
egl.create_surface();
egl.make_current();
crtc = egl.getCrtc();
screen_size.x = get_window_width();
screen_size.y = get_window_height();
initialized = true;
}
void cleanup_egl() {
if (!initialized)
return;
if (!crtc)
return;
drmModeSetCrtc(egl.getDevice(), crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, egl.getConnector_id(), 1, &crtc->mode);
drmModeFreeCrtc(crtc);
if (egl.getPrevious_bo()) {
drmModeRmFB(egl.getDevice(), egl.getPrevious_fb());
gbm_surface_release_buffer(egl.getGbm_surface(), egl.getPrevious_bo());
}
egl.destroy_surface();
gbm_surface_destroy(egl.getGbm_surface());
egl.cleanup();
gbm_device_destroy(egl.getGbm_device());
close(egl.getDevice());
initialized = false;
}
public:
// Module
VideoKMSDRM()
: initialized(false), vsync(true) {}
const char *get_id() const { return "video_kmsdrm"; }
bool probe() {
if (!frt_load_gbm("libgbm.so.1"))
return false;
if (!frt_load_drm("libdrm.so.2"))
return false;
if (!frt_load_egl(lib("libEGL.so.1")))
return false;
return true;
}
void cleanup() {
cleanup_egl();
}
// Video
Vec2 get_screen_size() const { return screen_size; }
Vec2 get_view_size() const { return screen_size; }
ContextGL *create_the_gl_context(int version, Vec2 size) {
if (!frt_load_gles(version))
return 0;
gl_version = version;
screen_size = size;
return this;
}
bool provides_quit() { return false; }
void set_title(const char *title) {}
Vec2 move_pointer(const Vec2 &screen) {
return Vec2(0, 0);
}
void show_pointer(bool enable) {}
int get_window_height() {
int h = 0;
if (crtc)
h = (int)crtc->height;
return h;
}
int get_window_width() {
int w = 0;
if (crtc)
w = (int)crtc->width;
return w;
}
// ContextGL
void release_current() {
egl.release_current();
}
void make_current() {
egl.make_current();
}
void swap_buffers() {
egl.swap_buffers();
}
bool initialize() {
init_egl(screen_size);
return true;
}
void set_use_vsync(bool use) {
egl.swap_interval(use ? 1 : 0);
vsync = use;
}
bool is_using_vsync() const { return vsync; }
};
FRT_REGISTER(VideoKMSDRM)
} // namespace frt

151
platform/frt/video_x11.cpp Normal file
View File

@ -0,0 +1,151 @@
// video_x11.cpp
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* 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 <string.h>
#include <unistd.h>
#include "frt.h"
#include "bits/x11.h"
#include "bits/egl_base_context.h"
#include "bits/frt_load_gles.h"
namespace frt {
static const long handled_mask = 0;
static const int handled_types[] = {
ClientMessage,
0,
};
class VideoX11 : public Video, public ContextGL, public EventHandler {
private:
X11User *x11;
Display *display;
Window window;
Atom wm_delete_window;
Vec2 screen_size;
Vec2 view_size;
EGLBaseContext egl;
int gl_version;
bool vsync;
void gles_init() {
window = x11->create_window(view_size.x, view_size.y, FRT_WINDOW_TITLE);
wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wm_delete_window, 1);
egl.init(gl_version, (EGLNativeDisplayType)display);
egl.create_simple_surface((EGLNativeWindowType)window);
egl.make_current();
}
public:
VideoX11()
: x11(0), display(0), window(0), gl_version(2), vsync(true) {
screen_size.x = 1200;
screen_size.y = 680;
}
// Module
const char *get_id() const { return "video_x11"; }
bool probe() {
if (x11)
return true;
x11 = X11Context::acquire(handled_mask, handled_types, this, true);
display = x11->get_display();
if (!frt_load_egl(lib("libEGL.so.1"))) {
x11->release();
x11 = 0;
return false;
}
return true;
}
void cleanup() {
if (window) {
egl.destroy_surface();
egl.cleanup();
}
if (x11)
x11->release();
window = 0;
x11 = 0;
}
// Video
Vec2 get_screen_size() const { return screen_size; }
Vec2 get_view_size() const { return view_size; }
void set_title(const char *title) { XStoreName(display, window, title); }
Vec2 move_pointer(const Vec2 &screen) {
/*
XWarpPointer(display, None, window, 0, 0, 0, 0, screen.x, screen.y);
XFlush(x_display);
*/
return screen;
}
void show_pointer(bool enable) {}
ContextGL *create_the_gl_context(int version, Vec2 size) {
if (!frt_load_gles(version))
return 0;
gl_version = version;
view_size = size;
return this;
}
bool provides_quit() { return true; }
// ContextGL
void release_current() {
egl.release_current();
}
void make_current() {
egl.make_current();
}
void swap_buffers() {
egl.swap_buffers();
}
int get_window_width() { return view_size.x; }
int get_window_height() { return view_size.y; }
bool initialize() {
gles_init();
return true;
}
void set_use_vsync(bool use) {
egl.swap_interval(use ? 1 : 0);
vsync = use;
}
bool is_using_vsync() const { return vsync; }
// EventHandler
void handle_event() {
XEvent ev;
x11->get_event(ev);
switch (ev.type) {
case ClientMessage:
if ((unsigned int)ev.xclient.data.l[0] == (unsigned int)wm_delete_window)
App::instance()->quit();
break;
}
}
};
FRT_REGISTER(VideoX11)
} // namespace frt