Added efornara's frt2 platform. (https://github.com/efornara/frt - 2.0 branch). It won't build when selected right now, due to core changes.

This commit is contained in:
Relintai 2022-03-27 13:00:05 +02:00
parent 4b2f580fda
commit cb739deb8e
28 changed files with 2922 additions and 0 deletions

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

@ -0,0 +1,6 @@
*.o
*.swp
*.pyc
*.gen.*
*.tmp
private/

21
platform/frt/LICENSE Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
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.

20
platform/frt/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Makefile
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
all:
@echo
@echo FRT is a platform for godot.
@echo
@echo You need to put it in the \"platform\" directory of godot and use scons as usual\;
@echo then, from the top level godot directory, you can type something like this:
@echo
@echo " " scons platform=frt tools=no target=release
@echo
@echo
clean:
rm -f *.o dl/*.gen.* import/*.o

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

@ -0,0 +1,96 @@
FRT2
====
patreon: efornaralabs
https://github.com/efornara/frt - f48d5792cca18041d7796a8d2a5263d8ba1edd43
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 to use FRT
Godot comes with a generic X11 platform that works very well on most
modern single board computer. So, if you are using X11, it is probably
better to compile the official engine for ARM and use that.
If your distro uses something other than X11, you can try if FRT works
for you. KMS/DRM and FBDEV are common display technologies, but Wayland
is also slowly becoming more popular.
## How to use FRT
First, you need to export a game from the official Godot editor.
The platform where you run the editor doesn't matter.
One option is to use precompiled binaries from here:
<https://sourceforge.net/projects/frt/files/>
as custom templates. Another option is to export a .PCK file and use
the FRT binary to run it. Details vary, but the end result is usually
a script with a command that looks something like this:
./frt_200_342_arm64v8.bin --main-pack MyGame.pck
There are some guides and posts around describing the process for FRT 1.0.
The process is pretty much the same for FRT 2.0.
### Which version?
FRT binary releases follow the following naming convention:
frt\_*frt-version*\_*godot-version*\_*arch-tag*.bin
For example:
frt\_200\_342\_arm32v7.bin
is FRT 2.0.0 compiled against Godot 3.4.2-stable. It is compiled for
a 32-bit distro. While:
frt\_200\_342\_arm64v8.bin
is compiled for a 64-bit distro.
The arm32v6 ones are there mainly to support older Pis.
My policy is to publish binaries for the latest release from upstream
plus 2.1.6 and the ones that were/are in debian stable (currenty 3.0.6
and 3.2.3). You are encouraged to compile any version you need yourself.
See [Compile](doc/Compile.md) for more info.
Ideally the codebase should be able to support building against any
upstream stable version since 2.1.6, but this is rarely tested.
## SDL2
Starting from version 2.0, FRT uses and dynamically links the SDL2 library,
so you can leverage a custom version of SDL2 patched for your board and
distro.
Keep in mind that SDL2 is a fairly complex library, and you can customize
its behaviour using environment variables. Before looking for alternatives
to the version of SDL2 already installed, it is probably worth spending some
time testing different drivers and options.
### Example: Pi Zero (older model)
In my (limited) experience, an exception is older Pis (the ones best used
with legacy drivers), where the SDL that you get out of the box is not
that great.
This would also serve as an example of how to use a custom SDL library.
Download a binary archive from here:
<https://github.com/efornara/sdl2/releases>
uncompress it somewhere, and run the FRT binary like this:
export LD_LIBRARY_PATH=~/local/sdl/linux-arm32v6
./frt_200_216_arm32v6.bin -path ~/games/mygame

47
platform/frt/SCsub Normal file
View File

@ -0,0 +1,47 @@
#! /usr/bin/env python
# SCSub
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
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_cc_action, suffix='.gen.cc', 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()
frt_env.ParseConfig(env['FRT_PKG_CONFIG'] + ' sdl2 --cflags --libs')
common_sources = [ 'frt_exe.cc', 'frt.cc' ]
import version
if version.major == 2:
version_sources = ['frt_godot2.cc', 'dl/gles2.gen.cc']
elif version.major == 3:
version_sources = ['frt_godot3.cc', 'dl/gles2.gen.cc', 'dl/gles3.gen.cc']
std = env['frt_std']
if std == 'auto':
std = {
2: 'c++98',
3: 'c++14',
}[version.major]
if std != 'no':
frt_env.Append(CCFLAGS=['-std=' + std])
prog = frt_env.add_program('#bin/godot', common_sources + version_sources)

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

@ -0,0 +1,31 @@
# detect.py
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
import version
if version.major == 2:
from detect_godot2 import *
version_handled = True
elif version.major == 3:
from detect_godot3 import *
version_handled = True
else:
version_handled = False
def get_name():
return "FRT"
def is_active():
return True
def can_build():
import os
if os.name != "posix":
return False
if not version_handled:
print("Error: Godot version not handled by FRT. Aborting.")
return False
return True

View File

@ -0,0 +1,111 @@
# detect_godot2.py
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
import os
import sys
import platform
def get_opts():
return [
('use_llvm', 'Use llvm compiler', 'no'),
('use_lto', 'Use link time optimization', 'no'),
('use_static_cpp', 'Link libgcc and libstdc++ statically', 'no'),
('frt_std', 'C++ standard for frt itself (no/auto/c++98/...)', 'auto'),
('frt_arch', 'Architecture (no/arm32v6/arm32v7/arm64v8)', 'no'),
('frt_cross', 'Cross compilation (no/auto/<triple>)', 'no'),
]
def get_flags():
return [
]
def configure_compiler(env):
if env['use_llvm'] == 'yes':
env['CC'] = 'clang'
env['CXX'] = 'clang++'
env['LD'] = 'clang++'
env.extra_suffix += '.llvm'
else:
print('Newer GCC compilers not supported in Godot 2. Handle with care.')
def configure_lto(env):
if env['use_lto'] == 'no':
return
if env['use_llvm'] == 'yes':
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'
def configure_arch(env):
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'
def configure_cross(env):
if env['frt_cross'] == 'no':
env['FRT_PKG_CONFIG'] = 'pkg-config'
return
if env['frt_cross'] == 'auto':
triple = {
'arm32v7': 'arm-linux-gnueabihf',
'arm64v8': 'aarch64-linux-gnu',
}[env['frt_arch']]
else:
triple = env['frt_cross']
if env['use_llvm'] == 'yes':
env.Append(CCFLAGS=['-target', triple])
env.Append(LINKFLAGS=['-target', triple])
else:
env['CC'] = triple + '-gcc'
env['CXX'] = triple + '-g++'
env['FRT_PKG_CONFIG'] = triple + '-pkg-config'
def configure_glsl_builders(env):
import methods
env.Append(BUILDERS={'GLSL120': env.Builder(action=methods.build_legacygl_headers, suffix='glsl.gen.h', src_suffix='.glsl')})
env.Append(BUILDERS={'GLSL': env.Builder(action=methods.build_glsl_headers, suffix='glsl.gen.h', src_suffix='.glsl')})
env.Append(BUILDERS={'GLSL120GLES': env.Builder(action=methods.build_gles2_headers, suffix='glsl.gen.h', src_suffix='.glsl')})
def configure_target(env):
if env['target'] == 'release':
env.Append(CCFLAGS=['-O2', '-ffast-math', '-fomit-frame-pointer'])
elif env['target'] == 'release_debug':
env.Append(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
elif env['target'] == 'debug':
env.Append(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
def configure_misc(env):
env.Append(CPPPATH=['#platform/frt'])
env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DJOYDEV_ENABLED'])
env.Append(CPPFLAGS=['-DFRT_ENABLED'])
env.Append(LIBS=['pthread', 'z'])
if env['CXX'] == 'clang++':
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
env['CC'] = 'clang'
env['LD'] = 'clang++'
if env['use_static_cpp'] == 'yes':
env.Append(LINKFLAGS=['-static-libgcc', '-static-libstdc++'])
def configure(env):
configure_compiler(env)
configure_lto(env)
configure_arch(env)
configure_cross(env)
configure_glsl_builders(env)
configure_target(env)
configure_misc(env)

View File

@ -0,0 +1,108 @@
# detect_godot3.py
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
import os
import sys
import platform
import version
# TODO factor out common bits
def get_opts():
from SCons.Variables import BoolVariable
return [
BoolVariable('use_llvm', 'Use llvm compiler', False),
BoolVariable('use_lto', 'Use link time optimization', False),
BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically', False),
('frt_std', 'C++ standard for frt itself (no/auto/c++98/...)', 'auto'),
('frt_arch', 'Architecture (no/arm32v6/arm32v7/arm64v8)', 'no'),
('frt_cross', 'Cross compilation (no/auto/<triple>)', 'no'),
]
def get_flags():
return [
]
def configure_compiler(env):
if env['use_llvm']:
env['CC'] = 'clang'
env['CXX'] = 'clang++'
env['LD'] = 'clang++'
env.extra_suffix += '.llvm'
def configure_lto(env):
if not env['use_lto']:
return
if 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'
def configure_arch(env):
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'
def configure_cross(env):
if env['frt_cross'] == 'no':
env['FRT_PKG_CONFIG'] = 'pkg-config'
return
if env['frt_cross'] == 'auto':
triple = {
'arm32v7': 'arm-linux-gnueabihf',
'arm64v8': 'aarch64-linux-gnu',
}[env['frt_arch']]
else:
triple = env['frt_cross']
if env['use_llvm']:
env.Append(CCFLAGS=['-target', triple])
env.Append(LINKFLAGS=['-target', triple])
else:
env['CC'] = triple + '-gcc'
env['CXX'] = triple + '-g++'
env['FRT_PKG_CONFIG'] = triple + '-pkg-config'
def configure_target(env):
if env['target'] == 'release':
env.Append(CCFLAGS=['-O2', '-ffast-math', '-fomit-frame-pointer'])
elif env['target'] == 'release_debug':
env.Append(CCFLAGS=['-O2', '-ffast-math'])
elif env['target'] == 'debug':
env.Append(CCFLAGS=['-g2'])
def configure_misc(env):
env.Append(CPPPATH=['#platform/frt'])
env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DGLES_ENABLED', '-DJOYDEV_ENABLED'])
env.Append(CPPFLAGS=['-DFRT_ENABLED'])
env.Append(CFLAGS=['-std=gnu11']) # for libwebp (maybe more in the future)
env.Append(LIBS=['pthread', 'z', 'dl'])
if env['frt_arch'] == 'arm32v6' and version.minor >= 4: # TODO find out exact combination
env.Append(LIBS=['atomic'])
if env['CXX'] == 'clang++':
env['CC'] = 'clang'
env['LD'] = 'clang++'
if env['use_static_cpp']:
env.Append(LINKFLAGS=['-static-libgcc', '-static-libstdc++'])
def configure(env):
configure_compiler(env)
configure_lto(env)
configure_arch(env)
configure_cross(env)
configure_target(env)
configure_misc(env)

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

@ -0,0 +1,153 @@
// gles2.dl
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#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);

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

@ -0,0 +1,255 @@
// gles3.dl
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#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);

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

@ -0,0 +1,112 @@
#! /usr/bin/python
# procdl.py
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
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('typedef void *(*FRT_FN_' + libname + '_GetProcAddress)(const char *name);')
out('extern void frt_resolve_symbols_' + libname + '(FRT_FN_' + libname + '_GetProcAddress get_proc_address);')
f.close()
def build_cc(dl, cc):
libname, head, symbols, types, includes = parse_dl(dl, '.gen.cc')
f = open(cc, '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 += 'get_proc_address("' + s + '");\n'
f.write("""\
#include "%(libname)s.gen.h"
#include <stdio.h>
%(assignments)s
void frt_resolve_symbols_%(libname)s(FRT_FN_%(libname)s_GetProcAddress get_proc_address) {
%(resolutions)s
}
""" % {
'libname': libname,
'assignments': assignments[:-1],
'resolutions': resolutions[:-1]
})
f.close()
def build_cc_action(target, source, env):
build_cc(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_cc(s, s.replace('.dl', '.gen.cc'))
build_h(s, s.replace('.dl', '.gen.h'))
sys.stdout.write('done.\n')

View File

@ -0,0 +1,77 @@
Compile
=======
## Native Compilation
As a prerequisite for compiling FRT, these packages should be enough
(using debian as an example):
$ sudo apt-get install build-essential scons pkg-config \
clang llvm lld libsdl2-dev libgles2-mesa-dev
Download and uncompress an official Godot source tarball from:
<https://github.com/godotengine/godot/releases>
or:
<https://downloads.tuxfamily.org/godotengine>
Here it is assumed that the top directory of the Godot source is ~/godot.
Go to the platform directory and clone this repository:
$ cd ~/godot
$ cd platform
$ git clone -b 2.0 https://github.com/efornara/frt
From the main directory, you now have a new platform available:
$ cd ~/godot
$ scons platform=frt tools=no target=release use_llvm=yes -j 4
_NOTE: If you only have access to a recent version of gcc (i.e. 6 or later),
you can only compile Godot 2 by using debug as a target._
## Cross compilation, crossbuild and release.sh
As an example, here are the steps needed to build some binaries on
a PC using docker. Even if you don't use docker, my crossbuild images
or the official script, these instructions, the Dockerfiles and the
script should have all the info that you need.
Create the docker images:
$ git clone https://github.com/efornara/crossbuild
$ cd crossbuild/docker
$ ./build.sh base
[...]
$ ./build.sh arm32v7
[...]
$ ./docker.sh arm32v7
root@.....:/# su - builder
builder@.....:$
You should be able to su to your user (builder in my case) and find your
home directory.
You might have everything you need in the container, but I usually
open another terminal and work outside the container, except for
compiling.
The release.sh script needs the current directory to look like this:
$ ls ~/somewhere
releases/ tag_216/ tag_342/
A directory where to copy the binaries (releases/) and every godot
version in its own directory named according to its "tag" version
and with frt already inside platform (see above).
From within the container, type:
$ cd ~/somewhere
$ ./tag_216/platform/frt/release.sh arm32v7 tag_*
If everything goes well, after a while you should have your binaries
ready in ~/somewhere/releases.

View File

@ -0,0 +1,6 @@
Release Notes
=============
## FRT 2.0.0
A rewrite of FRT that uses SDL2 instead of custom modules.

42
platform/frt/frt.cc Normal file
View File

@ -0,0 +1,42 @@
// frt.cc
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#include "frt.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
static void print_msg(const char *format, va_list ap) {
fprintf(stderr, "frt: ");
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
}
namespace frt {
void warn(const char *format, ...) {
va_list ap;
va_start(ap, format);
print_msg(format, ap);
va_end(ap);
}
void fatal(const char *format, ...) {
va_list ap;
va_start(ap, format);
print_msg(format, ap);
va_end(ap);
exit(1);
}
} // namespace frt
#include "frt_lib.h"
extern "C" void frt_parse_frt_args(int argc, char *argv[]) {
}

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

@ -0,0 +1,25 @@
// frt.h
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#define FRT_VERSION "2.0.0"
#if __cplusplus >= 201103L
#define FRT_OVERRIDE override
#else
#define FRT_OVERRIDE
#endif
namespace frt {
void warn(const char *format, ...);
#if __cplusplus >= 201103L
[[ noreturn ]]
#endif
void fatal(const char *format, ...);
} // namespace frt

28
platform/frt/frt_exe.cc Normal file
View File

@ -0,0 +1,28 @@
// frt_exe.cc
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#include "frt_lib.h"
#include <string.h>
static void handle_frt_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];
frt_parse_frt_args(frt_argc, frt_argv);
*argc = i;
break;
}
}
}
int main(int argc, char *argv[]) {
handle_frt_args(&argc, &argv);
return frt_godot_main(argc, argv);
}

393
platform/frt/frt_godot2.cc Normal file
View File

@ -0,0 +1,393 @@
// frt_godot2.cc
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#include "frt.h"
#include "sdl2_adapter.h"
#include "sdl2_godot_mapping.h"
#include "dl/gles2.gen.h"
#include "core/print_string.h"
#include "drivers/unix/os_unix.h"
#include "servers/visual_server.h"
#include "servers/visual/visual_server_wrap_mt.h"
#include "servers/visual/rasterizer.h"
#include "servers/physics_server.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/physics_server_sw.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
#include "servers/visual/visual_server_raster.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "main/main.h"
namespace frt {
class AudioDriverSDL2 : public AudioDriverSW, public SampleProducer {
private:
Audio audio_;
int mix_rate_;
OutputFormat output_format_;
public:
AudioDriverSDL2() : audio_(this) {
}
public: // AudioDriverSW
const char *get_name() const FRT_OVERRIDE {
return "SDL2";
}
Error init() FRT_OVERRIDE {
mix_rate_ = GLOBAL_DEF("audio/mix_rate", 44100);
output_format_ = OUTPUT_STEREO;
const int latency = GLOBAL_DEF("audio/output_latency", 25);
const int samples = closest_power_of_2(latency * mix_rate_ / 1000);
return audio_.init(mix_rate_, samples) ? OK : ERR_CANT_OPEN;
}
int get_mix_rate() const FRT_OVERRIDE {
return mix_rate_;
}
OutputFormat get_output_format() const FRT_OVERRIDE {
return output_format_;
}
void start() FRT_OVERRIDE {
audio_.start();
}
void lock() FRT_OVERRIDE {
audio_.lock();
}
void unlock() FRT_OVERRIDE {
audio_.unlock();
}
void finish() FRT_OVERRIDE {
audio_.finish();
}
public: // SampleProducer
void produce_samples(int n_of_frames, int32_t *frames) FRT_OVERRIDE {
audio_server_process(n_of_frames, frames);
}
};
class Godot2_OS : public OS_Unix, public EventHandler {
private:
MainLoop *main_loop_;
VideoMode video_mode_;
bool quit_;
OS_FRT os_;
RasterizerGLES2 *rasterizer_;
VisualServer *visual_server_;
int event_id_;
void init_video() {
rasterizer_ = memnew(RasterizerGLES2);
visual_server_ = memnew(VisualServerRaster(rasterizer_));
visual_server_->init();
}
void cleanup_video() {
visual_server_->finish();
memdelete(visual_server_);
memdelete(rasterizer_);
}
AudioDriverSDL2 audio_driver_;
AudioServerSW *audio_server_;
SampleManagerMallocSW *sample_manager_;
SpatialSoundServerSW *spatial_sound_server_;
SpatialSound2DServerSW *spatial_sound_2d_server_;
void init_audio() {
const int driver_id = 0;
AudioDriverManagerSW::add_driver(&audio_driver_);
AudioDriverManagerSW::get_driver(driver_id)->set_singleton();
if (AudioDriverManagerSW::get_driver(driver_id)->init() != OK)
fatal("audio driver failed to initialize.");
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();
}
void cleanup_audio() {
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_);
}
PhysicsServer *physics_server_;
Physics2DServer *physics_2d_server_;
void init_physics() {
physics_server_ = memnew(PhysicsServerSW);
physics_server_->init();
physics_2d_server_ = memnew(Physics2DServerSW);
physics_2d_server_->init();
}
void cleanup_physics() {
physics_2d_server_->finish();
memdelete(physics_2d_server_);
physics_server_->finish();
memdelete(physics_server_);
}
InputDefault *input_;
Point2 mouse_pos_;
int mouse_state_;
void init_input() {
input_ = memnew(InputDefault);
mouse_pos_ = Point2(-1, -1);
mouse_state_ = 0;
}
void cleanup_input() {
memdelete(input_);
}
void fill_modifier_state(::InputModifierState &st) {
const InputModifierState *os_st = os_.get_modifier_state();
st.shift = os_st->shift;
st.alt = os_st->alt;
st.control = os_st->control;
st.meta = os_st->meta;
}
public:
Godot2_OS() : os_(this) {
main_loop_ = 0;
quit_ = false;
event_id_ = 0;
}
void run() {
if (main_loop_) {
main_loop_->init();
while (!quit_ && !Main::iteration())
os_.dispatch_events();
main_loop_->finish();
}
}
public: // OS
int get_video_driver_count() const FRT_OVERRIDE {
return 1;
}
const char *get_video_driver_name(int driver) const FRT_OVERRIDE {
return "GLES2";
}
VideoMode get_default_video_mode() const FRT_OVERRIDE {
return OS::VideoMode(960, 540, false);
}
void initialize(const VideoMode &desired, int video_driver, int audio_driver) FRT_OVERRIDE {
video_mode_ = desired;
os_.init(API_OpenGL_ES2, video_mode_.width, video_mode_.height, video_mode_.resizable, video_mode_.borderless_window, video_mode_.always_on_top);
frt_resolve_symbols_gles2(get_proc_address);
init_video();
init_audio();
init_physics();
init_input();
_ensure_data_dir();
}
void set_main_loop(MainLoop *main_loop) FRT_OVERRIDE {
main_loop_ = main_loop;
input_->set_main_loop(main_loop);
}
void delete_main_loop() FRT_OVERRIDE {
if (main_loop_)
memdelete(main_loop_);
main_loop_ = 0;
}
void finalize() FRT_OVERRIDE {
delete_main_loop();
cleanup_input();
cleanup_physics();
cleanup_audio();
cleanup_video();
os_.cleanup();
}
Point2 get_mouse_pos() const FRT_OVERRIDE {
return mouse_pos_;
}
int get_mouse_button_state() const FRT_OVERRIDE {
return mouse_state_;
}
void set_mouse_mode(OS::MouseMode mode) FRT_OVERRIDE {
os_.set_mouse_mode(map_mouse_mode(mode));
}
OS::MouseMode get_mouse_mode() const FRT_OVERRIDE {
return map_mouse_os_mode(os_.get_mouse_mode());
}
void set_window_title(const String &title) FRT_OVERRIDE {
os_.set_title(title.utf8().get_data());
}
void set_video_mode(const VideoMode &video_mode, int screen) FRT_OVERRIDE {
}
VideoMode get_video_mode(int screen = 0) const FRT_OVERRIDE {
return video_mode_;
}
void get_fullscreen_mode_list(List<VideoMode> *list, int screen) const FRT_OVERRIDE {
}
Size2 get_window_size() const FRT_OVERRIDE {
return Size2(video_mode_.width, video_mode_.height);
}
void set_window_size(const Size2 size) FRT_OVERRIDE {
ivec2 os_size = { (int)size.width, (int)size.height };
os_.set_size(os_size);
video_mode_.width = os_size.x;
video_mode_.height = os_size.y;
}
Point2 get_window_position() const FRT_OVERRIDE {
ivec2 pos = os_.get_pos();
return Point2(pos.x, pos.y);
}
void set_window_position(const Point2 &pos) FRT_OVERRIDE {
ivec2 os_pos = { (int)pos.width, (int)pos.height };
os_.set_pos(os_pos);
}
void set_window_fullscreen(bool enable) FRT_OVERRIDE {
os_.set_fullscreen(enable);
video_mode_.fullscreen = enable;
}
bool is_window_fullscreen() const FRT_OVERRIDE {
return os_.is_fullscreen();
}
void set_window_always_on_top(bool enable) FRT_OVERRIDE {
os_.set_always_on_top(enable);
video_mode_.always_on_top = enable;
}
bool is_window_always_on_top() const FRT_OVERRIDE {
return os_.is_always_on_top();
}
void set_window_resizable(bool enable) FRT_OVERRIDE {
os_.set_resizable(enable);
}
bool is_window_resizable() const FRT_OVERRIDE {
return os_.is_resizable();
}
void set_window_maximized(bool enable) FRT_OVERRIDE {
os_.set_maximized(enable);
}
bool is_window_maximized() const FRT_OVERRIDE {
return os_.is_maximized();
}
void set_window_minimized(bool enable) FRT_OVERRIDE {
os_.set_minimized(enable);
}
bool is_window_minimized() const FRT_OVERRIDE {
return os_.is_minimized();
}
MainLoop *get_main_loop() const FRT_OVERRIDE {
return main_loop_;
}
bool can_draw() const FRT_OVERRIDE {
return true;
}
void set_cursor_shape(CursorShape shape) FRT_OVERRIDE {
}
void set_custom_mouse_cursor(const RES &cursor, CursorShape shape, const Vector2 &hotspot) FRT_OVERRIDE {
}
void make_rendering_thread() FRT_OVERRIDE {
os_.make_current();
}
void release_rendering_thread() FRT_OVERRIDE {
os_.release_current();
}
void swap_buffers() FRT_OVERRIDE {
os_.swap_buffers();
}
void set_use_vsync(bool enable) FRT_OVERRIDE {
os_.set_use_vsync(enable);
}
bool is_vsync_enabled() const FRT_OVERRIDE {
return os_.is_vsync_enabled();
}
public: // EventHandler
void handle_resize_event(ivec2 size) FRT_OVERRIDE {
video_mode_.width = size.x;
video_mode_.height = size.y;
}
void handle_key_event(int sdl2_code, int unicode, bool pressed) FRT_OVERRIDE {
int code = map_key_sdl2_code(sdl2_code);
InputEvent event;
event.ID = ++event_id_;
event.type = InputEvent::KEY;
event.device = 0;
fill_modifier_state(event.key.mod);
event.key.pressed = pressed;
event.key.scancode = code;
event.key.unicode = unicode;
event.key.echo = 0;
input_->parse_input_event(event);
}
void handle_mouse_motion_event(ivec2 pos, ivec2 dpos) FRT_OVERRIDE {
mouse_pos_.x = pos.x;
mouse_pos_.y = pos.y;
InputEvent event;
event.ID = ++event_id_;
event.type = InputEvent::MOUSE_MOTION;
event.device = 0;
fill_modifier_state(event.mouse_motion.mod);
event.mouse_motion.button_mask = mouse_state_;
event.mouse_motion.x = mouse_pos_.x;
event.mouse_motion.y = mouse_pos_.y;
input_->set_mouse_pos(mouse_pos_);
event.mouse_motion.global_x = mouse_pos_.x;
event.mouse_motion.global_y = mouse_pos_.y;
event.mouse_motion.speed_x = input_->get_mouse_speed().x;
event.mouse_motion.speed_y = input_->get_mouse_speed().y;
event.mouse_motion.relative_x = dpos.x;
event.mouse_motion.relative_y = dpos.y;
input_->parse_input_event(event);
}
void handle_mouse_button_event(int os_button, bool pressed, bool doubleclick) FRT_OVERRIDE {
int button = map_mouse_os_button(os_button);
int bit = (1 << (button - 1));
if (pressed)
mouse_state_ |= bit;
else
mouse_state_ &= ~bit;
InputEvent event;
event.ID = ++event_id_;
event.type = InputEvent::MOUSE_BUTTON;
event.device = 0;
fill_modifier_state(event.mouse_button.mod);
event.mouse_button.button_mask = mouse_state_;
event.mouse_button.x = mouse_pos_.x;
event.mouse_button.y = mouse_pos_.y;
event.mouse_button.global_x = mouse_pos_.x;
event.mouse_button.global_y = mouse_pos_.y;
event.mouse_button.button_index = button;
event.mouse_button.doubleclick = doubleclick;
event.mouse_button.pressed = pressed;
input_->parse_input_event(event);
}
void handle_js_status_event(int id, bool connected, const char *name, const char *guid) FRT_OVERRIDE {
input_->joy_connection_changed(id, connected, name, guid);
}
void handle_js_button_event(int id, int button, bool pressed) FRT_OVERRIDE {
event_id_ = input_->joy_button(event_id_, id, button, pressed ? 1 : 0);
}
void handle_js_axis_event(int id, int axis, float value) FRT_OVERRIDE {
InputDefault::JoyAxis v = { -1, value };
event_id_ = input_->joy_axis(event_id_, id, axis, v);
}
void handle_js_hat_event(int id, int os_mask) FRT_OVERRIDE {
int mask = map_hat_os_mask(os_mask);
event_id_ = input_->joy_hat(event_id_, id, mask);
}
void handle_quit_event() FRT_OVERRIDE {
quit_ = true;
}
};
} // namespace frt
#include "frt_lib.h"
extern "C" int frt_godot_main(int argc, char *argv[]) {
frt::Godot2_OS os;
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
if (err != OK)
return 255;
if (Main::start())
os.run();
Main::cleanup();
return os.get_exit_code();
}

401
platform/frt/frt_godot3.cc Normal file
View File

@ -0,0 +1,401 @@
// frt_godot3.cc
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#include "frt.h"
#include "sdl2_adapter.h"
#include "sdl2_godot_mapping.h"
#include "drivers/gles3/rasterizer_gles3.h"
#define FRT_DL_SKIP
#include "drivers/gles2/rasterizer_gles2.h"
#include "core/print_string.h"
#include "drivers/unix/os_unix.h"
#pragma GCC diagnostic ignored "-Wvolatile"
#include "servers/audio_server.h"
#pragma GCC diagnostic pop
#include "servers/visual_server.h"
#include "servers/visual/visual_server_wrap_mt.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/visual_server_raster.h"
#include "main/main.h"
namespace frt {
static const char *default_audio_device = "default"; // TODO
class AudioDriverSDL2 : public AudioDriver, public SampleProducer {
private:
Audio audio_;
int mix_rate_;
SpeakerMode speaker_mode_;
public:
AudioDriverSDL2() : audio_(this) {
}
public: // AudioDriverSW
const char *get_name() const FRT_OVERRIDE {
return "SDL2";
}
Error init() FRT_OVERRIDE {
mix_rate_ = GLOBAL_GET("audio/mix_rate");
speaker_mode_ = SPEAKER_MODE_STEREO;
const int latency = GLOBAL_GET("audio/output_latency");
const int samples = closest_power_of_2(latency * mix_rate_ / 1000);
return audio_.init(mix_rate_, samples) ? OK : ERR_CANT_OPEN;
}
int get_mix_rate() const FRT_OVERRIDE {
return mix_rate_;
}
SpeakerMode get_speaker_mode() const FRT_OVERRIDE {
return speaker_mode_;
}
Array get_device_list() FRT_OVERRIDE {
Array list;
list.push_back(default_audio_device);
return list;
}
String get_device() FRT_OVERRIDE {
return default_audio_device;
}
void set_device(String device) FRT_OVERRIDE {
}
void start() FRT_OVERRIDE {
audio_.start();
}
void lock() FRT_OVERRIDE {
audio_.lock();
}
void unlock() FRT_OVERRIDE {
audio_.unlock();
}
void finish() FRT_OVERRIDE {
audio_.finish();
}
public: // SampleProducer
void produce_samples(int n_of_frames, int32_t *frames) FRT_OVERRIDE {
audio_server_process(n_of_frames, frames);
}
};
class Godot3_OS : public OS_Unix, public EventHandler {
private:
enum {
VIDEO_DRIVER_GLES2,
VIDEO_DRIVER_GLES3
};
MainLoop *main_loop_;
VideoMode video_mode_;
bool quit_;
OS_FRT os_;
int video_driver_;
VisualServer *visual_server_;
void init_video() {
if (video_driver_ == VIDEO_DRIVER_GLES2) {
frt_resolve_symbols_gles2(get_proc_address);
RasterizerGLES2::register_config();
RasterizerGLES2::make_current();
} else {
frt_resolve_symbols_gles3(get_proc_address);
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
}
visual_server_ = memnew(VisualServerRaster);
visual_server_->init();
}
void cleanup_video() {
visual_server_->finish();
memdelete(visual_server_);
}
AudioDriverSDL2 audio_driver_;
void init_audio(int id) {
AudioDriverManager::initialize(id);
}
void cleanup_audio() {
}
InputDefault *input_;
Point2 mouse_pos_;
int mouse_state_;
void init_input() {
input_ = memnew(InputDefault);
mouse_pos_ = Point2(-1, -1);
mouse_state_ = 0;
}
void cleanup_input() {
memdelete(input_);
}
void fill_modifier_state(Ref<InputEventWithModifiers> st) {
const InputModifierState *os_st = os_.get_modifier_state();
st->set_shift(os_st->shift);
st->set_alt(os_st->alt);
st->set_control(os_st->control);
st->set_metakey(os_st->meta);
}
public:
Godot3_OS() : os_(this) {
AudioDriverManager::add_driver(&audio_driver_);
main_loop_ = 0;
quit_ = false;
}
void run() {
if (main_loop_) {
main_loop_->init();
while (!quit_ && !Main::iteration())
os_.dispatch_events();
main_loop_->finish();
}
}
public: // OS
int get_video_driver_count() const FRT_OVERRIDE {
return 2;
}
#if FRT_GODOT_VERSION >= 30100
int get_current_video_driver() const FRT_OVERRIDE {
return video_driver_;
}
#endif
const char *get_video_driver_name(int driver) const FRT_OVERRIDE {
return driver == VIDEO_DRIVER_GLES3 ? "GLES3" : "GLES2";
}
bool _check_internal_feature_support(const String &feature) FRT_OVERRIDE {
if (video_driver_ == VIDEO_DRIVER_GLES3 && feature == "etc2")
return true;
return feature == "mobile" || feature == "etc";
}
String get_config_path() const FRT_OVERRIDE {
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 FRT_OVERRIDE {
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 FRT_OVERRIDE {
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();
}
Error initialize(const VideoMode &desired, int video_driver, int audio_driver) FRT_OVERRIDE {
video_mode_ = desired;
video_driver_ = video_driver;
const GraphicsAPI api = video_driver == VIDEO_DRIVER_GLES2 ? API_OpenGL_ES2 : API_OpenGL_ES3;
os_.init(api, video_mode_.width, video_mode_.height, video_mode_.resizable, video_mode_.borderless_window, video_mode_.always_on_top);
_set_use_vsync(video_mode_.use_vsync);
init_video();
init_audio(audio_driver);
init_input();
#if FRT_GODOT_VERSION < 30300
_ensure_user_data_dir();
#endif
return OK;
}
void set_main_loop(MainLoop *main_loop) FRT_OVERRIDE {
main_loop_ = main_loop;
input_->set_main_loop(main_loop);
}
void delete_main_loop() FRT_OVERRIDE {
if (main_loop_)
memdelete(main_loop_);
main_loop_ = 0;
}
void finalize() FRT_OVERRIDE {
delete_main_loop();
cleanup_input();
cleanup_audio();
cleanup_video();
os_.cleanup();
}
Point2 get_mouse_position() const FRT_OVERRIDE {
return mouse_pos_;
}
int get_mouse_button_state() const FRT_OVERRIDE {
return mouse_state_;
}
void set_mouse_mode(OS::MouseMode mode) FRT_OVERRIDE {
os_.set_mouse_mode(map_mouse_mode(mode));
}
OS::MouseMode get_mouse_mode() const FRT_OVERRIDE {
return map_mouse_os_mode(os_.get_mouse_mode());
}
void set_window_title(const String &title) FRT_OVERRIDE {
os_.set_title(title.utf8().get_data());
}
void set_video_mode(const VideoMode &video_mode, int screen) FRT_OVERRIDE {
}
VideoMode get_video_mode(int screen = 0) const FRT_OVERRIDE {
return video_mode_;
}
void get_fullscreen_mode_list(List<VideoMode> *list, int screen) const FRT_OVERRIDE {
}
Size2 get_window_size() const FRT_OVERRIDE {
return Size2(video_mode_.width, video_mode_.height);
}
void set_window_size(const Size2 size) FRT_OVERRIDE {
ivec2 os_size = { (int)size.width, (int)size.height };
os_.set_size(os_size);
video_mode_.width = os_size.x;
video_mode_.height = os_size.y;
}
Point2 get_window_position() const FRT_OVERRIDE {
ivec2 pos = os_.get_pos();
return Point2(pos.x, pos.y);
}
void set_window_position(const Point2 &pos) FRT_OVERRIDE {
ivec2 os_pos = { (int)pos.width, (int)pos.height };
os_.set_pos(os_pos);
}
void set_window_fullscreen(bool enable) FRT_OVERRIDE {
os_.set_fullscreen(enable);
video_mode_.fullscreen = enable;
}
bool is_window_fullscreen() const FRT_OVERRIDE {
return os_.is_fullscreen();
}
void set_window_always_on_top(bool enable) FRT_OVERRIDE {
os_.set_always_on_top(enable);
video_mode_.always_on_top = enable;
}
bool is_window_always_on_top() const FRT_OVERRIDE {
return os_.is_always_on_top();
}
void set_window_resizable(bool enable) FRT_OVERRIDE {
os_.set_resizable(enable);
}
bool is_window_resizable() const FRT_OVERRIDE {
return os_.is_resizable();
}
void set_window_maximized(bool enable) FRT_OVERRIDE {
os_.set_maximized(enable);
}
bool is_window_maximized() const FRT_OVERRIDE {
return os_.is_maximized();
}
void set_window_minimized(bool enable) FRT_OVERRIDE {
os_.set_minimized(enable);
}
bool is_window_minimized() const FRT_OVERRIDE {
return os_.is_minimized();
}
MainLoop *get_main_loop() const FRT_OVERRIDE {
return main_loop_;
}
bool can_draw() const FRT_OVERRIDE {
return true;
}
void set_cursor_shape(CursorShape shape) FRT_OVERRIDE {
}
void set_custom_mouse_cursor(const RES &cursor, CursorShape shape, const Vector2 &hotspot) FRT_OVERRIDE {
}
void make_rendering_thread() FRT_OVERRIDE {
os_.make_current();
}
void release_rendering_thread() FRT_OVERRIDE {
os_.release_current();
}
void swap_buffers() FRT_OVERRIDE {
os_.swap_buffers();
}
void _set_use_vsync(bool enable) FRT_OVERRIDE {
os_.set_use_vsync(enable);
}
public: // EventHandler
void handle_resize_event(ivec2 size) FRT_OVERRIDE {
video_mode_.width = size.x;
video_mode_.height = size.y;
}
void handle_key_event(int sdl2_code, int unicode, bool pressed) FRT_OVERRIDE {
int code = map_key_sdl2_code(sdl2_code);
Ref<InputEventKey> key;
key.instance();
fill_modifier_state(key);
key->set_pressed(pressed);
key->set_scancode(code);
#if FRT_GODOT_VERSION >= 30400
key->set_physical_scancode(code); // TODO
#endif
key->set_unicode(unicode);
key->set_echo(false);
input_->parse_input_event(key);
}
void handle_mouse_motion_event(ivec2 pos, ivec2 dpos) FRT_OVERRIDE {
mouse_pos_.x = pos.x;
mouse_pos_.y = pos.y;
Ref<InputEventMouseMotion> mouse_motion;
mouse_motion.instance();
fill_modifier_state(mouse_motion);
Point2i posi(pos.x, pos.y);
mouse_motion->set_button_mask(mouse_state_);
mouse_motion->set_position(posi);
mouse_motion->set_global_position(posi);
input_->set_mouse_position(posi);
mouse_motion->set_speed(input_->get_last_mouse_speed());
Point2i reli(dpos.x, dpos.y);
mouse_motion->set_relative(reli);
input_->parse_input_event(mouse_motion);
}
void handle_mouse_button_event(int os_button, bool pressed, bool doubleclick) FRT_OVERRIDE {
int button = map_mouse_os_button(os_button);
int bit = (1 << (button - 1));
if (pressed)
mouse_state_ |= bit;
else
mouse_state_ &= ~bit;
Ref<InputEventMouseButton> mouse_button;
mouse_button.instance();
fill_modifier_state(mouse_button);
Point2i posi(mouse_pos_.x, mouse_pos_.y);
mouse_button->set_position(posi);
mouse_button->set_global_position(posi);
mouse_button->set_button_index(button);
mouse_button->set_button_mask(mouse_state_);
mouse_button->set_doubleclick(doubleclick);
mouse_button->set_pressed(pressed);
input_->parse_input_event(mouse_button);
}
void handle_js_status_event(int id, bool connected, const char *name, const char *guid) FRT_OVERRIDE {
input_->joy_connection_changed(id, connected, name, guid);
}
void handle_js_button_event(int id, int button, bool pressed) FRT_OVERRIDE {
input_->joy_button(id, button, pressed ? 1 : 0);
}
void handle_js_axis_event(int id, int axis, float value) FRT_OVERRIDE {
#if FRT_GODOT_VERSION >= 30500
input_->set_joy_axis(id, axis, value);
#else
InputDefault::JoyAxis v = { -1, value };
input_->joy_axis(id, axis, v);
#endif
}
void handle_js_hat_event(int id, int os_mask) FRT_OVERRIDE {
int mask = map_hat_os_mask(os_mask);
input_->joy_hat(id, mask);
}
void handle_quit_event() FRT_OVERRIDE {
quit_ = true;
}
};
} // namespace frt
#include "frt_lib.h"
extern "C" int frt_godot_main(int argc, char *argv[]) {
frt::Godot3_OS os;
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
if (err != OK)
return 255;
if (Main::start())
os.run();
Main::cleanup();
return os.get_exit_code();
}

22
platform/frt/frt_lib.h Normal file
View File

@ -0,0 +1,22 @@
/* frt_lib.h */
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#ifndef FRT_LIB_H
#define FRT_LIB_H
#ifdef __cplusplus
extern "C" {
#endif
void frt_parse_frt_args(int argc, char *argv[]);
int frt_godot_main(int argc, char *argv[]);
#ifdef __cplusplus
}
#endif
#endif /* FRT_LIB_H */

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

