mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-04-12 23:02:02 +02:00
Also added frt1 (https://github.com/efornara/frt/tree/1.x).
This commit is contained in:
parent
996d47081b
commit
09742a48b6
100
platform/frt/.clang-format
Normal file
100
platform/frt/.clang-format
Normal 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
8
platform/frt/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.o
|
||||
*.swp
|
||||
*.pyc
|
||||
*.bin
|
||||
a.out
|
||||
logo.h
|
||||
*.gen.*
|
||||
private/
|
20
platform/frt/.travis.yml
Normal file
20
platform/frt/.travis.yml
Normal 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
21
platform/frt/CREDITS.txt
Normal 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
21
platform/frt/LICENSE.txt
Normal 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.
|
28
platform/frt/LICENSE_GODOT.txt
Normal file
28
platform/frt/LICENSE_GODOT.txt
Normal 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
11
platform/frt/Local.mk
Normal 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
16
platform/frt/Makefile
Normal 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
72
platform/frt/README.md
Normal 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
28
platform/frt/SCsub
Normal 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'])
|
116
platform/frt/bits/egl_base_context.h
Normal file
116
platform/frt/bits/egl_base_context.h
Normal 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
|
114
platform/frt/bits/frt_app_impl.h
Normal file
114
platform/frt/bits/frt_app_impl.h
Normal 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
|
58
platform/frt/bits/frt_load_gles.h
Normal file
58
platform/frt/bits/frt_load_gles.h
Normal 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"));
|
||||
}
|
169
platform/frt/bits/linux_input.h
Normal file
169
platform/frt/bits/linux_input.h
Normal 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
|
110
platform/frt/bits/mouse_virtual.h
Normal file
110
platform/frt/bits/mouse_virtual.h
Normal 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
191
platform/frt/bits/x11.h
Normal 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
207
platform/frt/detect.py
Normal 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
41
platform/frt/dl/bcm.dl
Normal 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
39
platform/frt/dl/drm.dl
Normal 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
42
platform/frt/dl/egl.dl
Normal 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
36
platform/frt/dl/gbm.dl
Normal 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
171
platform/frt/dl/gles2.dl
Normal 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
273
platform/frt/dl/gles3.dl
Normal 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
11
platform/frt/dl/minidl.sh
Executable 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
141
platform/frt/dl/procdl.py
Executable 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
45
platform/frt/dl/x11.dl
Normal 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
38
platform/frt/doc/Bugs.md
Normal 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
158
platform/frt/doc/Compile.md
Normal 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.
|
68
platform/frt/doc/Environment.md
Normal file
68
platform/frt/doc/Environment.md
Normal 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,,
|
||||
|
101
platform/frt/doc/Extensions.md
Normal file
101
platform/frt/doc/Extensions.md
Normal 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.
|
82
platform/frt/doc/Porting.md
Normal file
82
platform/frt/doc/Porting.md
Normal 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.
|
40
platform/frt/doc/ReleaseNotes.md
Normal file
40
platform/frt/doc/ReleaseNotes.md
Normal 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
117
platform/frt/doc/Usage.md
Normal 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.
|
42
platform/frt/doc/Utgard.md
Normal file
42
platform/frt/doc/Utgard.md
Normal 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
31
platform/frt/doc/VC4.md
Normal 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
10
platform/frt/doc/VC6.md
Normal 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
202
platform/frt/envprobe.cpp
Normal 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
245
platform/frt/frt.h
Normal 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
|
156
platform/frt/frt_options.cpp
Normal file
156
platform/frt/frt_options.cpp
Normal 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 ¶ms[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 ¶ms[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
32
platform/frt/gles2_egl.h
Normal 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
116
platform/frt/godot_frt.cpp
Normal 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;
|
||||
}
|
11
platform/frt/import/cursor.h
Normal file
11
platform/frt/import/cursor.h
Normal 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 };
|
122
platform/frt/import/gdkeys.h
Normal file
122
platform/frt/import/gdkeys.h
Normal 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
|
55
platform/frt/import/key_mapping_x11.h
Normal file
55
platform/frt/import/key_mapping_x11.h
Normal 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
|
1810
platform/frt/import/key_mapping_x11_2.cpp
Normal file
1810
platform/frt/import/key_mapping_x11_2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1810
platform/frt/import/key_mapping_x11_3.cpp
Normal file
1810
platform/frt/import/key_mapping_x11_3.cpp
Normal file
File diff suppressed because it is too large
Load Diff
32
platform/frt/include/joypad_linux.cpp
Normal file
32
platform/frt/include/joypad_linux.cpp
Normal 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
|
26
platform/frt/include/libudev-so_wrap.c
Normal file
26
platform/frt/include/libudev-so_wrap.c
Normal 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"
|
240
platform/frt/keyboard_linux_input.cpp
Normal file
240
platform/frt/keyboard_linux_input.cpp
Normal 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
|
144
platform/frt/keyboard_x11.cpp
Normal file
144
platform/frt/keyboard_x11.cpp
Normal 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
BIN
platform/frt/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 439 B |
138
platform/frt/mouse_linux_input.cpp
Normal file
138
platform/frt/mouse_linux_input.cpp
Normal 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
110
platform/frt/mouse_x11.cpp
Normal 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
828
platform/frt/os_frt.cpp
Normal 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)
|
14
platform/frt/patches/alsa_21.patch
Normal file
14
platform/frt/patches/alsa_21.patch
Normal 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) {
|
14
platform/frt/patches/alsa_30.patch
Normal file
14
platform/frt/patches/alsa_30.patch
Normal 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) {
|
14
platform/frt/patches/alsa_31.patch
Normal file
14
platform/frt/patches/alsa_31.patch
Normal 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) {
|
13
platform/frt/patches/gcc492a_324.patch
Normal file
13
platform/frt/patches/gcc492a_324.patch
Normal 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();
|
38
platform/frt/platform_config.h
Normal file
38
platform/frt/platform_config.h
Normal 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"
|
43
platform/frt/porting/All.mk
Normal file
43
platform/frt/porting/All.mk
Normal 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
|
20
platform/frt/porting/BCM.mk
Normal file
20
platform/frt/porting/BCM.mk
Normal 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
|
16
platform/frt/porting/FBDev.mk
Normal file
16
platform/frt/porting/FBDev.mk
Normal 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
|
18
platform/frt/porting/KMSDRM.mk
Normal file
18
platform/frt/porting/KMSDRM.mk
Normal 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
|
6
platform/frt/porting/Local.mk
Normal file
6
platform/frt/porting/Local.mk
Normal 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
|
26
platform/frt/porting/Makefile
Normal file
26
platform/frt/porting/Makefile
Normal 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
|
25
platform/frt/porting/X11.mk
Normal file
25
platform/frt/porting/X11.mk
Normal 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
|
111
platform/frt/porting/test_all.cpp
Normal file
111
platform/frt/porting/test_all.cpp
Normal 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();
|
||||
}
|
71
platform/frt/porting/test_keyboard.cpp
Normal file
71
platform/frt/porting/test_keyboard.cpp
Normal 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();
|
||||
}
|
70
platform/frt/porting/test_modules.cpp
Normal file
70
platform/frt/porting/test_modules.cpp
Normal 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();
|
||||
}
|
77
platform/frt/porting/test_mouse.cpp
Normal file
77
platform/frt/porting/test_mouse.cpp
Normal 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();
|
||||
}
|
122
platform/frt/porting/test_video.cpp
Normal file
122
platform/frt/porting/test_video.cpp
Normal 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
111
platform/frt/release.sh
Executable 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
512
platform/frt/video_bcm.cpp
Normal 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
|
167
platform/frt/video_fbdev.cpp
Normal file
167
platform/frt/video_fbdev.cpp
Normal 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
|
313
platform/frt/video_kmsdrm.cpp
Normal file
313
platform/frt/video_kmsdrm.cpp
Normal 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
151
platform/frt/video_x11.cpp
Normal 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
|
Loading…
Reference in New Issue
Block a user