[osx, gles] expose gles surface and gles API to orca apps. git statusWARNING: No memory checks whatsoever for nowgit status
This commit is contained in:
parent
a658e714c3
commit
754dfc2f0e
|
@ -16,10 +16,13 @@ bin/*
|
|||
|
||||
Debug/*
|
||||
|
||||
scripts/__pycache__
|
||||
src/gles_api.json
|
||||
src/bindgen_core_api.c
|
||||
src/bindgen_gles_api.c
|
||||
sdk/io_stubs.c
|
||||
sdk/orca_surface.c
|
||||
sdk/gl31.h
|
||||
*bind_gen.c
|
||||
|
||||
.vscode/settings.json
|
||||
|
|
4
build.sh
4
build.sh
|
@ -57,6 +57,10 @@ elif [ $target = orca ] ; then
|
|||
LIBS="-Lbin -lmilepost -lwasm3"
|
||||
FLAGS="-g -DLOG_COMPILE_DEBUG -mmacos-version-min=10.15.4 -maes"
|
||||
|
||||
# generate gl31 header and json spec
|
||||
|
||||
python3 ./scripts/gles_gen.py --spec milepost/ext/gl.xml --header sdk/gl31.h --json src/gles_api.json
|
||||
|
||||
# generate wasm3 api bindings
|
||||
|
||||
python3 ./scripts/bindgen.py core \
|
||||
|
|
2
milepost
2
milepost
|
@ -1 +1 @@
|
|||
Subproject commit 6221370aa0e8c520ebde179a1e715a8ed2e28611
|
||||
Subproject commit 12fa7be765b139f41e45aa802b3e1558ba704fb9
|
|
@ -0,0 +1,3 @@
|
|||
Triangle
|
||||
profile.dtrace
|
||||
profile.spall
|
|
@ -0,0 +1,17 @@
|
|||
@echo off
|
||||
|
||||
:: compile wasm module
|
||||
set wasmFlags=--target=wasm32^
|
||||
--no-standard-libraries ^
|
||||
-fno-builtin ^
|
||||
-Wl,--no-entry ^
|
||||
-Wl,--export-dynamic ^
|
||||
-g ^
|
||||
-O2 ^
|
||||
-mbulk-memory ^
|
||||
-D__ORCA__ ^
|
||||
-isystem ..\..\cstdlib\include -I ..\..\sdk -I..\..\milepost\ext -I ..\..\milepost -I ..\..\milepost\src
|
||||
|
||||
clang %wasmFlags% -o .\module.wasm ..\..\sdk\orca.c ..\..\cstdlib\src\*.c src\main.c
|
||||
|
||||
python3 ..\..\scripts\mkapp.py --orca-dir ..\.. --name Triangle --resource-dir data module.wasm
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -x /usr/local/opt/llvm/bin/clang ]]; then
|
||||
CLANG=/usr/local/opt/llvm/bin/clang
|
||||
elif [[ -x /opt/homebrew/opt/llvm/bin/clang ]]; then
|
||||
CLANG=/opt/homebrew/opt/llvm/bin/clang
|
||||
else
|
||||
echo "Could not find Homebrew clang; this script will probably not work."
|
||||
CLANG=clang
|
||||
fi
|
||||
|
||||
STDLIB_DIR=../../cstdlib
|
||||
ORCA_SDK_DIR=../../sdk
|
||||
MILEPOST_DIR=../../milepost
|
||||
|
||||
wasmFlags="--target=wasm32 \
|
||||
--no-standard-libraries \
|
||||
-fno-builtin \
|
||||
-Wl,--no-entry \
|
||||
-Wl,--export-dynamic \
|
||||
-g \
|
||||
-O2 \
|
||||
-mbulk-memory \
|
||||
-D__ORCA__ \
|
||||
-I $STDLIB_DIR/include \
|
||||
-I $ORCA_SDK_DIR \
|
||||
-I $MILEPOST_DIR/ext -I $MILEPOST_DIR -I $MILEPOST_DIR/src"
|
||||
|
||||
$CLANG $wasmFlags -o ./module.wasm ../../sdk/orca.c ../../cstdlib/src/*.c src/main.c
|
||||
|
||||
python3 ../../scripts/mkapp.py --orca-dir ../.. --name Triangle --resource-dir data module.wasm
|
|
@ -0,0 +1,96 @@
|
|||
#include <keys.h>
|
||||
#include <graphics.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <orca.h>
|
||||
|
||||
vec2 frameSize = {100, 100};
|
||||
|
||||
mg_surface surface;
|
||||
|
||||
unsigned int program;
|
||||
|
||||
const char* vshaderSource =
|
||||
"attribute vec4 vPosition;\n"
|
||||
"uniform mat4 transform;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = transform*vPosition;\n"
|
||||
"}\n";
|
||||
|
||||
const char* fshaderSource =
|
||||
"precision mediump float;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
void compile_shader(GLuint shader, const char* source)
|
||||
{
|
||||
glShaderSource(shader, 1, &source, 0);
|
||||
glCompileShader(shader);
|
||||
|
||||
int err = glGetError();
|
||||
if(err)
|
||||
{
|
||||
log_info("gl error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
{
|
||||
surface = mg_surface_gles();
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
|
||||
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
program = glCreateProgram();
|
||||
|
||||
compile_shader(vshader, vshaderSource);
|
||||
compile_shader(fshader, fshaderSource);
|
||||
|
||||
glAttachShader(program, vshader);
|
||||
glAttachShader(program, fshader);
|
||||
glLinkProgram(program);
|
||||
glUseProgram(program);
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
|
||||
{
|
||||
log_info("frame resize %u, %u", width, height);
|
||||
frameSize.x = width;
|
||||
frameSize.y = height;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameRefresh(void)
|
||||
{
|
||||
f32 aspect = frameSize.x/frameSize.y;
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
glClearColor(0, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
static float alpha = 0;
|
||||
|
||||
glViewport(0, 0, frameSize.x * 2, frameSize.y * 2);
|
||||
|
||||
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0,
|
||||
-sinf(alpha)/aspect, cosf(alpha), 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1};
|
||||
alpha += 2*M_PI/120;
|
||||
|
||||
glUniformMatrix4fv(0, 1, false, matrix);
|
||||
|
||||
GLfloat vertices[] = {
|
||||
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0};
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||
glEnableVertexAttribArray(0);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
mg_surface_present(surface);
|
||||
}
|
|
@ -45,9 +45,6 @@ mg_image ballImage;
|
|||
mg_image paddleImage;
|
||||
mg_font pongFont;
|
||||
|
||||
// TODO(ben): Why is this here? Why isn't it forward-declared by some header?
|
||||
mg_surface mg_surface_main(void);
|
||||
|
||||
f32 lerp(f32 a, f32 b, f32 t);
|
||||
mp_rect blockRect(int i);
|
||||
int checkCollision(mp_rect block);
|
||||
|
@ -69,7 +66,7 @@ str8 loadFile(mem_arena* arena, str8 filename) {
|
|||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
{
|
||||
surface = mg_surface_main();
|
||||
surface = mg_surface_canvas();
|
||||
canvas = mg_canvas_create();
|
||||
|
||||
waterImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/underwater.jpg")), false);
|
||||
|
|
|
@ -12,12 +12,10 @@ mg_font font;
|
|||
ui_context ui;
|
||||
mem_arena textArena = {0};
|
||||
|
||||
mg_surface mg_surface_main(void);
|
||||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
{
|
||||
//TODO create surface for main window
|
||||
surface = mg_surface_main();
|
||||
surface = mg_surface_canvas();
|
||||
canvas = mg_canvas_create();
|
||||
ui_init(&ui);
|
||||
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
from reg_modified import *
|
||||
import xml.etree.ElementTree as et
|
||||
from argparse import ArgumentParser
|
||||
|
||||
def gen_gles_header(spec, filename):
|
||||
# Generates the GLES header, wrapping gl functions
|
||||
# prototypes in ORCA_IMPORT() macro
|
||||
|
||||
gles2through31Pat = '2\.[0-9]|3\.[01]'
|
||||
allVersions = '.*'
|
||||
|
||||
genOpts = CGeneratorOptions(
|
||||
filename=filename,
|
||||
apiname='gles2',
|
||||
profile='common',
|
||||
versions=gles2through31Pat,
|
||||
emitversions=allVersions,
|
||||
protectProto=False,
|
||||
procMacro='ORCA_IMPORT')
|
||||
|
||||
reg = Registry()
|
||||
tree = et.parse(spec)
|
||||
reg.loadElementTree(tree)
|
||||
|
||||
gen = COutputGenerator()
|
||||
reg.setGenerator(gen)
|
||||
reg.apiGen(genOpts)
|
||||
|
||||
|
||||
def get_bindgen_tag_for_type(typeName):
|
||||
typeToTags = {
|
||||
"void": "v",
|
||||
|
||||
"GLenum": "i",
|
||||
"GLbitfield": "i",
|
||||
|
||||
"GLboolean": "i",
|
||||
"GLbyte": "i",
|
||||
"GLubyte": "i",
|
||||
"GLchar": "i",
|
||||
|
||||
"GLshort": "i",
|
||||
"GLushort": "i",
|
||||
"GLhalf": "i",
|
||||
"GLhalfARB": "i",
|
||||
|
||||
"GLuint": "i",
|
||||
"GLint": "i",
|
||||
"GLclampx": "i",
|
||||
"GLsizei": "i",
|
||||
"GLfixed": "i",
|
||||
|
||||
"GLuint64": "I",
|
||||
"GLint64": "I",
|
||||
"GLintptr": "I",
|
||||
"GLsizeiptr": "I",
|
||||
|
||||
"GLfloat": "f",
|
||||
"GLclampf": "f",
|
||||
|
||||
"GLdouble": "F",
|
||||
"GLclampd": "F",
|
||||
|
||||
"GLsync": "p"
|
||||
}
|
||||
|
||||
if typeName[len(typeName)-1] == '*':
|
||||
return "p"
|
||||
else:
|
||||
tag = typeToTags.get(typeName)
|
||||
return tag
|
||||
|
||||
def gen_gles_bindgen_json(spec, filename):
|
||||
|
||||
# Gather gles 3.1 required functions
|
||||
tree = et.parse(spec)
|
||||
api = []
|
||||
|
||||
for feature in tree.iterfind('feature[@api="gles2"]'):
|
||||
if float(feature.get('number')) > 3.1:
|
||||
break
|
||||
|
||||
for require in feature.iter('require'):
|
||||
if require.get('profile') == 'compatibility':
|
||||
continue
|
||||
for command in require.iter('command'):
|
||||
api.append(command.get('name'))
|
||||
|
||||
for remove in feature.iter('remove'):
|
||||
for command in remove.iter('command'):
|
||||
api.remove(command.get('name'))
|
||||
|
||||
# put all GL commands in a dict
|
||||
commands = dict()
|
||||
commandsSpec = tree.find('./commands')
|
||||
for command in commandsSpec.iter('command'):
|
||||
name = command.find('proto/name')
|
||||
commands[name.text] = command
|
||||
|
||||
# TODO: Generate json descriptions for commands in api
|
||||
|
||||
manualBind = [
|
||||
"glShaderSource"]
|
||||
|
||||
json = '[\n'
|
||||
for name in api:
|
||||
if name in manualBind:
|
||||
continue
|
||||
|
||||
command = commands.get(name)
|
||||
if command == None:
|
||||
print("Couldn't find definition for required command '" + name + "'")
|
||||
exit(-1)
|
||||
|
||||
proto = command.find("proto")
|
||||
ptype = proto.find("ptype")
|
||||
|
||||
retType = ''
|
||||
if proto.text != None:
|
||||
retType += proto.text
|
||||
|
||||
if ptype != None:
|
||||
if ptype.text != None:
|
||||
retType += ptype.text
|
||||
if ptype.tail != None:
|
||||
retType += ptype.tail
|
||||
|
||||
retType = retType.strip()
|
||||
|
||||
retTag = get_bindgen_tag_for_type(retType)
|
||||
if retTag == None:
|
||||
print("Couldn't find tag for GL type '" + retType + "'")
|
||||
exit(-1)
|
||||
|
||||
entry = '{\n\t"name": "' + name + '",\n'
|
||||
entry += '\t"cname": "' + name + '",\n'
|
||||
entry += '\t"ret": { "name": "' + retType + '", "tag": "' + retTag + '"},\n'
|
||||
|
||||
entry += '\t"args": [ '
|
||||
|
||||
# iterate through params
|
||||
for param in command.iter('param'):
|
||||
|
||||
argNode = param.find('name')
|
||||
argName = argNode.text
|
||||
|
||||
typeNode = param.find('ptype')
|
||||
|
||||
typeName = ''
|
||||
|
||||
if param.text != None:
|
||||
typeName += param.text
|
||||
|
||||
if typeNode != None:
|
||||
if typeNode.text != None:
|
||||
typeName += typeNode.text
|
||||
if typeNode.tail != None:
|
||||
typeName += typeNode.tail
|
||||
|
||||
typeName = typeName.strip()
|
||||
|
||||
typeTag = get_bindgen_tag_for_type(typeName)
|
||||
|
||||
if typeTag == None:
|
||||
print("Couldn't find tag for GL type '" + typeName + "' in function '"+ name +"'")
|
||||
exit(-1)
|
||||
|
||||
entry += '\n'
|
||||
entry += '\t\t{"name": "'+ argName +'",\n'
|
||||
entry += '\t\t "type": {"name": "'+ typeName +'", "tag": "'+ typeTag +'"}'
|
||||
|
||||
if param.get('len') != None:
|
||||
lenString = param.get('len')
|
||||
tokens = lenString.split('*')
|
||||
|
||||
if lenString.startswith("COMPSIZE"):
|
||||
print("Warning: function " + name + ": parameter " + argName + " lenght uses COMPSIZE")
|
||||
else:
|
||||
entry += ',\n'
|
||||
entry += '\t\t "len": {'
|
||||
if len(tokens) == 2:
|
||||
if tokens[1].isnumeric() == False:
|
||||
print("Warning: function " + name + ": couldn't parse parameter '" + argName + "' lenght attribute")
|
||||
entry += '"count": "' + tokens[0] + '", "components": "'+ tokens[1] + '"'
|
||||
elif len(tokens) == 1:
|
||||
if tokens[0].isnumeric():
|
||||
entry += '"components":'+ tokens[0]
|
||||
else:
|
||||
entry += '"count": "'+ tokens[0] + '"'
|
||||
else:
|
||||
print("Warning: function " + name + ": couldn't parse parameter '" + argName + "' lenght attribute")
|
||||
|
||||
entry += '}'
|
||||
elif typeTag == "p":
|
||||
print("Warning: function " + name + ": parameter " + argName + " has no len attribute")
|
||||
|
||||
entry += '},'
|
||||
|
||||
entry = entry[:-1]
|
||||
entry += '\n\t]\n}'
|
||||
|
||||
json += entry
|
||||
json += ',\n'
|
||||
|
||||
json = json[:-2]
|
||||
json += '\n]'
|
||||
|
||||
# write json to jsonFile
|
||||
f = open(filename, 'w')
|
||||
f.write(json)
|
||||
f.close()
|
||||
|
||||
#----------------------------------------
|
||||
# driver
|
||||
#----------------------------------------
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-s", "--spec")
|
||||
parser.add_argument("--header")
|
||||
parser.add_argument("-j", "--json")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
glesHeader = args.header
|
||||
jsonFile = args.json
|
||||
|
||||
gen_gles_header(args.spec, glesHeader)
|
||||
gen_gles_bindgen_json(args.spec, jsonFile)
|
|
@ -137,6 +137,8 @@ def macos_make_app(args):
|
|||
<string>icon.icns</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>MetalCaptureEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
""".format(app_name=app_name, version=version, bundle_sig=bundle_sig, icon_file=icon_file)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,4 +25,9 @@
|
|||
#error "Orca apps can only be compiled with clang for now"
|
||||
#endif
|
||||
|
||||
#include"gl31.h"
|
||||
|
||||
mg_surface mg_surface_canvas();
|
||||
mg_surface mg_surface_gles();
|
||||
|
||||
#endif //__ORCA_H_
|
||||
|
|
|
@ -36,12 +36,6 @@
|
|||
{"name": "pixels",
|
||||
"type": {"name": "u8*", "tag": "p"}}]
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_main",
|
||||
"cname": "orca_surface_main",
|
||||
"ret": {"name": "mg_surface", "tag": "S"},
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_prepare",
|
||||
"cname": "mg_surface_prepare",
|
||||
|
@ -75,4 +69,17 @@
|
|||
"type": {"name": "u32", "tag": "i"}},
|
||||
{"name": "elements",
|
||||
"type": {"name": "mg_path_elt*", "tag": "p"}}]
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_canvas",
|
||||
"cname": "orca_surface_canvas",
|
||||
"ret": {"name": "mg_surface", "tag": "S"},
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_gles",
|
||||
"cname": "orca_surface_gles",
|
||||
"ret": {"name": "mg_surface", "tag": "S"},
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
|
|
4638
src/gles_api.json
4638
src/gles_api.json
File diff suppressed because it is too large
Load Diff
32
src/main.c
32
src/main.c
|
@ -170,11 +170,38 @@ void orca_log(log_level level,
|
|||
msg);
|
||||
}
|
||||
|
||||
mg_surface orca_surface_main(void)
|
||||
mg_surface orca_surface_canvas(void)
|
||||
{
|
||||
return(__orcaApp.surface);
|
||||
}
|
||||
|
||||
typedef struct orca_surface_create_data
|
||||
{
|
||||
mp_window window;
|
||||
mg_surface_api api;
|
||||
mg_surface surface;
|
||||
|
||||
} orca_surface_create_data;
|
||||
|
||||
i32 orca_surface_gles_callback(void* user)
|
||||
{
|
||||
orca_surface_create_data* data = (orca_surface_create_data*)user;
|
||||
data->surface = mg_surface_create_for_window(data->window, data->api);
|
||||
return(0);
|
||||
}
|
||||
|
||||
mg_surface orca_surface_gles(void)
|
||||
{
|
||||
orca_surface_create_data data = {
|
||||
.surface = mg_surface_nil(),
|
||||
.window = __orcaApp.window,
|
||||
.api = MG_GLES
|
||||
};
|
||||
|
||||
mp_dispatch_on_main_thread_sync(orca_surface_gles_callback, (void*)&data);
|
||||
return(data.surface);
|
||||
}
|
||||
|
||||
void orca_surface_render_commands(mg_surface surface,
|
||||
mg_color clearColor,
|
||||
u32 primitiveCount,
|
||||
|
@ -303,7 +330,7 @@ void orca_runtime_init(orca_runtime* runtime)
|
|||
#include"io_api_bind_gen.c"
|
||||
|
||||
#include"gles_api_bind_gen.c"
|
||||
#include"manual_gles_api.c"
|
||||
#include"gles_api_bind_manual.c"
|
||||
|
||||
i32 orca_runloop(void* user)
|
||||
{
|
||||
|
@ -765,6 +792,7 @@ int main(int argc, char** argv)
|
|||
app->canvas = mg_canvas_create();
|
||||
mg_surface_swap_interval(app->surface, 1);
|
||||
|
||||
|
||||
app->debugOverlay.show = false;
|
||||
app->debugOverlay.surface = mg_surface_create_for_window(app->window, MG_CANVAS);
|
||||
app->debugOverlay.canvas = mg_canvas_create();
|
||||
|
|
Loading…
Reference in New Issue