@ -0,0 +1,14 @@
// gles2_egl.h
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#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)

BIN
platform/frt/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

View File

@ -0,0 +1,11 @@
// platform_config.h
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#include <alloca.h>
#define GLES2_INCLUDE_H "gles2_egl.h"
#define GLES3_INCLUDE_H "dl/gles3.gen.h"

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

@ -0,0 +1,96 @@
#! /bin/sh
set -e
# release.sh
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
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 use_static_cpp=yes -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."
export BUILD_NAME=frt
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

74
platform/frt/scripts/compile.sh Executable file
View File

@ -0,0 +1,74 @@
#! /bin/sh
set -e
# compile.sh
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
# just an example
usage() {
cat <<EOT
usage: compile.sh <arch> <preset> [extra_scons_options]
where:
arch: arm32v7 arm64v8 native
preset: clang gcc clang-lto gcc-lto
example:
compile.sh arm32v7 clang use_static_cpp=yes -j4
EOT
exit 1
}
[ $# -ge 2 ] || usage
arch="$1"
preset="$2"
shift 2
case "$arch" in
arm32v7|arm64v8)
export PKG_CONFIG_PATH="$HOME/crossbuild/local/linux-$arch/lib/pkgconfig"
cross_opts="frt_arch=$arch frt_cross=auto"
;;
native)
cross_opts=""
;;
*)
echo "compile.sh: unknwon <arch>: $arch"
usage
;;
esac
case "$preset" in
clang)
nice scons platform=frt use_llvm=yes use_lto=no \
tools=no target=release \
$cross_opts $*
;;
gcc)
nice scons platform=frt use_llvm=no use_lto=no \
tools=no target=debug \
$cross_opts $*
;;
clang-lto)
nice scons platform=frt use_llvm=yes use_lto=yes \
tools=no target=release \
$cross_opts $*
;;
gcc-lto)
nice scons platform=frt use_llvm=no use_lto=yes \
tools=no target=debug \
$cross_opts $*
;;
*)
echo "compile.sh: unknwon <preset>: $preset"
usage
;;
esac

