start integrating milepost components into orca

This commit is contained in:
Martin Fouilleul 2023-04-17 10:56:38 +02:00
parent db7fe504bb
commit 4f90efbb22
12 changed files with 641 additions and 5 deletions

View File

@ -51,7 +51,7 @@ elif [ $target = orca ] ; then
./scripts/bindgen.py core ./src ./scripts/bindgen.py core ./src
./scripts/bindgen.py gles ./src ./scripts/bindgen.py gles ./src
./scripts/bindgen2.py canvas \ python3 ./scripts/bindgen2.py canvas \
src/canvas_api.json \ src/canvas_api.json \
--guest-stubs sdk/graphics.c \ --guest-stubs sdk/graphics.c \
--guest-include graphics.h \ --guest-include graphics.h \

@ -1 +1 @@
Subproject commit c347e105772072618d683214e76a21ca6229ac9a Subproject commit f36e144bc0fed66470aff0612098dba29c552604

Binary file not shown.

View File

@ -8,8 +8,8 @@ wasmFlags="--target=wasm32 \
-Wl,--allow-undefined \ -Wl,--allow-undefined \
-g \ -g \
-D__ORCA__ \ -D__ORCA__ \
-I ../../sdk -I ../../milepost/src" -I ../../sdk -I ../../milepost/src -I ../../milepost/src/util -I ../../milepost/src/platform"
/usr/local/opt/llvm/bin/clang $wasmFlags -o ./module.wasm ../../sdk/graphics.c ../../sdk/orca.c main.c /usr/local/opt/llvm/bin/clang $wasmFlags -o ./module.wasm ../../sdk/graphics.c ../../sdk/orca.c src/main.c
#python3 ../../scripts/mkapp.py --orca-dir ../.. --name Pong --icon icon.png module.wasm python3 ../../scripts/mkapp.py --orca-dir ../.. --name Pong --icon icon.png module.wasm

201
scripts/bindgen2.py Normal file
View File