View File

@ -0,0 +1,26 @@
#! /bin/sh
set -e
# for_tags.sh
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
usage() {
echo 'usage: for_tags.sh -g|-p|-f command...'
exit 1
}
[ $# -ge 1 ] || usage
arg="$1"
shift
case "$arg" in
-g) for i in tag_* ; do (cd $i ; $*) ; done ;;
-p) for i in tag_* ; do (cd $i/platform ; $*) ; done ;;
-f) for i in tag_* ; do (cd $i/platform/frt ; $*) ; done ;;
*) usage
esac

70
platform/frt/scripts/rolling.sh Executable file
View File

@ -0,0 +1,70 @@
#! /bin/sh
set -e
# rolling.sh
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022 Emanuele Fornara
# SPDX-License-Identifier: MIT
#
if [ $# -ge 2 -a "$1" = '-t' ] ; then
tag=$2
shift 2
else
tag=343
fi
build_216_98() {
echo 'Building 216 (C++ 98)'
cd tag_216
nice scons platform=frt tools=no target=release use_llvm=yes frt_std=c++98 -j 3
cd ..
}
build_216_14() {
echo 'Building 216 (C++ 14)'
cd tag_216
nice scons platform=frt tools=no target=release use_llvm=yes frt_std=c++14 -j 3
cd ..
}
build_latest() {
echo "Building ${tag} (C++ 20)"
cd tag_${tag}
nice scons platform=frt tools=no target=release use_static_cpp=yes frt_std=c++20 -j 3
cd ..
strip tag_${tag}/bin/godot.frt.opt
cp tag_${tag}/bin/godot.frt.opt releases/frt_${tag}_amd64.bin
}
pack() {
echo "Packing ${tag}"
cd releases
gzip --keep --force frt_${tag}_amd64.bin
ls -l frt_${tag}_amd64.bin.gz
cd ..
}
export BUILD_NAME=frt
case "$1" in
298)
build_216_98
;;
2*)
build_216_14
;;
3*)
build_latest
;;
all)
build_216_98
build_216_14
build_latest
pack
;;
*)
echo '- default -'
build_latest
;;
esac

493
platform/frt/sdl2_adapter.h Normal file
View File

@ -0,0 +1,493 @@
// sdl2_adapter.h
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
/*
KNOWN ISSUES:
Unicode
Keyboard/Text SDL2 events don't map very well to Godot input events.
If a SDL2 keypress event might need to be "translated", that event is saved
and passed to Godot only when a translation is received.
This is incomplete and likely to be a source of bugs. Ctrl+... combinations
for example don't seem to generate a translation. Multiple keypresses
are also going to have a wrong unicode traslation.
Still, this implementation seems a good compromise: simple enough,
yet functional enough.
The 2D platformer feels responsive (even when adding WASD input mappings
and pressing multiple keys), and the editor is usable for basic code editing
(tested with US and IT keymaps).
*/
#include <SDL.h>
namespace frt {
void *(*get_proc_address)(const char *) = SDL_GL_GetProcAddress;
struct SampleProducer {
virtual void produce_samples(int n_of_frames, int32_t *frames) = 0;
virtual ~SampleProducer();
};
SampleProducer::~SampleProducer() {
}
void audio_callback(void *userdata, Uint8 *stream, int len);
class Audio {
private:
SampleProducer *producer_;
SDL_mutex *mutex_;
int32_t *samples_;
int n_of_samples_;
public:
Audio(SampleProducer *producer) : producer_(producer) {
mutex_ = 0;
}
bool init(int mix_rate, int samples) {
SDL_AudioSpec desired, obtained;
memset(&desired, 0, sizeof(desired));
desired.freq = mix_rate;
desired.format = AUDIO_S16;
desired.channels = 2;
desired.samples = samples;
desired.callback = audio_callback;
desired.userdata = this;
if (SDL_OpenAudio(&desired, &obtained))
return false;
mutex_ = SDL_CreateMutex();
n_of_samples_ = obtained.channels * obtained.samples;
samples_ = new int32_t[n_of_samples_];
return true;
}
void start() {
SDL_PauseAudio(SDL_FALSE);
}
void lock() {
SDL_LockMutex(mutex_);
}
void unlock() {
SDL_UnlockMutex(mutex_);
}
void finish() {
SDL_PauseAudio(SDL_TRUE);
SDL_LockAudio();
// calling of sdl2 callback not expected after pause+lock
SDL_DestroyMutex(mutex_);
mutex_ = 0;
delete[] samples_;
samples_ = 0;
SDL_UnlockAudio();
SDL_CloseAudio();
}
void fill_buffer(unsigned char *data, int length) {
int n_of_samples = length / sizeof(int16_t);
if (n_of_samples > n_of_samples_) // just in case, it shouldn't happen
n_of_samples = n_of_samples_;
const int channels = 2;
SDL_LockMutex(mutex_);
producer_->produce_samples(n_of_samples / channels, samples_);
SDL_UnlockMutex(mutex_);
int16_t *data16 = (int16_t *)data; // assume alignment is fine
for (int i = 0; i < n_of_samples; i++)
data16[i] = samples_[i] >> 16;
}
};
void audio_callback(void *userdata, Uint8 *stream, int len) {
Audio *audio = (Audio *)userdata;
audio->fill_buffer(stream, len);
}
struct ivec2 {
int x;
int y;
};
enum HatMask {
HatUp = 1,
HatRight = 2,
HatDown = 4,
HatLeft = 8
};
enum MouseButton {
ButtonLeft = 1,
ButtonRight = 2,
ButtonMiddle = 3,
WheelUp = 4,
WheelDown = 5
};
enum MouseMode {
MouseVisible,
MouseHidden,
MouseCaptured
};
struct EventHandler {
virtual ~EventHandler();
virtual void handle_resize_event(ivec2 size) = 0;
virtual void handle_key_event(int sdl2_code, int unicode, bool pressed) = 0;
virtual void handle_mouse_motion_event(ivec2 pos, ivec2 dpos) = 0;
virtual void handle_mouse_button_event(int button, bool pressed, bool doubleclick) = 0;
virtual void handle_js_status_event(int id, bool connected, const char *name, const char *guid) = 0;
virtual void handle_js_button_event(int id, int button, bool pressed) = 0;
virtual void handle_js_axis_event(int id, int axis, float value) = 0;
virtual void handle_js_hat_event(int id, int mask) = 0;
virtual void handle_quit_event() = 0;
};
EventHandler::~EventHandler() {
}
struct InputModifierState {
bool shift;
bool alt;
bool control;
bool meta;
InputModifierState() : shift(false), alt(false), control(false), meta(false) {}
};
enum GraphicsAPI {
API_OpenGL_ES2,
API_OpenGL_ES3
};
class OS_FRT {
private:
static const int MAX_JOYSTICKS = 16;
static const int REQUEST_UNICODE = -1;
SDL_Window *window_;
SDL_GLContext context_;
EventHandler *handler_;
InputModifierState st_;
MouseMode mouse_mode_;
SDL_KeyboardEvent key_ev_;
int key_unicode_;
SDL_Joystick *js_[MAX_JOYSTICKS];
bool exit_shortcuts_;
void resize_event(const SDL_Event &ev) {
ivec2 size;
SDL_GL_GetDrawableSize(window_, &size.x, &size.y);
handler_->handle_resize_event(size);
}
int utf8_to_unicode(const char *s) {
if ((s[0] & 0x80) == 0)
return s[0];
else if ((s[0] & 0xe0) == 0xc0)
return ((s[0] & 0x1f) << 6) | (s[1] & 0x3f);
else if ((s[0] & 0xf0) == 0xe0)
return ((s[0] & 0x0f) << 12) | ((s[1] & 0x3f) << 6) | (s[2] & 0x3f);
else
return 0;
}
void text_event(const SDL_TextInputEvent &text) {
if (key_unicode_ != REQUEST_UNICODE)
return;
key_unicode_ = utf8_to_unicode(text.text);
int sdl2_code = key_ev_.keysym.sym;
handler_->handle_key_event(sdl2_code, key_unicode_, true);
}
bool require_unicode(int c) {
return (c >= 0x20 && c < 0x80) || (c >= 0xa0 && c < 0xff);
}
void key_event(const SDL_KeyboardEvent &key) {
st_.shift = key.keysym.mod & KMOD_SHIFT;
st_.alt = key.keysym.mod & KMOD_ALT;
st_.control = key.keysym.mod & KMOD_CTRL;
st_.meta = key.keysym.mod & KMOD_GUI;
bool pressed = key.state == SDL_PRESSED;
int sdl2_code = key.keysym.sym;
if (exit_shortcuts_ && st_.alt && pressed && sdl2_code == SDLK_KP_ENTER)
fatal("exit_shortcut (alt+enter), disable by setting FRT_NO_EXIT_SHORTCUTS");
if (pressed && !key.repeat && require_unicode(sdl2_code)) {
key_ev_ = key;
key_unicode_ = REQUEST_UNICODE;
return;
}
handler_->handle_key_event(sdl2_code, key_unicode_, pressed);
if (!pressed)
key_unicode_ = 0;
}
void mouse_event(const SDL_Event &ev) {
int os_button;
if (ev.type == SDL_MOUSEMOTION) {
ivec2 pos = { ev.motion.x, ev.motion.y };
ivec2 dpos = { ev.motion.xrel, ev.motion.yrel };
handler_->handle_mouse_motion_event(pos, dpos);
} else if (ev.type == SDL_MOUSEWHEEL) {
if (ev.wheel.y > 0)
os_button = WheelUp;
else if (ev.wheel.y < 0)
os_button = WheelDown;
else
return;
handler_->handle_mouse_button_event(os_button, true, false);
handler_->handle_mouse_button_event(os_button, false, false);
} else { // SDL_MOUSEBUTTONUP, SDL_MOUSEBUTTONDOWN
switch (ev.button.button) {
case SDL_BUTTON_LEFT:
os_button = ButtonLeft;
break;
case SDL_BUTTON_MIDDLE:
os_button = ButtonMiddle;
break;
case SDL_BUTTON_RIGHT:
os_button = ButtonRight;
break;
default:
return;
}
handler_->handle_mouse_button_event(os_button, ev.button.state == SDL_PRESSED, ev.button.clicks > 1);
}
}
int get_js_id(int inst_id) {
SDL_Joystick *js = SDL_JoystickFromInstanceID(inst_id);
for (int id = 0; id < MAX_JOYSTICKS; id++)
if (js_[id] == js)
return id;
return -1;
}
void js_event(const SDL_Event &ev) {
int id;
switch (ev.type) {
case SDL_JOYAXISMOTION: {
if ((id = get_js_id(ev.jaxis.which)) < 0)
return;
int axis = ev.jaxis.axis;
float value = (float)ev.jaxis.value / 32768.0f;
handler_->handle_js_axis_event(id, axis, value);
} break;
case SDL_JOYHATMOTION: {
if ((id = get_js_id(ev.jhat.which)) < 0)
return;
if (ev.jhat.hat != 0)
return;
int mask = 0;
switch (ev.jhat.value) {
case SDL_HAT_LEFT:
mask = HatLeft;
break;
case SDL_HAT_LEFTUP:
mask = HatLeft | HatUp;
break;
case SDL_HAT_UP:
mask = HatUp;
break;
case SDL_HAT_RIGHTUP:
mask = HatRight | HatUp;
break;
case SDL_HAT_RIGHT:
mask = HatRight;
break;
case SDL_HAT_RIGHTDOWN:
mask = HatRight | HatDown;
break;
case SDL_HAT_DOWN:
mask = HatDown;
break;
case SDL_HAT_LEFTDOWN:
mask = HatLeft | HatDown;
break;
}
handler_->handle_js_hat_event(id, mask);
} break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP: {
if ((id = get_js_id(ev.jbutton.which)) < 0)
return;
int button = ev.jbutton.button;
bool pressed = ev.jbutton.state == SDL_PRESSED;
if (exit_shortcuts_ && button == 6 && pressed)
fatal("exit_shortcut (joystick button #6), disable by setting FRT_NO_EXIT_SHORTCUTS");
handler_->handle_js_button_event(id, button, pressed);
} break;
case SDL_JOYDEVICEADDED: {
id = ev.jdevice.which;
if (id >= MAX_JOYSTICKS)
return;
const char *name = SDL_JoystickNameForIndex(id);
char guid[64];
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(id), guid, sizeof(guid));
handler_->handle_js_status_event(id, true, name, guid);
js_[id] = SDL_JoystickOpen(id);
} break;
case SDL_JOYDEVICEREMOVED: {
if ((id = get_js_id(ev.jdevice.which)) < 0)
return;
SDL_JoystickClose(js_[id]);
js_[id] = 0;
handler_->handle_js_status_event(id, false, "", "");
} break;
}
}
public:
OS_FRT(EventHandler *handler) : handler_(handler) {
mouse_mode_ = MouseVisible;
key_unicode_ = 0;
memset(js_, 0, sizeof(js_));
exit_shortcuts_ = !getenv("FRT_NO_EXIT_SHORTCUTS");
}
void init(GraphicsAPI api, int width, int height, bool resizable, bool borderless, bool always_on_top) {
setenv("SDL_VIDEO_RPI_OPTIONS", "gravity=center,scale=letterbox,background=1", 0);
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
fatal("SDL_Init failed.");
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, api == API_OpenGL_ES2 ? 2 : 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
if (resizable)
flags |= SDL_WINDOW_RESIZABLE;
if (borderless)
flags |= SDL_WINDOW_BORDERLESS;
if (always_on_top)
flags |= SDL_WINDOW_ALWAYS_ON_TOP;
if (!(window_ = SDL_CreateWindow("frt2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags)))
fatal("SDL_CreateWindow failed.");
context_ = SDL_GL_CreateContext(window_);
SDL_GL_MakeCurrent(window_, context_);
}
void cleanup() {
SDL_DestroyWindow(window_);
SDL_Quit();
}
void make_current() {
SDL_GL_MakeCurrent(window_, context_);
}
void release_current() {
// TODO: add release
}
void swap_buffers() {
SDL_GL_SwapWindow(window_);
}
void set_use_vsync(bool enable) {
SDL_GL_SetSwapInterval(enable ? 1 : 0);
}
bool is_vsync_enabled() const {
return SDL_GL_GetSwapInterval() != 0;
}
void dispatch_events() {
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_WINDOWEVENT:
if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
resize_event(ev);
break;
case SDL_TEXTINPUT:
text_event(ev.text);
break;
case SDL_KEYUP:
case SDL_KEYDOWN:
key_event(ev.key);
break;
case SDL_MOUSEMOTION:
case SDL_MOUSEWHEEL:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
mouse_event(ev);
break;
case SDL_JOYAXISMOTION:
case SDL_JOYHATMOTION:
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
case SDL_JOYDEVICEADDED:
case SDL_JOYDEVICEREMOVED:
js_event(ev);
break;
case SDL_QUIT:
handler_->handle_quit_event();
break;
}
}
}
const InputModifierState *get_modifier_state() const {
return &st_;
}
void set_title(const char *title) {
SDL_SetWindowTitle(window_, title);
}
void set_pos(ivec2 pos) {
SDL_SetWindowPosition(window_, pos.x, pos.y);
}
ivec2 get_pos() const {
ivec2 pos;
SDL_GetWindowPosition(window_, &pos.x, &pos.y);
return pos;
}
void set_size(ivec2 size) {
SDL_SetWindowSize(window_, size.x, size.y);
}
ivec2 get_size() const {
ivec2 size;
SDL_GetWindowSize(window_, &size.x, &size.y);
return size;
}
void set_fullscreen(bool enable) {
SDL_SetWindowFullscreen(window_, enable ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); // TODO: hint
}
bool is_fullscreen() const {
return SDL_GetWindowFlags(window_) & SDL_WINDOW_FULLSCREEN_DESKTOP;
}
void set_always_on_top(bool enable) {
// NOT IMPLEMENTED
}
bool is_always_on_top() const {
return SDL_GetWindowFlags(window_) & SDL_WINDOW_ALWAYS_ON_TOP;
}
void set_resizable(bool enable) {
SDL_SetWindowResizable(window_, enable ? SDL_TRUE : SDL_FALSE);
}
bool is_resizable() const {
return SDL_GetWindowFlags(window_) & SDL_WINDOW_RESIZABLE;
}
void set_maximized(bool enable) {
if (enable)
SDL_MaximizeWindow(window_);
else
SDL_RestoreWindow(window_);
}
bool is_maximized() const {
return SDL_GetWindowFlags(window_) & SDL_WINDOW_MAXIMIZED;
}
void set_minimized(bool enable) {
if (enable)
SDL_MinimizeWindow(window_);
else
SDL_RestoreWindow(window_);
}
bool is_minimized() const {
return SDL_GetWindowFlags(window_) & SDL_WINDOW_MINIMIZED;
}
void set_mouse_mode(MouseMode mouse_mode) {
switch (mouse_mode) {
case MouseVisible:
SDL_CaptureMouse(SDL_FALSE);
SDL_ShowCursor(1);
break;
case MouseHidden:
SDL_CaptureMouse(SDL_FALSE);
SDL_ShowCursor(0);
break;
case MouseCaptured:
SDL_ShowCursor(0);
SDL_CaptureMouse(SDL_TRUE);
break;
}
mouse_mode_ = mouse_mode;
}
MouseMode get_mouse_mode() const {
return mouse_mode_;
}
};
} // namespace frt