@ -0,0 +1,201 @@
#!/usr/bin/env python3
from argparse import ArgumentParser
import json
parser = ArgumentParser(prog='bindgen.py')
parser.add_argument('api')
parser.add_argument('spec')
parser.add_argument('-g', '--guest-stubs')
parser.add_argument('--guest-include')
parser.add_argument('--wasm3-bindings')
args = parser.parse_args()
apiName = args.api
spec = args.spec
guest_stubs_path = args.guest_stubs
if guest_stubs_path == None:
guest_stubs_path = 'bindgen_' + apiName + '_guest_stubs.c'
wasm3_bindings_path = args.wasm3_bindings
if wasm3_bindings_path == None:
wasm3_bindings_path = 'bindgen_' + apiName + '_wasm3_bindings.c'
host_bindings = open(wasm3_bindings_path, 'w')
guest_bindings = None
specFile = open(spec, 'r')
data = json.load(specFile)
def needs_arg_ptr_stub(decl):
res = (decl['ret']['tag'] == 'S')
for arg in decl['args']:
if arg['type']['tag'] == 'S':
res = True
return(res)
for decl in data:
if needs_arg_ptr_stub(decl):
guest_bindings = open(guest_stubs_path, 'w')
if args.guest_include != None:
s = '#include"' + args.guest_include + '"\n\n'
print(s, file=guest_bindings)
break
for decl in data:
name = decl['name']
cname = decl.get('cname', name)
if needs_arg_ptr_stub(decl):
argPtrStubName = name + '_argptr_stub'
# pointer arg stub declaration
s = ''
if decl['ret']['tag'] == 'S':
s += 'void'
else:
s += decl['ret']['name']
s += ' ' + argPtrStubName + '('
if decl['ret']['tag'] == 'S':
s += decl['ret']['name'] + '* __retArg'
if len(decl['args']) > 0:
s += ', '
for i, arg in enumerate(decl['args']):
s += arg['type']['name']
if arg['type']['tag'] == 'S':
s += '*'
s += ' ' + arg['name']
if i+1 < len(decl['args']):
s += ', '
s += ');\n\n'
# forward function to pointer arg stub declaration
s += decl['ret']['name'] + ' ' + name + '('
for i, arg in enumerate(decl['args']):
s += arg['type']['name'] + ' ' + arg['name']
if i+1 < len(decl['args']):
s += ', '
s += ')\n'
s += '{\n'
s += '\t'
if decl['ret']['tag'] == 'S':
s += decl['ret']['name'] + ' __ret;\n\t'
elif decl['ret']['tag'] != 'v':
s += decl['ret']['name']
s += ' __ret = '
s += argPtrStubName + '('
if decl['ret']['tag'] == 'S':
s += '&__ret'
if len(decl['args']) > 0:
s += ', '
for i, arg in enumerate(decl['args']):
if arg['type']['tag'] == 'S':
s += '&'
s += arg['name']
if i+1 < len(decl['args']):
s += ', '
s += ');\n'
if decl['ret']['tag'] != 'v':
s += '\treturn(__ret);\n'
s += '}\n\n'
print(s, file=guest_bindings)
# host-side stub
s = 'const void* ' + cname + '_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t* _sp, void* _mem)'
gen_stub = decl.get('gen_stub', True)
if gen_stub == False:
s += ';\n\n'
else:
s += '\n{\n\t'
retTag = decl['ret']['tag']
if retTag == 'i':
s += '*((i32*)&_sp[0]) = '
elif retTag == 'I':
s += '*((i64*)&_sp[0]) = '
elif retTag == 'f':
s += '*((f32*)&_sp[0]) = '
elif retTag == 'd':
s += '*((f64*)&_sp[0]) = '
elif retTag == 'S':
retTypeName = decl['ret']['name']
retTypeCName = decl['ret'].get('cname', retTypeName)
s += '*(' + retTypeCName + '*)((char*)_mem + *(i32*)&_sp[0]) = '
s += cname + '('
firstArgIndex = 0
if retTag != 'v':
firstArgIndex = 1
for i, arg in enumerate(decl['args']):
typeName = arg['type']['name']
typeCName = arg['type'].get('cname', typeName)
argTag = arg['type']['tag']
if argTag == 'i':
s += '*(i32*)&_sp[' + str(firstArgIndex + i) + ']'
elif argTag == 'I':
s += '*(i64*)&_sp[' + str(firstArgIndex + i) + ']'
elif argTag == 'f':
s += '*(f32*)&_sp[' + str(firstArgIndex + i) + ']'
elif argTag == 'd':
s += '*(f64*)&_sp[' + str(firstArgIndex + i) + ']'
elif argTag == 'p':
s += '(void*)((char*)_mem + *(i32*)&_sp[' + str(firstArgIndex + i) + '])'
elif argTag == 'S':
s += '*(' + typeCName + '*)((char*)_mem + *(i32*)&_sp[' + str(firstArgIndex + i) + '])'
else:
print('unrecognized type ' + c + ' in procedure signature\n')
break
if i+1 < len(decl['args']):
s += ', '
s += ');\n\treturn(0);\n}\n\n'
print(s, file=host_bindings)
# link function
s = 'int bindgen_link_' + apiName + '_api(IM3Module module)\n{\n\t'
s += 'M3Result res;\n'
for decl in data:
name = decl['name']
cname = decl.get('cname', name)
if needs_arg_ptr_stub(decl):
name = name + '_argptr_stub'
m3Sig = ''
if decl['ret']['tag'] == 'S':
m3Sig += 'v'
else:
m3Sig += decl['ret']['tag']
m3Sig += '('
if decl['ret']['tag'] == 'S':
m3Sig += 'i'
for arg in decl['args']:
tag = arg['type']['tag']
if tag == 'p' or tag == 'S':
tag = 'i'
m3Sig += tag
m3Sig += ')'
s += '\tres = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3Sig + '", ' + cname + '_stub);\n'
s += '\tif(res != m3Err_none && res != m3Err_functionLookupFailed) { LOG_ERROR("error: %s\\n", res); return(-1); }\n\n'
s += '\treturn(0);\n}\n'
print(s, file=host_bindings)

45
sdk/graphics.c Normal file
View File

@ -0,0 +1,45 @@
#include"graphics.h"
void g_set_color_argptr_stub(g_color* color);
void g_set_color(g_color color)
{
g_set_color_argptr_stub(&color);
}
void g_matrix_push_argptr_stub(g_mat2x3* m);
void g_matrix_push(g_mat2x3 m)
{
g_matrix_push_argptr_stub(&m);
}
void g_font_create_default_argptr_stub(g_font* __retArg);
g_font g_font_create_default()
{
g_font __ret;
g_font_create_default_argptr_stub(&__ret);
return(__ret);
}
void g_set_font_argptr_stub(g_font* font);
void g_set_font(g_font font)
{
g_set_font_argptr_stub(&font);
}
void g_text_outlines_argptr_stub(str8* text);
void g_text_outlines(str8 text)
{
g_text_outlines_argptr_stub(&text);
}

222
sdk/graphics.h Normal file
View File

@ -0,0 +1,222 @@
//*****************************************************************
//
// $file: graphics.h $
// $author: Martin Fouilleul $
// $date: 23/36/2015 $
// $revision: $
//
//*****************************************************************
#ifndef __GRAPHICS_H_
#define __GRAPHICS_H_
#include"typedefs.h"
typedef struct g_mat2x3
{
f32 m[6];
} g_mat2x3;
typedef struct g_color
{
union
{
struct
{
f32 r;
f32 g;
f32 b;
f32 a;
};
f32 c[4];
};
} g_color;
typedef enum {G_JOINT_MITER = 0,
G_JOINT_BEVEL,
G_JOINT_NONE } g_joint_type;
typedef enum {G_CAP_NONE = 0,
G_CAP_SQUARE } g_cap_type;
typedef struct g_font { u64 h; } g_font;
typedef struct g_font_extents
{
f32 ascent; // the extent above the baseline (by convention a positive value extends above the baseline)
f32 descent; // the extent below the baseline (by convention, positive value extends below the baseline)
f32 leading; // spacing between one row's descent and the next row's ascent
f32 xHeight; // height of the lower case letter 'x'
f32 capHeight; // height of the upper case letter 'M'
f32 width; // maximum width of the font
} g_font_extents;
typedef struct g_text_extents
{
f32 xBearing;
f32 yBearing;
f32 width;
f32 height;
f32 xAdvance;
f32 yAdvance;
} g_text_extents;
//------------------------------------------------------------------------------------------
//NOTE(martin): fonts
//------------------------------------------------------------------------------------------
g_font g_font_nil();
g_font g_font_create_default();
//g_font g_font_create_from_memory(u32 size, byte* buffer, u32 rangeCount, unicode_range* ranges);
void g_font_destroy(g_font font);
//NOTE(martin): the following int valued functions return -1 if font is invalid or codepoint is not present in font//
//TODO(martin): add enum error codes
/*
g_font_extents g_font_get_extents(g_font font);
g_font_extents g_font_get_scaled_extents(g_font font, f32 emSize);
f32 g_font_get_scale_for_em_pixels(g_font font, f32 emSize);
//NOTE(martin): if you need to process more than one codepoint, first convert your codepoints to glyph indices, then use the
// glyph index versions of the functions, which can take an array of glyph indices.
str32 g_font_get_glyph_indices(g_font font, str32 codePoints, str32 backing);
str32 g_font_push_glyph_indices(g_font font, mem_arena* arena, str32 codePoints);
u32 g_font_get_glyph_index(g_font font, utf32 codePoint);
int g_font_get_codepoint_extents(g_font font, utf32 codePoint, g_text_extents* outExtents);
int g_font_get_glyph_extents(g_font font, str32 glyphIndices, g_text_extents* outExtents);
mp_rect g_text_bounding_box_utf32(g_font font, f32 fontSize, str32 text);
mp_rect g_text_bounding_box(g_font font, f32 fontSize, str8 text);
*/
//------------------------------------------------------------------------------------------
//NOTE(martin): images
//------------------------------------------------------------------------------------------
/*
g_image g_image_nil();
bool g_image_is_nil(g_image a);
g_image g_image_create(u32 width, u32 height);
g_image g_image_create_from_rgba8(u32 width, u32 height, u8* pixels);
g_image g_image_create_from_data(str8 data, bool flip);
g_image g_image_create_from_file(str8 path, bool flip);
void g_image_destroy(g_image image);
void g_image_upload_region_rgba8(g_image image, mp_rect region, u8* pixels);
vec2 g_image_size(g_image image);
*/
//------------------------------------------------------------------------------------------
//NOTE(martin): atlasing
//------------------------------------------------------------------------------------------
/*
//NOTE: rectangle allocator
typedef struct g_rect_atlas g_rect_atlas;
g_rect_atlas* g_rect_atlas_create(mem_arena* arena, i32 width, i32 height);
mp_rect g_rect_atlas_alloc(g_rect_atlas* atlas, i32 width, i32 height);
void g_rect_atlas_recycle(g_rect_atlas* atlas, mp_rect rect);
//NOTE: image atlas helpers
typedef struct g_image_region
{
g_image image;
mp_rect rect;
} g_image_region;
g_image_region g_image_atlas_alloc_from_rgba8(g_rect_atlas* atlas, g_image backingImage, u32 width, u32 height, u8* pixels);
g_image_region g_image_atlas_alloc_from_data(g_rect_atlas* atlas, g_image backingImage, str8 data, bool flip);
g_image_region g_image_atlas_alloc_from_file(g_rect_atlas* atlas, g_image backingImage, str8 path, bool flip);
void g_image_atlas_recycle(g_rect_atlas* atlas, g_image_region imageRgn);
*/
//------------------------------------------------------------------------------------------
//NOTE(martin): transform, viewport and clipping
//------------------------------------------------------------------------------------------
void g_viewport(mp_rect viewPort);
void g_matrix_push(g_mat2x3 matrix);
void g_matrix_pop();
void g_clip_push(f32 x, f32 y, f32 w, f32 h);
void g_clip_pop();
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics attributes setting/getting
//------------------------------------------------------------------------------------------
void g_set_color(g_color color);
void g_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
void g_set_width(f32 width);
void g_set_tolerance(f32 tolerance);
void g_set_joint(g_joint_type joint);
void g_set_max_joint_excursion(f32 maxJointExcursion);
void g_set_cap(g_cap_type cap);
void g_set_font(g_font font);
void g_set_font_size(f32 size);
void g_set_text_flip(bool flip);
/*
void g_set_image(g_image image);
void g_set_image_source_region(mp_rect region);
*/
g_color g_get_color();
f32 g_get_width();
f32 g_get_tolerance();
g_joint_type g_get_joint();
f32 g_get_max_joint_excursion();
g_cap_type g_get_cap();
g_font g_get_font();
f32 g_get_font_size();
bool g_get_text_flip();
//------------------------------------------------------------------------------------------
//NOTE(martin): path construction
//------------------------------------------------------------------------------------------
vec2 g_get_position();
void g_move_to(f32 x, f32 y);
void g_line_to(f32 x, f32 y);
void g_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
void g_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
void g_close_path();
/*
mp_rect g_glyph_outlines(str32 glyphIndices);
void g_codepoints_outlines(str32 string);
*/
typedef struct str8
{
u64 len;
char* ptr;
} str8;
void g_text_outlines(str8 string);
//------------------------------------------------------------------------------------------
//NOTE(martin): clear/fill/stroke
//------------------------------------------------------------------------------------------
void g_clear();
void g_fill();
void g_stroke();
//------------------------------------------------------------------------------------------
//NOTE(martin): simple shapes helpers
//------------------------------------------------------------------------------------------
void g_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
void g_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
void g_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
void g_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
void g_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
void g_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
void g_circle_fill(f32 x, f32 y, f32 r);
void g_circle_stroke(f32 x, f32 y, f32 r);
void g_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
//NOTE: image helpers
/*
void g_image_draw(g_image image, mp_rect rect);
void g_image_draw_region(g_image image, mp_rect srcRegion, mp_rect dstRegion);
*/
#endif //__GRAPHICS_H_