View File

@ -0,0 +1,184 @@
// sdl2_godot_mapping.h
/*
FRT - A Godot platform targeting single board computers
Copyright (c) 2017-2022 Emanuele Fornara
SPDX-License-Identifier: MIT
*/
#include "core/version.h"
#define FRT_GODOT_VERSION ((((VERSION_MAJOR * 100) + VERSION_MINOR) * 100) + VERSION_PATCH)
#include "core/os/os.h"
#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "main/input_default.h"
namespace frt {
int map_mouse_os_button(int os_button) {
switch (os_button) {
case ButtonLeft:
return BUTTON_LEFT;
case ButtonRight:
return BUTTON_RIGHT;
case ButtonMiddle:
return BUTTON_MIDDLE;
case WheelUp:
return BUTTON_WHEEL_UP;
case WheelDown:
return BUTTON_WHEEL_DOWN;
default:
fatal("unexpected mouse button: %d", os_button);
}
}
OS::MouseMode map_mouse_os_mode(MouseMode os_mode) {
switch (os_mode) {
case MouseVisible:
return OS::MOUSE_MODE_VISIBLE;
case MouseHidden:
return OS::MOUSE_MODE_HIDDEN;
case MouseCaptured:
return OS::MOUSE_MODE_CAPTURED;
default:
fatal("unexpected mouse mode: %d", os_mode);
}
}
MouseMode map_mouse_mode(OS::MouseMode mode) {
switch (mode) {
case OS::MOUSE_MODE_VISIBLE:
return MouseVisible;
case OS::MOUSE_MODE_HIDDEN:
return MouseHidden;
case OS::MOUSE_MODE_CAPTURED:
#if FRT_GODOT_VERSION >= 30000
case OS::MOUSE_MODE_CONFINED:
#endif
return MouseCaptured;
default: // NOT REACHED
return MouseVisible;
}
}
int map_hat_os_mask(int os_mask) {
int mask = 0;
if (os_mask & HatUp)
mask |= InputDefault::HAT_MASK_UP;
if (os_mask & HatRight)
mask |= InputDefault::HAT_MASK_RIGHT;
if (os_mask & HatDown)
mask |= InputDefault::HAT_MASK_DOWN;
if (os_mask & HatLeft)
mask |= InputDefault::HAT_MASK_LEFT;
return mask;
}
struct KeyMap {
int sdl2_code;
int gd_code;
} keymap[] = {
{ SDLK_SPACE, ' ' },
{ SDLK_a, 'A' },
{ SDLK_b, 'B' },
{ SDLK_c, 'C' },
{ SDLK_d, 'D' },
{ SDLK_e, 'E' },
{ SDLK_f, 'F' },
{ SDLK_g, 'G' },
{ SDLK_h, 'H' },
{ SDLK_i, 'I' },
{ SDLK_j, 'J' },
{ SDLK_k, 'K' },
{ SDLK_l, 'L' },
{ SDLK_m, 'M' },
{ SDLK_n, 'N' },
{ SDLK_o, 'O' },
{ SDLK_p, 'P' },
{ SDLK_q, 'Q' },
{ SDLK_r, 'R' },
{ SDLK_s, 'S' },
{ SDLK_t, 'T' },
{ SDLK_u, 'U' },
{ SDLK_v, 'V' },
{ SDLK_w, 'W' },
{ SDLK_x, 'X' },
{ SDLK_y, 'Y' },
{ SDLK_z, 'Z' },
{ SDLK_0, '0' },
{ SDLK_1, '1' },
{ SDLK_2, '2' },
{ SDLK_3, '3' },
{ SDLK_4, '4' },
{ SDLK_5, '5' },
{ SDLK_6, '6' },
{ SDLK_7, '7' },
{ SDLK_8, '8' },
{ SDLK_9, '9' },
{ SDLK_F1, KEY_F1 },
{ SDLK_F2, KEY_F2 },
{ SDLK_F3, KEY_F3 },
{ SDLK_F4, KEY_F4 },
{ SDLK_F5, KEY_F5 },
{ SDLK_F6, KEY_F6 },
{ SDLK_F7, KEY_F7 },
{ SDLK_F8, KEY_F8 },
{ SDLK_F9, KEY_F9 },
{ SDLK_F10, KEY_F10 },
{ SDLK_F11, KEY_F11 },
{ SDLK_F12, KEY_F12 },
{ SDLK_UP, KEY_UP },
{ SDLK_DOWN, KEY_DOWN },
{ SDLK_LEFT, KEY_LEFT },
{ SDLK_RIGHT, KEY_RIGHT },
{ SDLK_TAB, KEY_TAB },
{ SDLK_BACKSPACE, KEY_BACKSPACE },
{ SDLK_INSERT, KEY_INSERT },
{ SDLK_DELETE, KEY_DELETE },
{ SDLK_HOME, KEY_HOME },
{ SDLK_END, KEY_END },
{ SDLK_PAGEUP, KEY_PAGEUP },
{ SDLK_PAGEDOWN, KEY_PAGEDOWN },
#if FRT_GODOT_VERSION >= 30000
{ SDLK_RETURN, KEY_ENTER },
#else
{ SDLK_RETURN, KEY_RETURN },
#endif
{ SDLK_ESCAPE, KEY_ESCAPE },
{ SDLK_LCTRL, KEY_CONTROL },
{ SDLK_RCTRL, KEY_CONTROL },
{ SDLK_LALT, KEY_ALT },
{ SDLK_RALT, KEY_ALT },
{ SDLK_LSHIFT, KEY_SHIFT },
{ SDLK_RSHIFT, KEY_SHIFT },
{ SDLK_LGUI, KEY_META },
{ SDLK_RGUI, KEY_META },
{ SDLK_KP_0, KEY_KP_0 },
{ SDLK_KP_1, KEY_KP_1 },
{ SDLK_KP_2, KEY_KP_2 },
{ SDLK_KP_3, KEY_KP_3 },
{ SDLK_KP_4, KEY_KP_4 },
{ SDLK_KP_5, KEY_KP_5 },
{ SDLK_KP_6, KEY_KP_6 },
{ SDLK_KP_7, KEY_KP_7 },
{ SDLK_KP_8, KEY_KP_8 },
{ SDLK_KP_9, KEY_KP_9 },
{ SDLK_KP_MULTIPLY, KEY_KP_MULTIPLY },
{ SDLK_KP_MINUS, KEY_KP_SUBTRACT },
{ SDLK_KP_PLUS, KEY_KP_ADD },
{ SDLK_KP_PERIOD, KEY_KP_PERIOD },
{ SDLK_KP_ENTER, KEY_KP_ENTER },
{ SDLK_KP_DIVIDE, KEY_KP_DIVIDE },
{ 0, 0 },
};
int map_key_sdl2_code(int sdl2_code) {
for (int i = 0; keymap[i].sdl2_code; i++) {
if (keymap[i].sdl2_code == sdl2_code)
return keymap[i].gd_code;
}
return 0;
}
} // namespace frt