9
sdk/orca.c Normal file
View File

@ -0,0 +1,9 @@
/************************************************************//**
*
* @file: orca.c
* @author: Martin Fouilleul
* @date: 13/04/2023
*
*****************************************************************/
//#include"util/memory.c"

14
sdk/orca.h Normal file
View File

@ -0,0 +1,14 @@
/************************************************************//**
*
* @file: orca.h
* @author: Martin Fouilleul
* @date: 13/04/2023
*
*****************************************************************/
#ifndef __ORCA_H_
#define __ORCA_H_
#include"util/typedefs.h"
#include"util/lists.h"
#endif //__ORCA_H_

124
src/canvas_api.json Normal file
View File

@ -0,0 +1,124 @@
[
{
"name": "g_clear",
"cname": "mg_clear",
"ret": {"name": "void", "tag": "v"},
"args": []
},
{
"name": "g_set_color_rgba",
"cname": "mg_set_color_rgba",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "r",
"type": {"name": "float", "tag": "f"}},
{"name": "g",
"type": {"name": "float", "tag": "f"}},
{"name": "b",
"type": {"name": "float", "tag": "f"}},
{"name": "a",
"type": {"name": "float", "tag": "f"}}]
},
{
"name": "g_set_color",
"cname": "mg_set_color",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "color",
"type": {"name": "g_color", "cname": "mg_color", "tag": "S"}}]
},
{
"name": "g_matrix_push",
"cname": "mg_matrix_push",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "m",
"type": {"name": "g_mat2x3", "cname": "mg_mat2x3", "tag": "S"}}]
},
{
"name": "g_matrix_pop",
"cname": "mg_matrix_pop",
"ret": {"name": "void", "tag": "v"},
"args": []
},
{
"name": "g_circle_fill",
"cname": "mg_circle_fill",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "x",
"type": {"name": "float", "tag": "f"}},
{"name": "y",
"type": {"name": "float", "tag": "f"}},
{"name": "r",
"type": {"name": "float", "tag": "f"}}]
},
{
"name": "g_rectangle_fill",
"cname": "mg_rectangle_fill",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "x",
"type": {"name": "float", "tag": "f"}},
{"name": "y",
"type": {"name": "float", "tag": "f"}},
{"name": "w",
"type": {"name": "float", "tag": "f"}},
{"name": "h",
"type": {"name": "float", "tag": "f"}}]
},
{
"name": "g_font_create_default",
"cname": "mg_font_create_default",
"ret": {"name": "g_font", "cname": "mg_font", "tag": "S"},
"args": []
},
{
"name": "g_set_font",
"cname": "mg_set_font",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "font",
"type": {"name": "g_font", "cname": "mg_font" , "tag": "S"}}]
},
{
"name": "g_set_font_size",
"cname": "mg_set_font_size",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "size",
"type": {"name": "float", "cname": "float" , "tag": "f"}}]
},
{
"gen_stub": false,
"name": "g_text_outlines",
"cname": "mg_text_outlines",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "text",
"type": {"name": "str8", "cname": "str8" , "tag": "S"}}]
},
{
"name": "g_fill",
"cname": "mg_fill",
"ret": {"name": "void", "tag": "v"},
"args": []
},
{
"name": "g_move_to",
"cname": "mg_move_to",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "x",
"type": {"name": "f32", "tag":"f"}},
{"name": "y",
"type": {"name": "f32", "tag":"f"}}]
},
{
"name": "g_set_text_flip",
"cname": "mg_set_text_flip",
"ret": {"name": "void", "tag": "v"},
"args": [
{"name": "flip",
"type": {"name": "bool", "tag":"i"}}]
}]

21
src/canvas_api_bind.c Normal file
View File

@ -0,0 +1,21 @@
#include"canvas_api_bind_gen.c"
typedef struct wasm_str8
{
i64 len;
i32 offset;
} wasm_str8;
const void* mg_text_outlines_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t* _sp, void* _mem)
{
wasm_str8 wasmStr = *(wasm_str8*)((char*)_mem + *(i32*)&_sp[0]);
/////////////////////////////////////////////////////////////////////
//TODO: bound checks
str8 str = {.len = wasmStr.len,
.ptr = (char*)_mem + wasmStr.offset};
/////////////////////////////////////////////////////////////////////
mg_text_outlines(str);
return(0);
}