Merge branch 'main' of git.handmade.network:hmn/orca into ui-redesign

This commit is contained in:
Ilia Demianenko 2023-09-06 22:30:56 -07:00
commit 15bc29d703
70 changed files with 2647 additions and 1818 deletions

35
doc/cheatsheet_app.h Normal file
View File

@ -0,0 +1,35 @@
/************************************************************/ /**
*
* @file: cheatsheet_app.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Handlers (can be defined by your app to respond to events)
//----------------------------------------------------------------
void oc_on_init(void);
void oc_on_mouse_down(oc_mouse_button button);
void oc_on_mouse_up(oc_mouse_button button);
void oc_on_mouse_enter(void);
void oc_on_mouse_leave(void);
void oc_on_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY);
void oc_on_mouse_wheel(f32 deltaX, f32 deltaY);
void oc_on_key_down(oc_key_code key);
void oc_on_key_up(oc_key_code key);
void oc_on_frame_refresh(void);
void oc_on_resize(f32 width, f32 height);
void oc_on_raw_event(oc_event* event);
void oc_on_terminate(void);
//----------------------------------------------------------------
// Window
//----------------------------------------------------------------
void oc_window_set_title(oc_str8 title);
void oc_window_set_size(oc_vec2 size);
//----------------------------------------------------------------
// Quitting
//----------------------------------------------------------------
void oc_request_quit(void)

162
doc/cheatsheet_graphics.h Normal file
View File

@ -0,0 +1,162 @@
/************************************************************/ /**
*
* @file: cheatsheet_graphics.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//------------------------------------------------------------------------------------------
// graphics surface
//------------------------------------------------------------------------------------------
oc_surface oc_surface_nil(void);
bool oc_surface_is_nil(oc_surface surface);
oc_surface oc_surface_canvas();
oc_surface oc_surface_gles();
void oc_surface_destroy(oc_surface surface);
void oc_surface_select(oc_surface surface);
void oc_surface_present(oc_surface surface);
void oc_surface_deselect(void);
oc_vec2 oc_surface_get_size(oc_surface surface);
oc_vec2 oc_surface_contents_scaling(oc_surface surface);
void oc_surface_bring_to_front(oc_surface surface);
void oc_surface_send_to_back(oc_surface surface);
//------------------------------------------------------------------------------------------
// 2D canvas command buffer
//------------------------------------------------------------------------------------------
oc_canvas oc_canvas_nil(void);
bool oc_canvas_is_nil(oc_canvas canvas);
oc_canvas oc_canvas_create(void);
void oc_canvas_destroy(oc_canvas canvas);
oc_canvas oc_canvas_set_current(oc_canvas canvas);
void oc_render(oc_surface surface, oc_canvas canvas);
//------------------------------------------------------------------------------------------
// transform and clipping
//------------------------------------------------------------------------------------------
void oc_matrix_push(oc_mat2x3 matrix);
void oc_matrix_pop(void);
oc_mat2x3 oc_matrix_top();
void oc_clip_push(f32 x, f32 y, f32 w, f32 h);
void oc_clip_pop(void);
oc_rect oc_clip_top();
//------------------------------------------------------------------------------------------
// graphics attributes setting/getting
//------------------------------------------------------------------------------------------
void oc_set_color(oc_color color);
void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
void oc_set_width(f32 width);
void oc_set_tolerance(f32 tolerance);
void oc_set_joint(oc_joint_type joint);
void oc_set_max_joint_excursion(f32 maxJointExcursion);
void oc_set_cap(oc_cap_type cap);
void oc_set_font(oc_font font);
void oc_set_font_size(f32 size);
void oc_set_text_flip(bool flip);
void oc_set_image(oc_image image);
void oc_set_image_source_region(oc_rect region);
oc_color oc_get_color(void);
f32 oc_get_width(void);
f32 oc_get_tolerance(void);
oc_joint_type oc_get_joint(void);
f32 oc_get_max_joint_excursion(void);
oc_cap_type oc_get_cap(void);
oc_font oc_get_font(void);
f32 oc_get_font_size(void);
bool oc_get_text_flip(void);
oc_image oc_get_image();
//------------------------------------------------------------------------------------------
// path construction
//------------------------------------------------------------------------------------------
oc_vec2 oc_get_position(void);
void oc_move_to(f32 x, f32 y);
void oc_line_to(f32 x, f32 y);
void oc_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
void oc_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
void oc_close_path(void);
oc_rect oc_glyph_outlines(oc_str32 glyphIndices);
void oc_codepoints_outlines(oc_str32 string);
void oc_text_outlines(oc_str8 string);
//------------------------------------------------------------------------------------------
// clear/fill/stroke
//------------------------------------------------------------------------------------------
void oc_clear(void);
void oc_fill(void);
void oc_stroke(void);
//------------------------------------------------------------------------------------------
// shapes helpers
//------------------------------------------------------------------------------------------
void oc_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
void oc_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
void oc_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
void oc_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
void oc_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
void oc_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
void oc_circle_fill(f32 x, f32 y, f32 r);
void oc_circle_stroke(f32 x, f32 y, f32 r);
void oc_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
void oc_image_draw(oc_image image, oc_rect rect);
void oc_image_draw_region(oc_image image, oc_rect srcRegion, oc_rect dstRegion);
//------------------------------------------------------------------------------------------
// fonts
//------------------------------------------------------------------------------------------
oc_font oc_font_nil(void);
bool oc_font_is_nil(oc_font font);
oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges);
void oc_font_destroy(oc_font font);
oc_font_extents oc_font_get_extents(oc_font font);
oc_font_extents oc_font_get_scaled_extents(oc_font font, f32 emSize);
f32 oc_font_get_scale_for_em_pixels(oc_font font, f32 emSize);
u32 oc_font_get_glyph_index(oc_font font, oc_utf32 codePoint);
oc_str32 oc_font_get_glyph_indices(oc_font font, oc_str32 codePoints, oc_str32 backing);
oc_str32 oc_font_push_glyph_indices(oc_font font, oc_arena* arena, oc_str32 codePoints);
int oc_font_get_codepoint_extents(oc_font font, oc_utf32 codePoint, oc_text_extents* outExtents);
int oc_font_get_glyph_extents(oc_font font, oc_str32 glyphIndices, oc_text_extents* outExtents);
oc_rect oc_text_bounding_box_utf32(oc_font font, f32 fontSize, oc_str32 text);
oc_rect oc_text_bounding_box(oc_font font, f32 fontSize, oc_str8 text);
//------------------------------------------------------------------------------------------
// images
//------------------------------------------------------------------------------------------
oc_image oc_image_nil(void);
bool oc_image_is_nil(oc_image a);
oc_image oc_image_create(oc_surface surface, u32 width, u32 height);
oc_image oc_image_create_from_rgba8(oc_surface surface, u32 width, u32 height, u8* pixels);
oc_image oc_image_create_from_memory(oc_surface surface, oc_str8 mem, bool flip);
oc_image oc_image_create_from_file(oc_surface surface, oc_str8 path, bool flip);
void oc_image_destroy(oc_image image);
void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels);
oc_vec2 oc_image_size(oc_image image);
//------------------------------------------------------------------------------------------
// image atlas
//------------------------------------------------------------------------------------------
oc_rect_atlas* oc_rect_atlas_create(oc_arena* arena, i32 width, i32 height);
oc_rect oc_rect_atlas_alloc(oc_rect_atlas* atlas, i32 width, i32 height);
void oc_rect_atlas_recycle(oc_rect_atlas* atlas, oc_rect rect);
oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_image backingImage, u32 width, u32 height, u8* pixels);
oc_image_region oc_image_atlas_alloc_from_data(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 data, bool flip);
oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 path, bool flip);
void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn);

39
doc/cheatsheet_io.h Normal file
View File

@ -0,0 +1,39 @@
/************************************************************/ /**
*
* @file: cheatsheet_io.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Low-level File IO API
//----------------------------------------------------------------
oc_io_cmp oc_io_wait_single_req(oc_io_req* req);
//----------------------------------------------------------------
// High-level File IO API
//----------------------------------------------------------------
oc_file oc_file_nil();
bool oc_file_is_nil(oc_file handle);
oc_file oc_file_open(oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
oc_file oc_file_open_at(oc_file dir, oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
void oc_file_close(oc_file file);
oc_io_error oc_file_last_error(oc_file handle);
i64 oc_file_pos(oc_file file);
i64 oc_file_seek(oc_file file, i64 offset, oc_file_whence whence);
u64 oc_file_write(oc_file file, u64 size, char* buffer);
u64 oc_file_read(oc_file file, u64 size, char* buffer);
oc_file_status oc_file_get_status(oc_file file);
u64 oc_file_size(oc_file file);
//----------------------------------------------------------------
// Asking users for file capabilities
//----------------------------------------------------------------
oc_file oc_file_open_with_request(oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
oc_file_open_with_dialog_result oc_file_open_with_dialog(oc_arena* arena, oc_file_access rights, oc_file_open_flags flags, oc_file_dialog_desc* desc);

64
doc/cheatsheet_ui.h Normal file
View File

@ -0,0 +1,64 @@
/************************************************************/ /**
*
* @file: cheatsheet_ui.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Context and frame lifecycle
//----------------------------------------------------------------
void oc_ui_init(oc_ui_context* context);
oc_ui_context* oc_ui_get_context(void);
void oc_ui_set_context(oc_ui_context* context);
void oc_ui_process_event(oc_event* event);
void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask mask);
void oc_ui_end_frame(void);
void oc_ui_draw(void);
#define oc_ui_frame(size, style, mask)
//----------------------------------------------------------------
// Common widget helpers
//----------------------------------------------------------------
oc_ui_sig oc_ui_label(const char* label);
oc_ui_sig oc_ui_label_str8(oc_str8 label);
oc_ui_sig oc_ui_button(const char* label);
oc_ui_sig oc_ui_checkbox(const char* name, bool* checked);
oc_ui_box* oc_ui_slider(const char* label, f32 thumbRatio, f32* scrollValue);
oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8 text);
oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info);
void oc_ui_panel_begin(const char* name, oc_ui_flags flags);
void oc_ui_panel_end(void);
#define oc_ui_panel(s, f)
void oc_ui_menu_bar_begin(const char* label);
void oc_ui_menu_bar_end(void);
#define oc_ui_menu_bar(name)
void oc_ui_menu_begin(const char* label);
void oc_ui_menu_end(void);
#define oc_ui_menu(name)
oc_ui_sig oc_ui_menu_button(const char* name);
oc_ui_sig oc_ui_tooltip_begin(const char* name);
void oc_ui_tooltip_end(void);
#define oc_ui_tooltip(name)
//-------------------------------------------------------------------------------------
// Styling
//-------------------------------------------------------------------------------------
void oc_ui_style_next(oc_ui_style* style, oc_ui_style_mask mask);
void oc_ui_pattern_push(oc_arena* arena, oc_ui_pattern* pattern, oc_ui_selector selector);
oc_ui_pattern oc_ui_pattern_all(void);
oc_ui_pattern oc_ui_pattern_owner(void);
void oc_ui_style_match_before(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);
void oc_ui_style_match_after(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);

101
doc/cheatsheet_util.h Normal file
View File

@ -0,0 +1,101 @@
/************************************************************/ /**
*
* @file: cheatsheet_util.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Arenas
//----------------------------------------------------------------
void oc_arena_init(oc_arena* arena);
void oc_arena_init_with_options(oc_arena* arena, oc_arena_options* options);
void oc_arena_cleanup(oc_arena* arena);
void* oc_arena_push(oc_arena* arena, u64 size);
#define oc_arena_push_type(arena, type)
#define oc_arena_push_array(arena, type, count)
void oc_arena_clear(oc_arena* arena);
oc_arena_scope oc_arena_scope_begin(oc_arena* arena);
void oc_arena_scope_end(oc_arena_scope scope);
oc_arena_scope oc_scratch_begin(void);
oc_arena_scope oc_scratch_begin_next(oc_arena* used);
#define oc_scratch_end(scope)
//----------------------------------------------------------------
// Lists
//----------------------------------------------------------------
void oc_list_init(oc_list* list);
bool oc_list_empty(oc_list* list);
oc_list_elt* oc_list_begin(oc_list* list);
oc_list_elt* oc_list_end(oc_list* list);
oc_list_elt* oc_list_last(oc_list* list);
#define oc_list_next(elt)
#define oc_list_prev(elt)
#define oc_list_entry(ptr, type, member)
#define oc_list_next_entry(list, elt, type, member)
#define oc_list_prev_entry(list, elt, type, member)
#define oc_list_first_entry(list, type, member)
#define oc_list_last_entry(list, type, member)
#define oc_list_pop_entry(list, type, member)
void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt);
void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt);
void oc_list_remove(oc_list* list, oc_list_elt* elt);
void oc_list_push(oc_list* list, oc_list_elt* elt);
oc_list_elt* oc_list_pop(oc_list* list);
void oc_list_push_back(oc_list* list, oc_list_elt* elt);
oc_list_elt* oc_list_pop_back(oc_list* list);
#define oc_list_for(list, elt, type, member)
#define oc_list_for_reverse(list, elt, type, member)
#define oc_list_for_safe(list, elt, type, member)
//----------------------------------------------------------------
// Strings / string lists / path strings
//----------------------------------------------------------------
oc_str8 oc_str8_from_buffer(u64 len, char* buffer);
oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end);
oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer);
oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str);
oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s);
oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end);
oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args);
oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...);
int oc_str8_cmp(oc_str8 s1, oc_str8 s2);
char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string);
void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str);
void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...);
oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix);
oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list);
oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators);
oc_str8 oc_path_slice_directory(oc_str8 path);
oc_str8 oc_path_slice_filename(oc_str8 path);
oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path);
oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements);
oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath);
bool oc_path_is_absolute(oc_str8 path);
//----------------------------------------------------------------
// Debugging
//----------------------------------------------------------------
#define oc_log_info(message, ...)
#define oc_log_warning(message, ...)
#define oc_log_error(message, ...)
#define OC_ASSERT(test, message, ...)
#define OC_ABORT(message, ...)

View File

@ -19,7 +19,7 @@ f32 minf(f32 a, f32 b);
ORCA_EXPORT void oc_on_init(void)
{
oc_runtime_window_set_title(OC_STR8("clock"));
oc_window_set_title(OC_STR8("clock"));
oc_runtime_window_set_size((oc_vec2){ .x = 400, .y = 400 });
surface = oc_surface_canvas();

View File

@ -615,7 +615,7 @@ ORCA_EXPORT void oc_on_init()
{
oc_log_info("Hello, world (from C)");
oc_runtime_window_set_title(OC_STR8("fluid"));
oc_window_set_title(OC_STR8("fluid"));
surface = oc_surface_gles();
oc_surface_select(surface);

View File

@ -37,7 +37,7 @@ void compile_shader(GLuint shader, const char* source)
ORCA_EXPORT void oc_on_init(void)
{
oc_runtime_window_set_title(OC_STR8("triangle"));
oc_window_set_title(OC_STR8("triangle"));
surface = oc_surface_gles();
oc_surface_select(surface);

View File

@ -69,7 +69,7 @@ oc_str8 loadFile(oc_arena* arena, oc_str8 filename)
ORCA_EXPORT void oc_on_init(void)
{
oc_runtime_window_set_title(OC_STR8("pong"));
oc_window_set_title(OC_STR8("pong"));
surface = oc_surface_canvas();
canvas = oc_canvas_create();

View File

@ -16,7 +16,6 @@ STDLIB_DIR=../../src/libc-shim
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-fno-builtin \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \

View File

@ -10,7 +10,7 @@ oc_arena textArena = { 0 };
ORCA_EXPORT void oc_on_init(void)
{
oc_runtime_window_set_title(OC_STR8("ui"));
oc_window_set_title(OC_STR8("ui"));
surface = oc_surface_canvas();
canvas = oc_canvas_create();

View File

@ -1,8 +0,0 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle/include
if not exist "bin" mkdir bin
cl /we4013 /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% main.c /link /LIBPATH:../../build/bin orca.dll.lib /out:bin/example_surface_sharing.exe
copy ..\..\build\bin\orca.dll bin
copy ..\..\ext\angle\bin\libEGL.dll bin
copy ..\..\ext\angle\bin\libGLESv2.dll bin

View File

@ -1,22 +0,0 @@
#!/bin/bash
BINDIR=bin
LIBDIR=../../build/bin
RESDIR=../resources
SRCDIR=../../src
EXTDIR=../../ext
ANGLEDIR=../../ext/angle/
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR/ -I$ANGLEDIR/include"
LIBS="-L$LIBDIR -lorca"
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
mkdir -p $BINDIR
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_surface_sharing main.c
cp $LIBDIR/liborca.dylib $BINDIR/
cp $LIBDIR/mtl_renderer.metallib $BINDIR/
cp $ANGLEDIR/bin/libEGL.dylib $BINDIR/
cp $ANGLEDIR/bin/libGLESv2.dylib $BINDIR/
install_name_tool -add_rpath "@executable_path" $BINDIR/example_surface_sharing

View File

@ -1,289 +0,0 @@
#include <stdlib.h>
#include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define OC_INCLUDE_GL_API
#include "orca.h"
#ifdef OC_PLATFORM_WINDOWS
#include <process.h>
#include <io.h>
#include <fcntl.h>
#define dup2 _dup2
#define pipe(fds) _pipe(fds, 256, O_BINARY)
#define read _read
#define write _write
#define process_id HANDLE
process_id spawn_child(char* program, char** argv)
{
return ((process_id)_spawnv(P_NOWAIT, program, argv));
}
void terminate_child(process_id child)
{
TerminateProcess(child, 0);
}
#elif OC_PLATFORM_MACOS
#include <unistd.h>
#include <signal.h>
#define process_id pid_t
process_id spawn_child(char* program, char** argv)
{
pid_t pid = fork();
if(!pid)
{
char* envp[] = { 0 };
execve(program, argv, envp);
OC_ASSERT(0);
}
return (pid);
}
void terminate_child(process_id child)
{
kill(child, SIGTERM);
}
#endif
unsigned int program;
const char* vshaderSource =
//"#version 320 es\n"
"attribute vec4 vPosition;\n"
"uniform mat4 transform;\n"
"void main()\n"
"{\n"
" gl_Position = transform*vPosition;\n"
"}\n";
const char* fshaderSource =
//"#version 320 es\n"
"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)
{
oc_log_error("gl error: %i\n", err);
}
int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetShaderInfoLog(shader, 256, &size, buffer);
oc_log_error("shader error: %.*s\n", size, buffer);
}
}
int child_main(int writeFd)
{
oc_init();
oc_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
oc_window window = oc_window_create(rect, OC_STR8("test"), 0);
//NOTE: create surface
oc_surface surface = oc_surface_create_remote(800, 600, OC_GLES);
oc_surface_id connectionID = oc_surface_remote_id(surface);
oc_surface_select(surface);
//NOTE: init shader and gl state
oc_surface_select(surface);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
GLfloat vertices[] = {
-0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
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);
int status = 0;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
oc_log_error("link error: %.*s\n", size, buffer);
}
glUseProgram(program);
//NOTE: send context id to parent
write(writeFd, &connectionID, sizeof(connectionID));
//NOTE: render loop
while(!oc_should_quit())
{
oc_pump_events(0);
oc_event* event = 0;
while((event = oc_next_event(oc_scratch())) != 0)
{
switch(event->type)
{
case OC_EVENT_WINDOW_CLOSE:
{
oc_request_quit();
}
break;
default:
break;
}
}
oc_surface_select(surface);
oc_vec2 size = oc_surface_get_size(surface);
oc_vec2 scaling = oc_surface_contents_scaling(surface);
glViewport(0, 0, size.x * scaling.x, size.y * scaling.y);
glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
static float alpha = 0;
//f32 aspect = frameSize.x/frameSize.y;
f32 aspect = 800 / (f32)600;
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);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
oc_surface_present(surface);
}
oc_terminate();
return (0);
}
int main(int argc, char** argv)
{
if(argc > 1)
{
if(!strcmp(argv[1], "--child"))
{
int writeFd = atoi(argv[2]);
oc_log_info("child process created with file desc %i\n", writeFd);
return (child_main(writeFd));
}
else
{
return (-1);
}
}
// setvbuf( stdout, NULL, _IONBF, 0 );
oc_init();
//NOTE: create main window
oc_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
oc_window window = oc_window_create(rect, OC_STR8("test"), 0);
//NOTE: create surface client
oc_surface surface = oc_surface_create_host(window);
//NOTE setup descriptors
int fileDesc[2];
pipe(fileDesc);
oc_log_info("parent process created readFd %i and writeFd %i\n", fileDesc[0], fileDesc[1]);
char writeDescStr[64];
snprintf(writeDescStr, 64, "%i", fileDesc[1]);
char* args[] = { "bin/example_surface_sharing", "--child", writeDescStr, 0 };
process_id child = spawn_child(args[0], args);
//NOTE: read the connection id
oc_surface_id connectionID = 0;
read(fileDesc[0], &connectionID, sizeof(connectionID));
oc_log_info("received child connection id %llu\n", connectionID);
//NOTE: connect the client
oc_surface_host_connect(surface, connectionID);
//NOTE: show the window
oc_window_bring_to_front(window);
while(!oc_should_quit())
{
oc_pump_events(0);
oc_event* event = 0;
while((event = oc_next_event(oc_scratch())) != 0)
{
switch(event->type)
{
case OC_EVENT_WINDOW_CLOSE:
{
oc_request_quit();
}
break;
default:
break;
}
oc_arena_clear(oc_scratch());
}
oc_surface_select(surface);
oc_surface_present(surface);
}
terminate_child(child);
oc_terminate();
return (0);
}

View File

@ -215,3 +215,12 @@ void oc_window_set_frame_size(oc_window window, oc_vec2 size)
frame.h = size.y;
oc_window_set_frame_rect(window, frame);
}
//---------------------------------------------------------------
// dialogs
//---------------------------------------------------------------
oc_file_dialog_result oc_file_dialog(oc_arena* arena, oc_file_dialog_desc* desc)
{
return (oc_file_dialog_for_table(arena, desc, oc_file_table_get_global()));
}

View File

@ -389,6 +389,60 @@ ORCA_API oc_str8 oc_save_dialog(oc_arena* arena,
oc_str8 defaultPath,
oc_str8_list filters);
#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
#include "platform/platform_io.h"
typedef enum
{
OC_FILE_DIALOG_SAVE,
OC_FILE_DIALOG_OPEN,
} oc_file_dialog_kind;
typedef u32 oc_file_dialog_flags;
enum _oc_file_dialog_flags
{
OC_FILE_DIALOG_FILES = 1,
OC_FILE_DIALOG_DIRECTORIES = 1 << 1,
OC_FILE_DIALOG_MULTIPLE = 1 << 2,
OC_FILE_DIALOG_CREATE_DIRECTORIES = 1 << 3,
};
typedef struct oc_file_dialog_desc
{
oc_file_dialog_kind kind;
oc_file_dialog_flags flags;
oc_str8 title;
oc_str8 okLabel;
oc_file startAt;
oc_str8 startPath;
oc_str8_list filters;
//... later customization options with checkboxes / radiobuttons
} oc_file_dialog_desc;
typedef enum
{
OC_FILE_DIALOG_CANCEL = 0,
OC_FILE_DIALOG_OK,
} oc_file_dialog_button;
typedef struct oc_file_dialog_result
{
oc_file_dialog_button button;
oc_str8 path;
oc_str8_list selection;
} oc_file_dialog_result;
#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
ORCA_API oc_file_dialog_result oc_file_dialog(oc_arena* arena, oc_file_dialog_desc* desc);
typedef struct oc_file_table oc_file_table;
ORCA_API oc_file_dialog_result oc_file_dialog_for_table(oc_arena* arena, oc_file_dialog_desc* desc, oc_file_table* table);
ORCA_API int oc_alert_popup(oc_str8 title,
oc_str8 message,
oc_str8_list options);
@ -403,12 +457,11 @@ ORCA_API int oc_directory_create(oc_str8 path);
#else
void oc_window_set_title(oc_str8 title);
void oc_window_set_size(oc_vec2 size);
void ORCA_IMPORT(oc_request_quit)(void);
void ORCA_IMPORT(oc_runtime_window_set_title)(oc_str8 title);
void ORCA_IMPORT(oc_runtime_window_set_size)(oc_vec2 size);
#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
#ifdef __cplusplus

View File

@ -12,6 +12,7 @@
#include "app.h"
#include "platform/platform.h"
#include "platform/platform_io_internal.h"
#include "util/ringbuffer.h"
#if OC_PLATFORM_WINDOWS

View File

@ -2,3 +2,8 @@
//This is used to pass raw events from the runtime
ORCA_EXPORT oc_event oc_rawEvent;
ORCA_EXPORT void* oc_arena_push_stub(oc_arena* arena, u64 size)
{
return (oc_arena_push(arena, size));
}

View File

@ -19,7 +19,7 @@
#include "platform_clock.h"
#include "platform_debug.h"
#include "ringbuffer.h"
#include "platform/platform_path.h"
#include "app.c"
//--------------------------------------------------------------------
@ -1843,213 +1843,6 @@ void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window
}
}
//------------------------------------------------------------------------------------------------
// Remote surfaces
//------------------------------------------------------------------------------------------------
oc_surface_id oc_osx_surface_remote_id(oc_surface_data* surface)
{
oc_surface_id remoteID = 0;
if(surface->layer.caContext)
{
@autoreleasepool
{
remoteID = (oc_surface_id)[surface->layer.caContext contextId];
}
}
return (remoteID);
}
void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height)
{
@autoreleasepool
{
surface->nativeLayer = oc_osx_surface_native_layer;
surface->contentsScaling = oc_osx_surface_contents_scaling;
surface->getSize = oc_osx_surface_get_size;
surface->getHidden = oc_osx_surface_get_hidden;
surface->setHidden = oc_osx_surface_set_hidden;
surface->remoteID = oc_osx_surface_remote_id;
surface->layer.caLayer = [[CALayer alloc] init];
[surface->layer.caLayer retain];
[surface->layer.caLayer setFrame:(CGRect){ { 0, 0 }, { width, height } }];
NSDictionary* dict = [[NSDictionary alloc] init];
CGSConnectionID connectionID = CGSMainConnectionID();
surface->layer.caContext = [CAContext contextWithCGSConnection:connectionID options:dict];
[surface->layer.caContext retain];
[surface->layer.caContext setLayer:surface->layer.caLayer];
}
}
void oc_osx_surface_host_connect(oc_surface_data* surface, oc_surface_id remoteID)
{
@autoreleasepool
{
[(CALayerHost*)surface->layer.caLayer setContextId:(CAContextID)remoteID];
}
}
void oc_surface_init_host(oc_surface_data* surface, oc_window_data* window)
{
@autoreleasepool
{
surface->api = OC_HOST;
surface->nativeLayer = oc_osx_surface_native_layer;
surface->contentsScaling = oc_osx_surface_contents_scaling;
surface->getSize = oc_osx_surface_get_size;
surface->getHidden = oc_osx_surface_get_hidden;
surface->setHidden = oc_osx_surface_set_hidden;
surface->hostConnect = oc_osx_surface_host_connect;
surface->layer.caLayer = [[CALayerHost alloc] init];
[surface->layer.caLayer retain];
NSRect frame = [[window->osx.nsWindow contentView] frame];
CGSize size = frame.size;
[surface->layer.caLayer setFrame:(CGRect){ { 0, 0 }, size }];
[window->osx.nsView.layer addSublayer:surface->layer.caLayer];
}
}
oc_surface_data* oc_osx_surface_create_host(oc_window windowHandle)
{
oc_surface_data* surface = 0;
oc_window_data* window = oc_window_ptr_from_handle(windowHandle);
if(window)
{
surface = oc_malloc_type(oc_surface_data);
if(surface)
{
oc_surface_init_host(surface, window);
}
}
return (surface);
}
//--------------------------------------------------------------------
// view management
//--------------------------------------------------------------------
/*
oc_view oc_view_create(oc_window windowHandle, oc_rect frame)
{@autoreleasepool{
oc_window_data* window = oc_window_ptr_from_handle(windowHandle);
if(!window)
{
oc_log_error("Can't create view for nil window\n");
return(oc_view_nil());
}
oc_view_data* view = oc_view_alloc();
if(!view)
{
oc_log_error("Could not allocate view data\n");
return(oc_view_nil());
}
view->window = windowHandle;
NSRect nsFrame = {{frame.x, frame.y}, {frame.w, frame.h}};
view->nsView = [[NSView alloc] initWithFrame: nsFrame];
[view->nsView setWantsLayer:YES];
[[window->osx.nsWindow contentView] addSubview: view->nsView];
return(oc_view_handle_from_ptr(view));
}}
void oc_view_destroy(oc_view viewHandle)
{@autoreleasepool{
oc_view_data* view = oc_view_ptr_from_handle(viewHandle);
if(!view)
{
return;
}
oc_window_data* window = oc_window_ptr_from_handle(view->window);
if(!window)
{
return;
}
[view->nsView removeFromSuperview];
oc_view_recycle_ptr(view);
}}
void oc_view_set_frame(oc_view viewHandle, oc_rect frame)
{
oc_view_data* view = oc_view_ptr_from_handle(viewHandle);
if(!view)
{
return;
}
NSRect nsFrame = {{frame.x, frame.y}, {frame.w, frame.h}};
[view->nsView setFrame: nsFrame];
if(!oc_surface_is_nil(view->surface))
{
oc_surface_resize(view->surface, frame.w, frame.h);
}
}
*/
//--------------------------------------------------------------------
// Main loop throttle
//--------------------------------------------------------------------
void oc_set_target_fps(u32 fps)
{
oc_appData.frameStats.targetFramePeriod = 1. / (f64)fps;
oc_appData.frameStats.workTime = 0;
oc_appData.frameStats.remainingTime = 0;
if(oc_appData.osx.frameTimer)
{
[oc_appData.osx.frameTimer invalidate];
}
oc_appData.osx.frameTimer = [NSTimer timerWithTimeInterval:oc_appData.frameStats.targetFramePeriod
target:[NSApp delegate]
selector:@selector(timerElapsed:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:oc_appData.osx.frameTimer forMode:NSRunLoopCommonModes];
}
/*
void oc_begin_frame()
{
oc_appData.frameStats.start = oc_get_elapsed_seconds();
LOG_DEBUG("workTime = %.6f (%.6f fps), remaining = %.6f\n",
oc_appData.frameStats.workTime,
1/oc_appData.frameStats.workTime,
oc_appData.frameStats.remainingTime);
}
void oc_end_frame()
{
oc_appData.frameStats.workTime = oc_get_elapsed_seconds() - oc_appData.frameStats.start;
oc_appData.frameStats.remainingTime = oc_appData.frameStats.targetFramePeriod - oc_appData.frameStats.workTime;
while(oc_appData.frameStats.remainingTime > 100e-9)
{
if(oc_appData.frameStats.remainingTime > 10e-6)
{
oc_sleep_nano(oc_appData.frameStats.remainingTime*0.8*1e9);
}
oc_appData.frameStats.workTime = oc_get_elapsed_seconds() - oc_appData.frameStats.start;
oc_appData.frameStats.remainingTime = oc_appData.frameStats.targetFramePeriod - oc_appData.frameStats.workTime;
}
}
*/
//--------------------------------------------------------------------
// Events handling
//--------------------------------------------------------------------
@ -2133,73 +1926,87 @@ oc_str8 oc_open_dialog(oc_arena* arena,
oc_str8_list filters,
bool directory)
{
@autoreleasepool
__block oc_str8 path = { 0 };
dispatch_block_t block = ^{
@autoreleasepool
{
NSWindow* keyWindow = [NSApp keyWindow];
NSOpenPanel* dialog = [NSOpenPanel openPanel];
NSString* nsTitle = [[NSString alloc] initWithBytes:title.ptr length:title.len encoding:NSUTF8StringEncoding];
//NOTE: title is not displayed since OS X 10.11, now use setMessage instead.
// see https://stackoverflow.com/questions/36879212/title-bar-missing-in-nsopenpanel
[dialog setMessage:nsTitle];
[dialog setLevel:NSModalPanelWindowLevel];
if(filters.eltCount)
{
NSMutableArray* fileTypesArray = [NSMutableArray array];
oc_list_for((oc_list*)&filters.list, elt, oc_str8_elt, listElt)
{
oc_str8 string = elt->string;
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
[fileTypesArray addObject:filter];
}
[dialog setAllowedFileTypes:fileTypesArray];
}
// Enable options in the dialog.
if(directory)
{
[dialog setCanChooseDirectories:YES];
}
else
{
[dialog setCanChooseFiles:YES];
}
[dialog setAllowsMultipleSelection:FALSE];
NSString* nsPath = 0;
;
if(defaultPath.len)
{
nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding];
}
else
{
nsPath = [NSString stringWithUTF8String:"~"];
}
nsPath = [nsPath stringByExpandingTildeInPath];
[dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]];
// Display the dialog box. If the OK pressed,
// process the files.
if([dialog runModal] == NSModalResponseOK)
{
// Gets list of all files selected
NSArray* files = [dialog URLs];
//TODO: Loop through the files and process them.
const char* result = [[[files objectAtIndex:0] path] UTF8String];
path = oc_str8_push_cstring(arena, result);
}
[keyWindow makeKeyWindow];
}
};
if([NSThread isMainThread])
{
NSWindow* keyWindow = [NSApp keyWindow];
NSOpenPanel* dialog = [NSOpenPanel openPanel];
[dialog setLevel:CGShieldingWindowLevel()];
if(filters.eltCount)
{
NSMutableArray* fileTypesArray = [NSMutableArray array];
oc_list_for(&filters.list, elt, oc_str8_elt, listElt)
{
oc_str8 string = elt->string;
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
[fileTypesArray addObject:filter];
}
[dialog setAllowedFileTypes:fileTypesArray];
}
// Enable options in the dialog.
if(directory)
{
[dialog setCanChooseDirectories:YES];
}
else
{
[dialog setCanChooseFiles:YES];
}
[dialog setAllowsMultipleSelection:FALSE];
NSString* nsPath = 0;
;
if(defaultPath.len)
{
nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding];
}
else
{
nsPath = [NSString stringWithUTF8String:"~"];
}
nsPath = [nsPath stringByExpandingTildeInPath];
[dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]];
// Display the dialog box. If the OK pressed,
// process the files.
if([dialog runModal] == NSModalResponseOK)
{
// Gets list of all files selected
NSArray* files = [dialog URLs];
//TODO: Loop through the files and process them.
const char* result = [[[files objectAtIndex:0] path] UTF8String];
oc_str8 path = oc_str8_push_cstring(arena, result);
[keyWindow makeKeyWindow];
return (path);
}
else
{
[keyWindow makeKeyWindow];
return ((oc_str8){ 0, 0 });
}
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
return (path);
}
oc_str8 oc_save_dialog(oc_arena* arena,
@ -2207,61 +2014,221 @@ oc_str8 oc_save_dialog(oc_arena* arena,
oc_str8 defaultPath,
oc_str8_list filters)
{
@autoreleasepool
__block oc_str8 path = { 0 };
dispatch_block_t block = ^{
@autoreleasepool
{
NSWindow* keyWindow = [NSApp keyWindow];
NSSavePanel* dialog = [NSSavePanel savePanel];
[dialog setLevel:CGShieldingWindowLevel()];
if(filters.eltCount)
{
NSMutableArray* fileTypesArray = [NSMutableArray array];
oc_list_for((oc_list*)&filters.list, elt, oc_str8_elt, listElt)
{
oc_str8 string = elt->string;
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
[fileTypesArray addObject:filter];
}
[dialog setAllowedFileTypes:fileTypesArray];
}
NSString* nsPath = 0;
;
if(defaultPath.len)
{
nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding];
}
else
{
nsPath = [NSString stringWithUTF8String:"~"];
}
nsPath = [nsPath stringByExpandingTildeInPath];
[dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]];
// Display the dialog box. If the OK pressed,
// process the files.
if([dialog runModal] == NSModalResponseOK)
{
// Gets list of all files selected
NSURL* files = [dialog URL];
// Loop through the files and process them.
const char* result = [[files path] UTF8String];
path = oc_str8_push_cstring(arena, result);
}
[keyWindow makeKeyWindow];
}
};
if([NSThread isMainThread])
{
NSWindow* keyWindow = [NSApp keyWindow];
NSSavePanel* dialog = [NSSavePanel savePanel];
[dialog setLevel:CGShieldingWindowLevel()];
if(filters.eltCount)
{
NSMutableArray* fileTypesArray = [NSMutableArray array];
oc_list_for(&filters.list, elt, oc_str8_elt, listElt)
{
oc_str8 string = elt->string;
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
[fileTypesArray addObject:filter];
}
[dialog setAllowedFileTypes:fileTypesArray];
}
NSString* nsPath = 0;
;
if(defaultPath.len)
{
nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding];
}
else
{
nsPath = [NSString stringWithUTF8String:"~"];
}
nsPath = [nsPath stringByExpandingTildeInPath];
[dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]];
// Display the dialog box. If the OK pressed,
// process the files.
if([dialog runModal] == NSModalResponseOK)
{
// Gets list of all files selected
NSURL* files = [dialog URL];
// Loop through the files and process them.
const char* result = [[files path] UTF8String];
oc_str8 path = oc_str8_push_cstring(arena, result);
[keyWindow makeKeyWindow];
return (path);
}
else
{
[keyWindow makeKeyWindow];
return ((oc_str8){ 0, 0 });
}
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
return (path);
}
ORCA_API oc_file_dialog_result oc_file_dialog_for_table(oc_arena* arena, oc_file_dialog_desc* desc, oc_file_table* table)
{
__block oc_file_dialog_result result = { 0 };
dispatch_block_t block = ^{
@autoreleasepool
{
oc_arena_scope scratch = oc_scratch_begin_next(arena);
NSWindow* keyWindow = [NSApp keyWindow];
NSSavePanel* dialog = 0;
if(desc->kind == OC_FILE_DIALOG_OPEN)
{
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
dialog = (NSSavePanel*)openPanel;
openPanel.canChooseFiles = (desc->flags & OC_FILE_DIALOG_FILES) ? YES : NO;
openPanel.canChooseDirectories = (desc->flags & OC_FILE_DIALOG_DIRECTORIES) ? YES : NO;
openPanel.allowsMultipleSelection = (desc->flags & OC_FILE_DIALOG_MULTIPLE) ? YES : NO;
}
else
{
dialog = [NSSavePanel savePanel];
dialog.canCreateDirectories = (desc->flags & OC_FILE_DIALOG_CREATE_DIRECTORIES) ? YES : NO;
}
//NOTE: set title. "title" property is not displayed since OS X 10.11, now use setMessage instead.
// see https://stackoverflow.com/questions/36879212/title-bar-missing-in-nsopenpanel
NSString* nsTitle = [[NSString alloc] initWithBytes:desc->title.ptr
length:desc->title.len
encoding:NSUTF8StringEncoding];
[dialog setMessage:nsTitle];
//NOTE: set ok button
if(desc->okLabel.len)
{
NSString* label = [[NSString alloc] initWithBytes:desc->okLabel.ptr
length:desc->okLabel.len
encoding:NSUTF8StringEncoding];
[dialog setPrompt:label];
}
//NOTE: set starting path
oc_str8 startPath = { 0 };
{
oc_str8_list list = { 0 };
if(!oc_file_is_nil(desc->startAt))
{
oc_file_slot* slot = oc_file_slot_from_handle(table, desc->startAt);
if(slot)
{
char path[PATH_MAX];
if(fcntl(slot->fd, F_GETPATH, path) != -1)
{
oc_str8 string = oc_str8_push_cstring(scratch.arena, path);
oc_str8_list_push(scratch.arena, &list, string);
}
}
}
if(desc->startPath.len)
{
oc_str8_list_push(scratch.arena, &list, desc->startPath);
}
startPath = oc_path_join(scratch.arena, list);
}
NSString* nsPath = 0;
if(startPath.len)
{
nsPath = [[NSString alloc] initWithBytes:startPath.ptr
length:startPath.len
encoding:NSUTF8StringEncoding];
}
else
{
nsPath = [NSString stringWithUTF8String:"~"];
}
nsPath = [nsPath stringByExpandingTildeInPath];
[dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]];
//NOTE: set filters
if(desc->filters.eltCount)
{
NSMutableArray* fileTypesArray = [NSMutableArray array];
oc_list_for((oc_list*)&desc->filters.list, elt, oc_str8_elt, listElt)
{
oc_str8 string = elt->string;
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
[fileTypesArray addObject:filter];
}
[dialog setAllowedFileTypes:fileTypesArray];
}
// Display the dialog box. If the OK pressed,
// process the files.
[dialog validateVisibleColumns];
[dialog setLevel:NSModalPanelWindowLevel];
if([dialog runModal] == NSModalResponseOK)
{
if(desc->kind == OC_FILE_DIALOG_OPEN && (desc->flags & OC_FILE_DIALOG_MULTIPLE))
{
// Gets list of all files selected
NSArray* files = [((NSOpenPanel*)dialog) URLs];
const char* path = [[[files objectAtIndex:0] path] UTF8String];
result.path = oc_str8_push_cstring(arena, path);
for(int i = 0; i < [files count]; i++)
{
const char* path = [[[files objectAtIndex:i] path] UTF8String];
oc_str8 string = oc_str8_push_cstring(arena, path);
oc_str8_list_push(arena, &result.selection, string);
}
}
else
{
const char* path = [[[dialog URL] path] UTF8String];
result.path = oc_str8_push_cstring(arena, path);
oc_str8_list_push(arena, &result.selection, result.path);
}
result.button = OC_FILE_DIALOG_OK;
}
else
{
result.button = OC_FILE_DIALOG_CANCEL;
}
[keyWindow makeKeyWindow];
oc_scratch_end(scratch);
}
};
if([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
return (result);
}
int oc_alert_popup(oc_str8 title,

View File

@ -1189,16 +1189,16 @@ void oc_win32_surface_set_hidden(oc_surface_data* surface, bool hidden)
void oc_win32_surface_bring_to_front(oc_surface_data* surface)
{
oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_list_push(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_win32_update_child_layers_zorder(surface->layer.parent);
oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_list_push(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_win32_update_child_layers_zorder(surface->layer.parent);
}
void oc_win32_surface_send_to_back(oc_surface_data* surface)
{
oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_list_push_back(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_win32_update_child_layers_zorder(surface->layer.parent);
oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_list_push_back(&surface->layer.parent->win32.layers, &surface->layer.listElt);
oc_win32_update_child_layers_zorder(surface->layer.parent);
}
void* oc_win32_surface_native_layer(oc_surface_data* surface)
@ -1206,31 +1206,6 @@ void* oc_win32_surface_native_layer(oc_surface_data* surface)
return ((void*)surface->layer.hWnd);
}
oc_surface_id oc_win32_surface_remote_id(oc_surface_data* surface)
{
return ((oc_surface_id)surface->layer.hWnd);
}
void oc_win32_surface_host_connect(oc_surface_data* surface, oc_surface_id remoteID)
{
HWND dstWnd = surface->layer.hWnd;
HWND srcWnd = (HWND)remoteID;
RECT dstRect;
GetClientRect(dstWnd, &dstRect);
SetParent(srcWnd, dstWnd);
ShowWindow(srcWnd, SW_NORMAL);
SetWindowPos(srcWnd,
HWND_TOP,
0,
0,
dstRect.right - dstRect.left,
dstRect.bottom - dstRect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
void oc_surface_cleanup(oc_surface_data* surface)
{
oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt);
@ -1307,68 +1282,6 @@ void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window
oc_list_append(&window->win32.layers, &surface->layer.listElt);
}
void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height)
{
surface->contentsScaling = oc_win32_surface_contents_scaling;
surface->getSize = oc_win32_surface_get_size;
surface->getHidden = oc_win32_surface_get_hidden;
surface->setHidden = oc_win32_surface_set_hidden;
surface->nativeLayer = oc_win32_surface_native_layer;
surface->remoteID = oc_win32_surface_remote_id;
WNDCLASS layerWindowClass = { .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
.lpfnWndProc = DefWindowProc,
.hInstance = GetModuleHandleW(NULL),
.lpszClassName = "server_layer_window_class",
.hCursor = LoadCursor(0, IDC_ARROW) };
RegisterClass(&layerWindowClass);
//NOTE(martin): create a temporary parent window. This seems like a necessary hack, because if layer window is created as
// a normal window first, and then parented to the client window, it breaks resizing the parent
// window for some reason...
HWND tmpParent = CreateWindow("server_layer_window_class", "layerParent",
WS_OVERLAPPED,
0, 0, width, height,
0,
0,
layerWindowClass.hInstance,
0);
//NOTE: create the layer window
surface->layer.hWnd = CreateWindowEx(WS_EX_NOACTIVATE,
"server_layer_window_class", "layer",
WS_CHILD,
0, 0, width, height,
tmpParent,
0,
layerWindowClass.hInstance,
0);
//NOTE: unparent it and destroy tmp parent
SetParent(surface->layer.hWnd, 0);
DestroyWindow(tmpParent);
}
oc_surface_data* oc_win32_surface_create_host(oc_window window)
{
oc_surface_data* surface = 0;
oc_window_data* windowData = oc_window_ptr_from_handle(window);
if(windowData)
{
surface = oc_malloc_type(oc_surface_data);
if(surface)
{
memset(surface, 0, sizeof(oc_surface_data));
oc_surface_init_for_window(surface, windowData);
surface->api = OC_HOST;
surface->hostConnect = oc_win32_surface_host_connect;
}
}
return (surface);
}
//--------------------------------------------------------------------
// native open/save/alert windows
//--------------------------------------------------------------------
@ -1565,6 +1478,207 @@ oc_str8 oc_save_dialog(oc_arena* arena,
return (res);
}
#include "platform/platform_io_internal.h"
oc_str16 win32_path_from_handle_null_terminated(oc_arena* arena, HANDLE handle); // defined in win32_io.c
oc_file_dialog_result oc_file_dialog_for_table(oc_arena* arena, oc_file_dialog_desc* desc, oc_file_table* table)
{
oc_arena_scope scratch = oc_scratch_begin_next(arena);
oc_file_dialog_result result = { 0 };
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if(SUCCEEDED(hr))
{
IFileDialog* dialog = 0;
if(desc->kind == OC_FILE_DIALOG_OPEN)
{
hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, (void**)&dialog);
if(SUCCEEDED(hr))
{
FILEOPENDIALOGOPTIONS opt;
dialog->lpVtbl->GetOptions(dialog, &opt);
//NOTE: OC_FILE_DIALOG_FILES is always implied, since IFileDialog offers no way to pick _only_ folders
if(desc->flags & OC_FILE_DIALOG_DIRECTORIES)
{
opt |= FOS_PICKFOLDERS;
}
else
{
opt &= ~FOS_PICKFOLDERS;
}
if(desc->flags & OC_FILE_DIALOG_MULTIPLE)
{
opt |= FOS_ALLOWMULTISELECT;
}
else
{
opt &= ~FOS_ALLOWMULTISELECT;
}
dialog->lpVtbl->SetOptions(dialog, opt);
}
}
else
{
hr = CoCreateInstance(&CLSID_FileSaveDialog, NULL, CLSCTX_ALL, &IID_IFileSaveDialog, (void**)&dialog);
//NOTE: OC_FILE_DIALOG_CREATE_DIRECTORIES is implied, IFileSaveDialog offers no way of disabling it...
}
if(SUCCEEDED(hr))
{
//NOTE set title
if(desc->title.len)
{
oc_str16 titleWide = oc_win32_utf8_to_wide(scratch.arena, desc->title);
dialog->lpVtbl->SetTitle(dialog, (LPCWSTR)titleWide.ptr);
}
//NOTE set ok button
if(desc->okLabel.len)
{
oc_str16 okLabelWide = oc_win32_utf8_to_wide(scratch.arena, desc->okLabel);
dialog->lpVtbl->SetOkButtonLabel(dialog, (LPCWSTR)okLabelWide.ptr);
}
//NOTE: set starting path
oc_str8 startPath = { 0 };
{
oc_str8_list list = { 0 };
if(!oc_file_is_nil(desc->startAt))
{
oc_file_slot* slot = oc_file_slot_from_handle(table, desc->startAt);
if(slot)
{
oc_str16 pathWide = win32_path_from_handle_null_terminated(scratch.arena, slot->fd);
oc_str8 path = oc_win32_wide_to_utf8(scratch.arena, pathWide);
//NOTE: remove potential \\?\ prefix which doesn't work with SHCreateItemFromParsingName()
if(!oc_str8_cmp(oc_str8_slice(path, 0, 4), OC_STR8("\\\\?\\")))
{
path = oc_str8_slice(path, 4, path.len);
}
oc_str8_list_push(scratch.arena, &list, path);
}
}
if(desc->startPath.len)
{
oc_str8_list_push(scratch.arena, &list, desc->startPath);
}
startPath = oc_path_join(scratch.arena, list);
}
if(startPath.len)
{
oc_str16 pathWide = oc_win32_utf8_to_wide(scratch.arena, startPath);
IShellItem* item = 0;
hr = SHCreateItemFromParsingName((LPCWSTR)pathWide.ptr, NULL, &IID_IShellItem, (void**)&item);
if(SUCCEEDED(hr))
{
hr = dialog->lpVtbl->SetFolder(dialog, item);
item->lpVtbl->Release(item);
}
}
//NOTE: set filters
if(desc->filters.eltCount)
{
COMDLG_FILTERSPEC* filterSpecs = oc_arena_push_array(scratch.arena, COMDLG_FILTERSPEC, desc->filters.eltCount);
int i = 0;
oc_list_for(&desc->filters.list, elt, oc_str8_elt, listElt)
{
oc_str8_list list = { 0 };
oc_str8_list_push(scratch.arena, &list, OC_STR8("*."));
oc_str8_list_push(scratch.arena, &list, elt->string);
oc_str8 filter = oc_str8_list_join(scratch.arena, list);
int filterWideSize = 1 + MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, NULL, 0);
filterSpecs[i].pszSpec = oc_arena_push_array(scratch.arena, wchar_t, filterWideSize);
MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, (LPWSTR)filterSpecs[i].pszSpec, filterWideSize);
((LPWSTR)(filterSpecs[i].pszSpec))[filterWideSize - 1] = 0;
filterSpecs[i].pszName = filterSpecs[i].pszSpec;
i++;
}
hr = dialog->lpVtbl->SetFileTypes(dialog, i, filterSpecs);
}
hr = dialog->lpVtbl->Show(dialog, NULL);
if(SUCCEEDED(hr))
{
if(desc->kind == OC_FILE_DIALOG_OPEN && (desc->flags & OC_FILE_DIALOG_MULTIPLE))
{
IShellItemArray* array = 0;
hr = ((IFileOpenDialog*)dialog)->lpVtbl->GetResults((IFileOpenDialog*)dialog, &array);
if(SUCCEEDED(hr))
{
int count = 0;
array->lpVtbl->GetCount(array, &count);
for(int i = 0; i < count; i++)
{
IShellItem* item = 0;
hr = array->lpVtbl->GetItemAt(array, i, &item);
if(SUCCEEDED(hr))
{
PWSTR pathWCStr = 0;
hr = item->lpVtbl->GetDisplayName(item, SIGDN_FILESYSPATH, &pathWCStr);
if(SUCCEEDED(hr))
{
oc_str16 pathWide = oc_str16_from_buffer(lstrlenW(pathWCStr), pathWCStr);
oc_str8 path = oc_win32_wide_to_utf8(arena, pathWide);
oc_str8_list_push(arena, &result.selection, path);
if(i == 0)
{
result.path = path;
}
CoTaskMemFree(pathWCStr);
}
item->lpVtbl->Release(item);
}
}
result.button = OC_FILE_DIALOG_OK;
}
}
else
{
IShellItem* item;
hr = dialog->lpVtbl->GetResult(dialog, &item);
if(SUCCEEDED(hr))
{
PWSTR pathWCStr;
hr = item->lpVtbl->GetDisplayName(item, SIGDN_FILESYSPATH, &pathWCStr);
if(SUCCEEDED(hr))
{
oc_str16 pathWide = oc_str16_from_buffer(lstrlenW(pathWCStr), pathWCStr);
result.path = oc_win32_wide_to_utf8(arena, pathWide);
oc_str8_list_push(arena, &result.selection, result.path);
CoTaskMemFree(pathWCStr);
}
item->lpVtbl->Release(item);
result.button = OC_FILE_DIALOG_OK;
}
}
}
}
dialog->lpVtbl->Release(dialog);
}
CoUninitialize();
oc_scratch_end(scratch);
return (result);
}
#include <commctrl.h>
int oc_alert_popup(oc_str8 title,

View File

@ -150,22 +150,6 @@ void oc_egl_surface_init(oc_egl_surface* surface)
eglSwapInterval(surface->eglDisplay, 1);
}
oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height)
{
oc_egl_surface* surface = 0;
surface = oc_malloc_type(oc_egl_surface);
if(surface)
{
memset(surface, 0, sizeof(oc_egl_surface));
oc_surface_init_remote((oc_surface_data*)surface, width, height);
oc_egl_surface_init(surface);
}
return ((oc_surface_data*)surface);
}
oc_surface_data* oc_egl_surface_create_for_window(oc_window window)
{
oc_egl_surface* surface = 0;

View File

@ -14,7 +14,7 @@
#include "util/typedefs.h"
//------------------------------------------------------------------------------------------
//NOTE(martin): backends selection
//SECTION: backends selection
//------------------------------------------------------------------------------------------
typedef enum
@ -85,49 +85,48 @@ typedef enum
#include "wgl_surface.h"
#endif
//TODO: expose nsgl surface when supported, expose egl surface, etc...
//TODO: add OC_INCLUDE_OPENGL/GLES/etc, once we know how we make different gl versions co-exist
ORCA_API bool oc_is_surface_api_available(oc_surface_api api);
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics surface
//SECTION: graphics surface
//------------------------------------------------------------------------------------------
typedef struct oc_surface
{
u64 h;
} oc_surface;
ORCA_API oc_surface oc_surface_nil(void);
ORCA_API bool oc_surface_is_nil(oc_surface surface);
ORCA_API oc_surface oc_surface_nil(void); //DOC: returns a nil surface
ORCA_API bool oc_surface_is_nil(oc_surface surface); //DOC: true if surface is nil
#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA
ORCA_API oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api);
ORCA_API void oc_surface_destroy(oc_surface surface);
ORCA_API void oc_surface_select(oc_surface surface);
ORCA_API void oc_surface_present(oc_surface surface);
ORCA_API void oc_surface_deselect(void);
ORCA_API void oc_surface_swap_interval(oc_surface surface, int swap);
ORCA_API oc_vec2 oc_surface_get_size(oc_surface surface);
ORCA_API oc_vec2 oc_surface_contents_scaling(oc_surface surface);
ORCA_API bool oc_surface_get_hidden(oc_surface surface);
ORCA_API void oc_surface_set_hidden(oc_surface surface, bool hidden);
ORCA_API void oc_surface_bring_to_front(oc_surface surface);
ORCA_API void oc_surface_send_to_back(oc_surface surface);
#else
//NOTE(martin): surface sharing
typedef u64 oc_surface_id;
ORCA_API oc_surface oc_surface_canvas(); //DOC: creates a surface for use with the canvas API
ORCA_API oc_surface oc_surface_gles(); //DOC: create a surface for use with GLES API
ORCA_API oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api);
ORCA_API oc_surface oc_surface_create_host(oc_window window);
ORCA_API oc_surface_id oc_surface_remote_id(oc_surface surface);
ORCA_API void oc_surface_host_connect(oc_surface surface, oc_surface_id remoteId);
#endif
ORCA_API void oc_surface_destroy(oc_surface surface); //DOC: destroys the surface
ORCA_API void oc_surface_select(oc_surface surface); //DOC: selects the surface in the current thread before drawing
ORCA_API void oc_surface_present(oc_surface surface); //DOC: presents the surface to its window
ORCA_API void oc_surface_deselect(void); //DOC: deselects the current thread's previously selected surface
ORCA_API oc_vec2 oc_surface_get_size(oc_surface surface);
ORCA_API oc_vec2 oc_surface_contents_scaling(oc_surface surface); //DOC: returns the scaling of the surface (pixels = points * scale)
ORCA_API void oc_surface_bring_to_front(oc_surface surface); //DOC: puts surface on top of the surface stack
ORCA_API void oc_surface_send_to_back(oc_surface surface); //DOC: puts surface at the bottom of the surface stack
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics canvas structs
//SECTION: graphics canvas structs
//------------------------------------------------------------------------------------------
typedef struct oc_canvas
{
@ -196,18 +195,18 @@ typedef struct oc_text_extents
} oc_text_extents;
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics canvas
//SECTION: graphics canvas
//------------------------------------------------------------------------------------------
ORCA_API oc_canvas oc_canvas_nil(void);
ORCA_API bool oc_canvas_is_nil(oc_canvas canvas);
ORCA_API oc_canvas oc_canvas_nil(void); //DOC: returns a nil canvas
ORCA_API bool oc_canvas_is_nil(oc_canvas canvas); //DOC: true if canvas is nil
ORCA_API oc_canvas oc_canvas_create(void);
ORCA_API void oc_canvas_destroy(oc_canvas canvas);
ORCA_API oc_canvas oc_canvas_set_current(oc_canvas canvas);
ORCA_API void oc_render(oc_surface surface, oc_canvas canvas);
ORCA_API oc_canvas oc_canvas_create(void); //DOC: create a new canvas
ORCA_API void oc_canvas_destroy(oc_canvas canvas); //DOC: destroys canvas
ORCA_API oc_canvas oc_canvas_set_current(oc_canvas canvas); //DOC: selects canvas in the current thread
ORCA_API void oc_render(oc_surface surface, oc_canvas canvas); //DOC: renders all canvas commands onto surface
//------------------------------------------------------------------------------------------
//NOTE(martin): fonts
//SECTION: fonts
//------------------------------------------------------------------------------------------
ORCA_API oc_font oc_font_nil(void);
ORCA_API oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges);
@ -235,7 +234,7 @@ ORCA_API oc_rect oc_text_bounding_box_utf32(oc_font font, f32 fontSize, oc_str32
ORCA_API oc_rect oc_text_bounding_box(oc_font font, f32 fontSize, oc_str8 text);
//------------------------------------------------------------------------------------------
//NOTE(martin): images
//SECTION: images
//------------------------------------------------------------------------------------------
ORCA_API oc_image oc_image_nil(void);
ORCA_API bool oc_image_is_nil(oc_image a);
@ -251,7 +250,7 @@ ORCA_API void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* p
ORCA_API oc_vec2 oc_image_size(oc_image image);
//------------------------------------------------------------------------------------------
//NOTE(martin): atlasing
//SECTION: atlasing
//------------------------------------------------------------------------------------------
//NOTE: rectangle allocator
@ -274,19 +273,18 @@ ORCA_API oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc
ORCA_API void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn);
//------------------------------------------------------------------------------------------
//NOTE(martin): transform, viewport and clipping
//SECTION: transform, viewport and clipping
//------------------------------------------------------------------------------------------
ORCA_API void oc_viewport(oc_rect viewPort);
ORCA_API void oc_matrix_push(oc_mat2x3 matrix);
ORCA_API void oc_matrix_pop(void);
ORCA_API oc_mat2x3 oc_matrix_top();
ORCA_API void oc_clip_push(f32 x, f32 y, f32 w, f32 h);
ORCA_API void oc_clip_pop(void);
ORCA_API oc_rect oc_clip();
ORCA_API oc_rect oc_clip_top();
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics attributes setting/getting
//SECTION: graphics attributes setting/getting
//------------------------------------------------------------------------------------------
ORCA_API void oc_set_color(oc_color color);
ORCA_API void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
@ -310,9 +308,11 @@ ORCA_API oc_cap_type oc_get_cap(void);
ORCA_API oc_font oc_get_font(void);
ORCA_API f32 oc_get_font_size(void);
ORCA_API bool oc_get_text_flip(void);
ORCA_API oc_image oc_get_image();
ORCA_API oc_rect oc_get_image_source_region();
//------------------------------------------------------------------------------------------
//NOTE(martin): path construction
//SECTION: path construction
//------------------------------------------------------------------------------------------
ORCA_API oc_vec2 oc_get_position(void);
ORCA_API void oc_move_to(f32 x, f32 y);
@ -326,14 +326,14 @@ ORCA_API void oc_codepoints_outlines(oc_str32 string);
ORCA_API void oc_text_outlines(oc_str8 string);
//------------------------------------------------------------------------------------------
//NOTE(martin): clear/fill/stroke
//SECTION: clear/fill/stroke
//------------------------------------------------------------------------------------------
ORCA_API void oc_clear(void);
ORCA_API void oc_fill(void);
ORCA_API void oc_stroke(void);
//------------------------------------------------------------------------------------------
//NOTE(martin): 'fast' shapes primitives
//SECTION: shapes helpers
//------------------------------------------------------------------------------------------
ORCA_API void oc_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
ORCA_API void oc_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);

View File

@ -928,6 +928,21 @@ void oc_matrix_pop()
}
}
oc_mat2x3 oc_matrix_top()
{
oc_mat2x3 mat = {
1, 0, 0,
0, 1, 0
};
oc_canvas_data* canvas = __mgCurrentCanvas;
if(canvas)
{
mat = oc_matrix_stack_top(canvas);
}
return (mat);
}
void oc_clip_push(f32 x, f32 y, f32 w, f32 h)
{
oc_canvas_data* canvas = __mgCurrentCanvas;
@ -972,7 +987,7 @@ void oc_clip_pop()
}
}
oc_rect oc_clip()
oc_rect oc_clip_top()
{
oc_rect clip = { -FLT_MAX / 2, -FLT_MAX / 2, FLT_MAX, FLT_MAX };
@ -1193,6 +1208,28 @@ bool oc_get_text_flip()
return (flip);
}
oc_image oc_get_image()
{
oc_image image = oc_image_nil();
oc_canvas_data* canvas = __mgCurrentCanvas;
if(canvas)
{
image = canvas->attributes.image;
}
return (image);
}
oc_rect oc_get_image_source_region()
{
oc_rect rect = { 0 };
oc_canvas_data* canvas = __mgCurrentCanvas;
if(canvas)
{
rect = canvas->attributes.srcRegion;
}
return (rect);
}
//------------------------------------------------------------------------------------------
//NOTE(martin): path construction
//------------------------------------------------------------------------------------------

View File

@ -153,55 +153,6 @@ oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api)
return (surfaceHandle);
}
oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api)
{
if(!oc_graphicsData.init)
{
oc_graphics_init();
}
oc_surface surfaceHandle = oc_surface_nil();
oc_surface_data* surface = 0;
switch(api)
{
#if OC_COMPILE_GLES
case OC_GLES:
surface = oc_egl_surface_create_remote(width, height);
break;
#endif
default:
break;
}
if(surface)
{
surfaceHandle = oc_surface_handle_alloc(surface);
oc_surface_select(surfaceHandle);
}
return (surfaceHandle);
}
oc_surface oc_surface_create_host(oc_window window)
{
if(!oc_graphicsData.init)
{
oc_graphics_init();
}
oc_surface handle = oc_surface_nil();
oc_surface_data* surface = 0;
#if OC_PLATFORM_MACOS
surface = oc_osx_surface_create_host(window);
#elif OC_PLATFORM_WINDOWS
surface = oc_win32_surface_create_host(window);
#endif
if(surface)
{
handle = oc_surface_handle_alloc(surface);
}
return (handle);
}
void oc_surface_destroy(oc_surface handle)
{
OC_DEBUG_ASSERT(oc_graphicsData.init);
@ -328,26 +279,6 @@ void* oc_surface_native_layer(oc_surface surface)
return (res);
}
oc_surface_id oc_surface_remote_id(oc_surface handle)
{
oc_surface_id remoteId = 0;
oc_surface_data* surface = oc_surface_data_from_handle(handle);
if(surface && surface->remoteID)
{
remoteId = surface->remoteID(surface);
}
return (remoteId);
}
void oc_surface_host_connect(oc_surface handle, oc_surface_id remoteID)
{
oc_surface_data* surface = oc_surface_data_from_handle(handle);
if(surface && surface->hostConnect)
{
surface->hostConnect(surface, remoteID);
}
}
void oc_surface_render_commands(oc_surface surface,
oc_color clearColor,
u32 primitiveCount,

View File

@ -31,8 +31,6 @@ typedef oc_vec2 (*oc_surface_contents_scaling_proc)(oc_surface_data* surface);
typedef bool (*oc_surface_get_hidden_proc)(oc_surface_data* surface);
typedef void (*oc_surface_set_hidden_proc)(oc_surface_data* surface, bool hidden);
typedef void* (*oc_surface_native_layer_proc)(oc_surface_data* surface);
typedef oc_surface_id (*oc_surface_remote_id_proc)(oc_surface_data* surface);
typedef void (*oc_surface_host_connect_proc)(oc_surface_data* surface, oc_surface_id remoteId);
typedef void (*oc_surface_bring_to_front_proc)(oc_surface_data* surface);
typedef void (*oc_surface_send_to_back_proc)(oc_surface_data* surface);
@ -52,8 +50,6 @@ typedef struct oc_surface_data
oc_surface_get_hidden_proc getHidden;
oc_surface_set_hidden_proc setHidden;
oc_surface_native_layer_proc nativeLayer;
oc_surface_remote_id_proc remoteID;
oc_surface_host_connect_proc hostConnect;
oc_surface_bring_to_front_proc bringToFront;
oc_surface_send_to_back_proc sendToBack;
@ -66,8 +62,6 @@ oc_surface oc_surface_handle_alloc(oc_surface_data* surface);
oc_surface_data* oc_surface_data_from_handle(oc_surface handle);
void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window);
void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height);
void oc_surface_init_host(oc_surface_data* surface, oc_window_data* window);
void oc_surface_cleanup(oc_surface_data* surface);
void* oc_surface_native_layer(oc_surface surface);

View File

@ -53,6 +53,7 @@
#include "platform/platform_io_common.c"
#include "platform/orca_io_stubs.c"
#include "platform/orca_platform.c"
#include "platform/platform_path.c"
#else
#error "Unsupported platform"
#endif

View File

@ -22,6 +22,7 @@
#include "platform/platform.h"
#include "platform/platform_clock.h"
#include "platform/platform_io.h"
#include "platform/platform_io_dialog.h"
#include "platform/platform_path.h"
#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
@ -39,9 +40,6 @@
//TODO: maybe make this conditional
#include "graphics/orca_gl31.h"
oc_surface oc_surface_canvas();
oc_surface oc_surface_gles();
#else
#ifdef OC_INCLUDE_GL_API
#include "graphics/gl_api.h"

View File

@ -49,7 +49,7 @@ typedef struct oc_log_output
static oc_log_output oc_logDefaultOutput = { .kind = ORCA_LOG_OUTPUT_CONSOLE };
oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput;
void ORCA_IMPORT(oc_runtime_log)(oc_log_level level,
void ORCA_IMPORT(oc_bridge_log)(oc_log_level level,
int fileLen,
const char* file,
int functionLen,
@ -77,7 +77,7 @@ void platform_log_push(oc_log_output* output,
oc_str8 string = oc_str8_list_join(scratch, ctx.list);
oc_runtime_log(level, strlen(file), file, strlen(function), function, line, oc_str8_ip(string));
oc_bridge_log(level, strlen(file), file, strlen(function), function, line, oc_str8_ip(string));
oc_arena_scope_end(tmp);
}
@ -86,8 +86,8 @@ void platform_log_push(oc_log_output* output,
// Assert/Abort
//----------------------------------------------------------------
_Noreturn void ORCA_IMPORT(oc_runtime_abort_ext)(const char* file, const char* function, int line, const char* msg);
_Noreturn void ORCA_IMPORT(oc_runtime_assert_fail)(const char* file, const char* function, int line, const char* src, const char* msg);
_Noreturn void ORCA_IMPORT(oc_bridge_abort_ext)(const char* file, const char* function, int line, const char* msg);
_Noreturn void ORCA_IMPORT(oc_bridge_assert_fail)(const char* file, const char* function, int line, const char* src, const char* msg);
_Noreturn void oc_abort_ext(const char* file, const char* function, int line, const char* fmt, ...)
{
@ -108,7 +108,7 @@ _Noreturn void oc_abort_ext(const char* file, const char* function, int line, co
oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list);
oc_runtime_abort_ext(file, function, line, msg.ptr);
oc_bridge_abort_ext(file, function, line, msg.ptr);
oc_scratch_end(scratch);
}
@ -132,7 +132,7 @@ _Noreturn void oc_assert_fail(const char* file, const char* function, int line,
oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list);
oc_runtime_assert_fail(file, function, line, src, msg.ptr);
oc_bridge_assert_fail(file, function, line, src, msg.ptr);
oc_scratch_end(scratch);
}

View File

@ -222,4 +222,10 @@ ORCA_API u64 oc_file_size(oc_file file);
//TODO: Complete as needed...
//----------------------------------------------------------------
// Acquiring new file capabilities through user interaction
//----------------------------------------------------------------
ORCA_API oc_file oc_file_open_with_request(oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
#endif //__PLATFORM_IO_H_

View File

@ -7,6 +7,7 @@
*****************************************************************/
#include "platform_io.h"
#include "platform_io_dialog.h"
//------------------------------------------------------------------------------
// File stream read/write API

View File

@ -0,0 +1,29 @@
/************************************************************/ /**
*
* @file: platform_io_dialog.h
* @author: Martin Fouilleul
* @date: 01/09/2023
*
*****************************************************************/
#ifndef __PLATFORM_IO_DIALOG_H_
#define __PLATFORM_IO_DIALOG_H_
#include "platform_io.h"
#include "app/app.h"
typedef struct oc_file_open_with_dialog_elt
{
oc_list_elt listElt;
oc_file file;
} oc_file_open_with_dialog_elt;
typedef struct oc_file_open_with_dialog_result
{
oc_file_dialog_button button;
oc_file file;
oc_list selection;
} oc_file_open_with_dialog_result;
ORCA_API oc_file_open_with_dialog_result oc_file_open_with_dialog(oc_arena* arena, oc_file_access rights, oc_file_open_flags flags, oc_file_dialog_desc* desc);
#endif //__PLATFORM_IO_DIALOG_H_

View File

@ -5,12 +5,17 @@
* @date: 11/06/2023
*
*****************************************************************/
#include "platform_io_internal.h"
#include "platform_path.h"
#include "app/app.h"
#include "platform/platform_io_internal.h"
#include "platform/platform_path.h"
oc_file_table oc_globalFileTable = { 0 };
oc_file_table* oc_file_table_get_global()
{
return (&oc_globalFileTable);
}
oc_file_slot* oc_file_slot_alloc(oc_file_table* table)
{
oc_file_slot* slot = oc_list_pop_entry(&table->freeList, oc_file_slot, freeListElt);
@ -62,7 +67,7 @@ oc_file_slot* oc_file_slot_from_handle(oc_file_table* table, oc_file handle)
oc_io_cmp oc_io_wait_single_req(oc_io_req* req)
{
return (oc_io_wait_single_req_with_table(req, &oc_globalFileTable));
return (oc_io_wait_single_req_for_table(req, &oc_globalFileTable));
}
//-----------------------------------------------------------------------
@ -341,3 +346,100 @@ oc_io_cmp oc_io_open_at(oc_file_slot* atSlot, oc_io_req* req, oc_file_table* tab
}
return (cmp);
}
oc_file oc_file_open_with_request_for_table(oc_str8 path, oc_file_access rights, oc_file_open_flags flags, oc_file_table* table)
{
oc_arena_scope scratch = oc_scratch_begin();
oc_str8 msg = oc_str8_pushf(scratch.arena, "Application wants to access file '%.*s'.", (int)path.len, path.ptr);
oc_str8_list options = { 0 };
oc_str8_list_push(scratch.arena, &options, OC_STR8("Deny"));
oc_str8_list_push(scratch.arena, &options, OC_STR8("Accept"));
int res = oc_alert_popup(OC_STR8("File Access"), msg, options);
oc_file file = oc_file_nil();
if(res == 1)
{
oc_io_cmp cmp = { 0 };
oc_io_req req = {
.op = OC_IO_OPEN_AT,
.size = path.len,
.buffer = path.ptr,
.open.rights = rights,
.open.flags = flags
};
cmp = oc_io_open_at(0, &req, table);
if(cmp.error == OC_IO_OK)
{
file = cmp.handle;
}
}
oc_scratch_end(scratch);
return (file);
}
oc_file oc_file_open_with_request(oc_str8 path, oc_file_access rights, oc_file_open_flags flags)
{
return (oc_file_open_with_request_for_table(path, rights, flags, &oc_globalFileTable));
}
oc_file_open_with_dialog_result oc_file_open_with_dialog_for_table(oc_arena* arena,
oc_file_access rights,
oc_file_open_flags flags,
oc_file_dialog_desc* desc,
oc_file_table* table)
{
oc_arena_scope scratch = oc_scratch_begin_next(arena);
oc_file_dialog_result dialogResult = oc_file_dialog_for_table(scratch.arena, desc, table);
oc_file_open_with_dialog_result result = {
.button = dialogResult.button
};
if(dialogResult.button == OC_FILE_DIALOG_OK)
{
int i = 0;
oc_list_for(&dialogResult.selection.list, elt, oc_str8_elt, listElt)
{
oc_file file = oc_file_nil();
if(elt->string.len)
{
oc_io_req req = {
.op = OC_IO_OPEN_AT,
.size = elt->string.len,
.buffer = elt->string.ptr,
.open.rights = rights,
.open.flags = flags
};
oc_io_cmp cmp = oc_io_wait_single_req_for_table(&req, table);
file = cmp.handle;
}
oc_file_open_with_dialog_elt* resElt = oc_arena_push_type(arena, oc_file_open_with_dialog_elt);
memset(resElt, 0, sizeof(*resElt));
resElt->file = file;
oc_list_push_back(&result.selection, &resElt->listElt);
if(i == 0)
{
result.file = file;
i++;
}
}
}
oc_scratch_end(scratch);
return (result);
}
oc_file_open_with_dialog_result oc_file_open_with_dialog(oc_arena* arena, oc_file_access rights, oc_file_open_flags flags, oc_file_dialog_desc* desc)
{
return (oc_file_open_with_dialog_for_table(arena, rights, flags, desc, &oc_globalFileTable));
}

View File

@ -10,6 +10,7 @@
#include "platform.h"
#include "platform_io.h"
#include "platform_io_dialog.h"
#if OC_PLATFORM_MACOS || PLATFORM_LINUX
typedef int oc_file_desc;
@ -46,12 +47,22 @@ typedef struct oc_file_table
oc_list freeList;
} oc_file_table;
ORCA_API oc_file_table* oc_file_table_get_global();
oc_file_slot* oc_file_slot_alloc(oc_file_table* table);
void oc_file_slot_recycle(oc_file_table* table, oc_file_slot* slot);
oc_file oc_file_from_slot(oc_file_table* table, oc_file_slot* slot);
oc_file_slot* oc_file_slot_from_handle(oc_file_table* table, oc_file handle);
ORCA_API oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table);
ORCA_API oc_io_cmp oc_io_wait_single_req_for_table(oc_io_req* req, oc_file_table* table);
ORCA_API oc_file oc_file_open_with_request_for_table(oc_str8 path, oc_file_access rights, oc_file_open_flags flags, oc_file_table* table);
ORCA_API oc_file_open_with_dialog_result oc_file_open_with_dialog_for_table(oc_arena* arena,
oc_file_access rights,
oc_file_open_flags flags,
oc_file_dialog_desc* desc,
oc_file_table* table);
//-----------------------------------------------------------------------
// raw io primitives

View File

@ -54,7 +54,7 @@ oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path)
oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements)
{
//TODO: check if elements have ending/begining '/' ?
oc_str8 res = oc_str8_list_collate(arena, elements, OC_STR8("/"), OC_STR8("/"), (oc_str8){ 0 });
oc_str8 res = oc_str8_list_collate(arena, elements, OC_STR8(""), OC_STR8("/"), (oc_str8){ 0 });
return (res);
}
@ -90,6 +90,8 @@ oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath)
return (result);
}
#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA
oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath)
{
oc_str8_list list = { 0 };
@ -103,3 +105,5 @@ oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath)
oc_scratch_end(scratch);
return (path);
}
#endif

View File

@ -8,6 +8,7 @@
#ifndef __PLATFORM_PATH_H_
#define __PLATFORM_PATH_H_
#include"platform.h"
#include "util/strings.h"
/*NOTE:
@ -24,10 +25,14 @@ ORCA_API oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements);
ORCA_API oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath);
ORCA_API bool oc_path_is_absolute(oc_str8 path);
#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA
ORCA_API oc_str8 oc_path_executable(oc_arena* arena);
ORCA_API oc_str8 oc_path_canonical(oc_arena* arena, oc_str8 path);
// helper: gets the path from oc_path_executable() and appends relPath
ORCA_API oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath);
#endif
#endif //__PLATFORM_PATH_H_

View File

@ -518,7 +518,7 @@ oc_io_cmp oc_io_get_error(oc_file_slot* slot, oc_io_req* req)
return (cmp);
}
oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table)
oc_io_cmp oc_io_wait_single_req_for_table(oc_io_req* req, oc_file_table* table)
{
oc_io_cmp cmp = { 0 };

View File

@ -73,7 +73,7 @@ oc_io_error oc_io_raw_last_error()
return (error);
}
static oc_str16 win32_path_from_handle_null_terminated(oc_arena* arena, HANDLE handle)
oc_str16 win32_path_from_handle_null_terminated(oc_arena* arena, HANDLE handle)
{
oc_str16 res = { 0 };
@ -108,7 +108,7 @@ static oc_str16 win32_get_path_at_null_terminated(oc_arena* arena, oc_file_desc
oc_arena_scope scratch = oc_scratch_begin_next(arena);
oc_str16 dirPathW = win32_path_from_handle_null_terminated(scratch.arena, dirFd);
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
oc_str16 pathW = oc_win32_utf8_to_wide(scratch.arena, path);
if(dirPathW.len && pathW.len)
{
@ -194,7 +194,7 @@ oc_file_desc oc_io_raw_open_at(oc_file_desc dirFd, oc_str8 path, oc_file_access
}
oc_arena_scope scratch = oc_scratch_begin();
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
oc_str16 pathW = oc_win32_utf8_to_wide(scratch.arena, path);
if(dirFd == NULL || dirFd == INVALID_HANDLE_VALUE)
{
@ -505,7 +505,7 @@ static oc_io_cmp oc_io_get_error(oc_file_slot* slot, oc_io_req* req)
return (cmp);
}
oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table)
oc_io_cmp oc_io_wait_single_req_for_table(oc_io_req* req, oc_file_table* table)
{
oc_io_cmp cmp = { 0 };

View File

@ -13,7 +13,7 @@
bool oc_path_is_absolute(oc_str8 path)
{
oc_arena_scope scratch = oc_scratch_begin();
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
oc_str16 pathW = oc_win32_utf8_to_wide(scratch.arena, path);
bool result = !PathIsRelativeW(pathW.ptr);
oc_scratch_end(scratch);

View File

@ -11,7 +11,7 @@
#include "win32_string_helpers.h"
oc_str16 oc_win32_utf8_to_wide_null_terminated(oc_arena* arena, oc_str8 s)
oc_str16 oc_win32_utf8_to_wide(oc_arena* arena, oc_str8 s)
{
oc_str16 res = { 0 };
res.len = 1 + MultiByteToWideChar(CP_UTF8, 0, s.ptr, s.len, NULL, 0);

View File

@ -10,7 +10,7 @@
#include "util/strings.h"
oc_str16 oc_win32_utf8_to_wide_null_terminated(oc_arena* arena, oc_str8 s);
oc_str16 oc_win32_utf8_to_wide(oc_arena* arena, oc_str8 s);
oc_str8 oc_win32_wide_to_utf8(oc_arena* arena, oc_str16 s);
#endif // __WIN32_STRING_HELPERS_H_

View File

@ -19,7 +19,7 @@
oc_font orca_font_create(const char* resourcePath)
{
//NOTE(martin): create default font
//NOTE(martin): create default fonts
oc_str8 fontPath = oc_path_executable_relative(oc_scratch(), OC_STR8(resourcePath));
FILE* fontFile = fopen(fontPath.ptr, "r");
@ -49,11 +49,6 @@ oc_font orca_font_create(const char* resourcePath)
return (font);
}
oc_font oc_font_create_default()
{
return (orca_font_create("../resources/OpenSansLatinSubset.ttf"));
}
oc_runtime __orcaApp = { 0 };
oc_runtime* oc_runtime_get()
@ -61,43 +56,49 @@ oc_runtime* oc_runtime_get()
return (&__orcaApp);
}
oc_runtime_env* oc_runtime_env_get()
oc_wasm_env* oc_runtime_get_env()
{
return (&__orcaApp.runtime);
return (&__orcaApp.env);
}
void* oc_runtime_ptr_to_native(oc_runtime* orca, void* wasmPtr, u32 length)
oc_str8 oc_runtime_get_wasm_memory()
{
// We can't use the runtime's memory pointer directly because wasm3 embeds a
// header at the beginning of the block we give it.
u64 bufferIndex = (u64)wasmPtr & 0xffffffff;
u32 memSize = 0;
char* memory = (char*)m3_GetMemory(orca->runtime.m3Runtime, &memSize, 0);
oc_str8 mem = { 0 };
u32 size = 0;
mem.ptr = (char*)m3_GetMemory(__orcaApp.env.m3Runtime, &size, 0);
mem.len = size;
return (mem);
}
if(bufferIndex + length < memSize)
void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg)
{
M3ErrorInfo errInfo = { 0 };
m3_GetErrorInfo(runtime, &errInfo);
if(errInfo.message && res == errInfo.result)
{
char* nativePtr = memory + bufferIndex;
return nativePtr;
oc_abort_ext(file, function, line, "%s: %s (%s)", msg, res, errInfo.message);
}
return NULL;
}
void oc_runtime_window_set_title(oc_str8 title)
{
title.ptr = oc_runtime_ptr_to_native(oc_runtime_get(), title.ptr, title.len);
if(title.ptr)
else
{
oc_window_set_title(__orcaApp.window, title);
oc_abort_ext(file, function, line, "%s: %s", msg, res);
}
}
void oc_runtime_window_set_size(oc_vec2 size)
void oc_bridge_window_set_title(oc_wasm_str8 title)
{
oc_str8 nativeTitle = oc_wasm_str8_to_native(title);
if(nativeTitle.ptr)
{
oc_window_set_title(__orcaApp.window, nativeTitle);
}
}
void oc_bridge_window_set_size(oc_vec2 size)
{
oc_window_set_content_size(__orcaApp.window, size);
}
void oc_runtime_log(oc_log_level level,
void oc_bridge_log(oc_log_level level,
int fileLen,
char* file,
int functionLen,
@ -231,8 +232,8 @@ void orca_surface_render_commands(oc_surface surface,
{
oc_runtime* app = &__orcaApp;
char* memBase = app->runtime.wasmMemory.ptr;
u32 memSize = app->runtime.wasmMemory.committed;
char* memBase = app->env.wasmMemory.ptr;
u32 memSize = app->env.wasmMemory.committed;
if(((char*)primitives > memBase)
&& ((char*)primitives + primitiveCount * sizeof(oc_primitive) - memBase <= memSize)
&& ((char*)elements > memBase)
@ -334,9 +335,9 @@ char m3_type_to_tag(M3ValueType type)
}
}
void oc_runtime_env_init(oc_runtime_env* runtime)
void oc_wasm_env_init(oc_wasm_env* runtime)
{
memset(runtime, 0, sizeof(oc_runtime_env));
memset(runtime, 0, sizeof(oc_wasm_env));
oc_base_allocator* allocator = oc_base_allocator_default();
runtime->wasmMemory.committed = 0;
runtime->wasmMemory.reserved = 4ULL << 30;
@ -350,27 +351,11 @@ void oc_runtime_env_init(oc_runtime_env* runtime)
#include "wasmbind/io_api_bind_gen.c"
#include "wasmbind/surface_api_bind_gen.c"
void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg)
{
M3ErrorInfo errInfo = { 0 };
m3_GetErrorInfo(runtime, &errInfo);
if(errInfo.message && res == errInfo.result)
{
oc_abort_ext(file, function, line, "%s: %s (%s)", msg, res, errInfo.message);
}
else
{
oc_abort_ext(file, function, line, "%s: %s", msg, res);
}
}
#define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg)
i32 orca_runloop(void* user)
{
oc_runtime* app = &__orcaApp;
oc_runtime_env_init(&app->runtime);
oc_wasm_env_init(&app->env);
//NOTE: loads wasm module
const char* bundleNameCString = "module";
@ -386,42 +371,42 @@ i32 orca_runloop(void* user)
u64 wasmSize = ftell(file);
rewind(file);
app->runtime.wasmBytecode.len = wasmSize;
app->runtime.wasmBytecode.ptr = oc_malloc_array(char, wasmSize);
fread(app->runtime.wasmBytecode.ptr, 1, app->runtime.wasmBytecode.len, file);
app->env.wasmBytecode.len = wasmSize;
app->env.wasmBytecode.ptr = oc_malloc_array(char, wasmSize);
fread(app->env.wasmBytecode.ptr, 1, app->env.wasmBytecode.len, file);
fclose(file);
u32 stackSize = 65536;
app->runtime.m3Env = m3_NewEnvironment();
app->env.m3Env = m3_NewEnvironment();
app->runtime.m3Runtime = m3_NewRuntime(app->runtime.m3Env, stackSize, NULL);
app->env.m3Runtime = m3_NewRuntime(app->env.m3Env, stackSize, NULL);
//NOTE: host memory will be freed when runtime is freed.
m3_RuntimeSetMemoryCallbacks(app->runtime.m3Runtime, wasm_memory_resize_callback, wasm_memory_free_callback, &app->runtime.wasmMemory);
m3_RuntimeSetMemoryCallbacks(app->env.m3Runtime, oc_wasm_memory_resize_callback, oc_wasm_memory_free_callback, &app->env.wasmMemory);
M3Result res = m3_ParseModule(app->runtime.m3Env, &app->runtime.m3Module, (u8*)app->runtime.wasmBytecode.ptr, app->runtime.wasmBytecode.len);
M3Result res = m3_ParseModule(app->env.m3Env, &app->env.m3Module, (u8*)app->env.wasmBytecode.ptr, app->env.wasmBytecode.len);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't parse its web assembly module");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't parse its web assembly module");
}
res = m3_LoadModule(app->runtime.m3Runtime, app->runtime.m3Module);
res = m3_LoadModule(app->env.m3Runtime, app->env.m3Module);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't load its web assembly module into the runtime");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't load its web assembly module into the runtime");
}
m3_SetModuleName(app->runtime.m3Module, bundleNameCString);
m3_SetModuleName(app->env.m3Module, bundleNameCString);
oc_arena_clear(oc_scratch());
//NOTE: bind orca APIs
{
int err = 0;
err |= bindgen_link_core_api(app->runtime.m3Module);
err |= bindgen_link_surface_api(app->runtime.m3Module);
err |= bindgen_link_clock_api(app->runtime.m3Module);
err |= bindgen_link_io_api(app->runtime.m3Module);
err |= bindgen_link_gles_api(app->runtime.m3Module);
err |= manual_link_gles_api(app->runtime.m3Module);
err |= bindgen_link_core_api(app->env.m3Module);
err |= bindgen_link_surface_api(app->env.m3Module);
err |= bindgen_link_clock_api(app->env.m3Module);
err |= bindgen_link_io_api(app->env.m3Module);
err |= bindgen_link_gles_api(app->env.m3Module);
err |= manual_link_gles_api(app->env.m3Module);
if(err)
{
@ -429,10 +414,10 @@ i32 orca_runloop(void* user)
}
}
//NOTE: compile
res = m3_CompileModule(app->runtime.m3Module);
res = m3_CompileModule(app->env.m3Module);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't compile its web assembly module");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't compile its web assembly module");
}
//NOTE: Find and type check event handlers.
@ -440,7 +425,7 @@ i32 orca_runloop(void* user)
{
const oc_export_desc* desc = &OC_EXPORT_DESC[i];
IM3Function handler = 0;
m3_FindFunction(&handler, app->runtime.m3Runtime, desc->name.ptr);
m3_FindFunction(&handler, app->env.m3Runtime, desc->name.ptr);
if(handler)
{
@ -481,7 +466,7 @@ i32 orca_runloop(void* user)
if(checked)
{
app->runtime.exports[i] = handler;
app->env.exports[i] = handler;
}
else
{
@ -491,8 +476,8 @@ i32 orca_runloop(void* user)
}
//NOTE: get location of the raw event slot
IM3Global rawEventGlobal = m3_FindGlobal(app->runtime.m3Module, "oc_rawEvent");
app->runtime.rawEventOffset = (u32)rawEventGlobal->intValue;
IM3Global rawEventGlobal = m3_FindGlobal(app->env.m3Module, "oc_rawEvent");
app->env.rawEventOffset = (u32)rawEventGlobal->intValue;
//NOTE: preopen the app local root dir
{
@ -502,11 +487,11 @@ i32 orca_runloop(void* user)
.open.rights = OC_FILE_ACCESS_READ | OC_FILE_ACCESS_WRITE,
.size = localRootPath.len,
.buffer = localRootPath.ptr };
oc_io_cmp cmp = oc_io_wait_single_req_with_table(&req, &app->fileTable);
oc_io_cmp cmp = oc_io_wait_single_req_for_table(&req, &app->fileTable);
app->rootDir = cmp.handle;
}
IM3Function* exports = app->runtime.exports;
IM3Function* exports = app->env.exports;
//NOTE: call init handler
if(exports[OC_EXPORT_ON_INIT])
@ -514,7 +499,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_ON_INIT], 0, 0);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
@ -527,7 +512,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
@ -547,14 +532,14 @@ i32 orca_runloop(void* user)
if(exports[OC_EXPORT_RAW_EVENT])
{
#ifndef M3_BIG_ENDIAN
oc_event* eventPtr = (oc_event*)wasm_memory_offset_to_ptr(&app->runtime.wasmMemory, app->runtime.rawEventOffset);
oc_event* eventPtr = (oc_event*)oc_wasm_address_to_ptr(app->env.rawEventOffset, sizeof(oc_event));
memcpy(eventPtr, event, sizeof(*event));
const void* args[1] = { &app->runtime.rawEventOffset };
const void* args[1] = { &app->env.rawEventOffset };
M3Result res = m3_Call(exports[OC_EXPORT_RAW_EVENT], 1, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
#else
oc_log_error("oc_on_raw_event() is not supported on big endian platforms");
@ -565,7 +550,7 @@ i32 orca_runloop(void* user)
{
case OC_EVENT_WINDOW_CLOSE:
{
oc_request_quit();
oc_request_quit();
}
break;
@ -581,7 +566,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
}
@ -598,7 +583,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
}
@ -611,7 +596,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
}
@ -626,7 +611,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_MOVE], 4, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
}
@ -649,7 +634,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 1, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
}
@ -661,7 +646,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 1, args);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
}
@ -680,7 +665,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_REFRESH], 0, 0);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}
@ -837,7 +822,7 @@ i32 orca_runloop(void* user)
M3Result res = m3_Call(exports[OC_EXPORT_TERMINATE], 0, 0);
if(res)
{
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
}
}

View File

@ -27,7 +27,8 @@
X(OC_EXPORT_FRAME_REFRESH, "oc_on_frame_refresh", "", "") \
X(OC_EXPORT_FRAME_RESIZE, "oc_on_resize", "", "ii") \
X(OC_EXPORT_RAW_EVENT, "oc_on_raw_event", "", "i") \
X(OC_EXPORT_TERMINATE, "oc_on_terminate", "", "")
X(OC_EXPORT_TERMINATE, "oc_on_terminate", "", "") \
X(OC_EXPORT_ARENA_PUSH, "oc_arena_push_stub", "i", "iI")
typedef enum
{
@ -53,18 +54,18 @@ const oc_export_desc OC_EXPORT_DESC[] = {
#undef OC_STR8_LIT
};
typedef struct wasm_memory
typedef struct oc_wasm_memory
{
char* ptr;
u64 reserved;
u64 committed;
} wasm_memory;
} oc_wasm_memory;
typedef struct oc_runtime_env
typedef struct oc_wasm_env
{
oc_str8 wasmBytecode;
wasm_memory wasmMemory;
oc_wasm_memory wasmMemory;
// wasm3 data
IM3Environment m3Env;
@ -73,7 +74,7 @@ typedef struct oc_runtime_env
IM3Function exports[OC_EXPORT_COUNT];
u32 rawEventOffset;
} oc_runtime_env;
} oc_wasm_env;
typedef struct log_entry
{
@ -111,21 +112,22 @@ typedef struct oc_debug_overlay
typedef struct oc_runtime
{
bool quit;
bool quit;
oc_window window;
oc_debug_overlay debugOverlay;
oc_file_table fileTable;
oc_file rootDir;
oc_runtime_env runtime;
oc_debug_overlay debugOverlay;
oc_wasm_env env;
} oc_runtime;
oc_runtime* oc_runtime_get();
oc_runtime_env* oc_runtime_env_get();
oc_runtime* oc_runtime_get(void);
oc_wasm_env* oc_runtime_get_env(void);
oc_str8 oc_runtime_get_wasm_memory(void);
void* oc_runtime_ptr_to_native(oc_runtime* runtime, void* wasmPtr, u32 length);
void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg);
#define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg)
#endif //__RUNTIME_H_

View File

@ -7,15 +7,17 @@
*****************************************************************/
#include "platform/platform_io_internal.h"
#include "runtime.h"
#include "runtime_memory.h"
oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq)
oc_io_cmp oc_bridge_io_single_rect(oc_io_req* wasmReq)
{
oc_runtime* orca = oc_runtime_get();
oc_io_cmp cmp = { 0 };
oc_io_req req = *wasmReq;
void* buffer = oc_runtime_ptr_to_native(orca, req.buffer, req.size);
//TODO have a separate oc_wasm_io_req struct
void* buffer = oc_wasm_address_to_ptr((oc_wasm_addr)(uintptr_t)req.buffer, req.size);
if(buffer)
{
@ -30,7 +32,7 @@ oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq)
req.open.flags |= OC_FILE_OPEN_RESTRICT;
}
}
cmp = oc_io_wait_single_req_with_table(&req, &orca->fileTable);
cmp = oc_io_wait_single_req_for_table(&req, &orca->fileTable);
}
else
{
@ -39,3 +41,105 @@ oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq)
return (cmp);
}
oc_file oc_file_open_with_request_bridge(oc_wasm_str8 path, oc_file_access rights, oc_file_open_flags flags)
{
oc_file file = oc_file_nil();
oc_runtime* orca = oc_runtime_get();
oc_str8 nativePath = oc_wasm_str8_to_native(path);
if(nativePath.ptr)
{
file = oc_file_open_with_request_for_table(nativePath, rights, flags, &orca->fileTable);
}
return (file);
}
typedef struct oc_wasm_file_dialog_desc
{
oc_file_dialog_kind kind;
oc_file_dialog_flags flags;
oc_wasm_str8 title;
oc_wasm_str8 okLabel;
oc_file startAt;
oc_wasm_str8 startPath;
oc_wasm_str8_list filters;
} oc_wasm_file_dialog_desc;
typedef struct oc_wasm_file_open_with_dialog_elt
{
oc_wasm_list_elt listElt;
oc_file file;
} oc_wasm_file_open_with_dialog_elt;
typedef struct oc_wasm_file_open_with_dialog_result
{
oc_file_dialog_button button;
oc_file file;
oc_wasm_list selection;
} oc_wasm_file_open_with_dialog_result;
oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(oc_wasm_addr wasmArena,
oc_file_access rights,
oc_file_open_flags flags,
oc_wasm_file_dialog_desc* desc)
{
oc_runtime* orca = oc_runtime_get();
oc_arena_scope scratch = oc_scratch_begin();
oc_file_dialog_desc nativeDesc = {
.kind = desc->kind,
.flags = desc->flags
};
nativeDesc.title.ptr = oc_wasm_address_to_ptr(desc->title.ptr, desc->title.len);
nativeDesc.title.len = desc->title.len;
nativeDesc.okLabel.ptr = oc_wasm_address_to_ptr(desc->okLabel.ptr, desc->okLabel.len);
nativeDesc.okLabel.len = desc->okLabel.len;
if(oc_file_is_nil(desc->startAt) && desc->startPath.len)
{
nativeDesc.startAt = orca->rootDir;
}
else
{
nativeDesc.startAt = desc->startAt;
}
nativeDesc.startPath.ptr = oc_wasm_address_to_ptr(desc->startPath.ptr, desc->startPath.len);
nativeDesc.startPath.len = desc->startPath.len;
u32 eltIndex = desc->filters.list.first;
while(eltIndex)
{
oc_wasm_str8_elt* elt = oc_wasm_address_to_ptr(eltIndex, sizeof(oc_wasm_str8_elt));
oc_str8 filter = oc_wasm_str8_to_native(elt->string);
oc_str8_list_push(scratch.arena, &nativeDesc.filters, filter);
oc_log_info("filter: %.*s\n", (int)filter.len, filter.ptr);
eltIndex = elt->listElt.next;
}
oc_file_open_with_dialog_result nativeResult = oc_file_open_with_dialog_for_table(scratch.arena, rights, flags, &nativeDesc, &orca->fileTable);
oc_wasm_file_open_with_dialog_result result = {
.button = nativeResult.button,
.file = nativeResult.file
};
oc_list_for(&nativeResult.selection, elt, oc_file_open_with_dialog_elt, listElt)
{
oc_wasm_file_open_with_dialog_elt* wasmElt = oc_wasm_arena_push(wasmArena, sizeof(oc_wasm_file_open_with_dialog_elt));
wasmElt->file = elt->file;
oc_wasm_list_push_back(&result.selection, &wasmElt->listElt);
}
oc_scratch_end(scratch);
return (result);
}

View File

@ -7,10 +7,11 @@
*****************************************************************/
#include "runtime.h"
#include "runtime_memory.h"
void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
void* oc_wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
{
wasm_memory* memory = (wasm_memory*)userData;
oc_wasm_memory* memory = (oc_wasm_memory*)userData;
if(memory->committed >= size)
{
@ -32,35 +33,119 @@ void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
}
}
void wasm_memory_free_callback(void* p, void* userData)
void oc_wasm_memory_free_callback(void* p, void* userData)
{
wasm_memory* memory = (wasm_memory*)userData;
oc_wasm_memory* memory = (oc_wasm_memory*)userData;
oc_base_allocator* allocator = oc_base_allocator_default();
oc_base_release(allocator, memory->ptr, memory->reserved);
memset(memory, 0, sizeof(wasm_memory));
memset(memory, 0, sizeof(oc_wasm_memory));
}
extern u32 oc_mem_grow(u64 size)
{
oc_runtime_env* runtime = oc_runtime_env_get();
wasm_memory* memory = &runtime->wasmMemory;
oc_wasm_env* env = oc_runtime_get_env();
oc_wasm_memory* memory = &env->wasmMemory;
size = oc_align_up_pow2(size, d_m3MemPageSize);
u64 totalSize = size + m3_GetMemorySize(runtime->m3Runtime);
u64 totalSize = size + m3_GetMemorySize(env->m3Runtime);
u32 addr = memory->committed;
//NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because
// wasm3 doesn't allow resizing the memory directly
M3Result res = ResizeMemory(runtime->m3Runtime, totalSize / d_m3MemPageSize);
M3Result res = ResizeMemory(env->m3Runtime, totalSize / d_m3MemPageSize);
return (addr);
}
void* wasm_memory_offset_to_ptr(wasm_memory* memory, u32 offset)
void* oc_wasm_address_to_ptr(oc_wasm_addr addr, oc_wasm_size size)
{
M3MemoryHeader* header = (M3MemoryHeader*)(memory->ptr);
OC_DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length");
return memory->ptr + sizeof(M3MemoryHeader) + offset;
oc_str8 mem = oc_runtime_get_wasm_memory();
OC_ASSERT(addr + size < mem.len, "Object overflows wasm memory");
void* ptr = (addr == 0) ? 0 : mem.ptr + addr;
return (ptr);
}
oc_wasm_addr oc_wasm_address_from_ptr(void* ptr, oc_wasm_size size)
{
oc_wasm_addr addr = 0;
if(ptr != 0)
{
oc_str8 mem = oc_runtime_get_wasm_memory();
OC_ASSERT((char*)ptr > mem.ptr && (((char*)ptr - mem.ptr) + size < mem.len), "Object overflows wasm memory");
addr = (char*)ptr - mem.ptr;
}
return (addr);
}
//------------------------------------------------------------------------------------
// oc_wasm_list helpers
//------------------------------------------------------------------------------------
void oc_wasm_list_push(oc_wasm_list* list, oc_wasm_list_elt* elt)
{
elt->next = list->first;
elt->prev = 0;
oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt));
if(list->first)
{
oc_wasm_list_elt* first = oc_wasm_address_to_ptr(list->first, sizeof(oc_wasm_list_elt));
first->prev = eltAddr;
}
else
{
list->last = eltAddr;
}
list->first = eltAddr;
}
void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt)
{
elt->prev = list->last;
elt->next = 0;
oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt));
if(list->last)
{
oc_wasm_list_elt* last = oc_wasm_address_to_ptr(list->last, sizeof(oc_wasm_list_elt));
last->next = eltAddr;
}
else
{
list->first = eltAddr;
}
list->last = eltAddr;
}
//------------------------------------------------------------------------------------
// Wasm arenas helpers
//------------------------------------------------------------------------------------
void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size)
{
oc_wasm_env* env = oc_runtime_get_env();
oc_wasm_addr retValues[1] = { 0 };
const void* retPointers[1] = { (void*)&retValues[0] };
const void* args[2] = { &arena, &size };
M3Result res = m3_Call(env->exports[OC_EXPORT_ARENA_PUSH], 2, args);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
res = m3_GetResults(env->exports[OC_EXPORT_ARENA_PUSH], 1, retPointers);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
void* ptr = oc_wasm_address_to_ptr(retValues[0], size);
return (ptr);
}

101
src/runtime_memory.h Normal file
View File

@ -0,0 +1,101 @@
/************************************************************/ /**
*
* @file: runtime_memory.h
* @author: Martin Fouilleul
* @date: 02/09/2023
*
*****************************************************************/
#ifndef __RUNTIME_MEMORY_H_
#define __RUNTIME_MEMORY_H_
#include "runtime.h"
typedef u32 oc_wasm_addr;
typedef u32 oc_wasm_size;
void* oc_wasm_address_to_ptr(oc_wasm_addr addr, oc_wasm_size size);
oc_wasm_addr oc_wasm_address_from_ptr(void* ptr, oc_wasm_size size);
//------------------------------------------------------------------------------------
// oc_wasm_list helpers
//------------------------------------------------------------------------------------
typedef struct oc_wasm_list
{
u32 first;
u32 last;
} oc_wasm_list;
typedef struct oc_wasm_list_elt
{
u32 prev;
u32 next;
} oc_wasm_list_elt;
bool oc_wasm_list_empty(oc_wasm_list* list);
#define oc_wasm_list_begin(list) oc_wasm_address_to_ptr(list->first, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_end(list) oc_wasm_address_to_ptr(list->last, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_next(elt) oc_wasm_address_to_ptr((elt)->next, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_prev(elt) oc_wasm_address_to_ptr((elt)->prev, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_entry(ptr, type, member) \
oc_container_of(ptr, type, member)
#define oc_wasm_list_next_entry(list, elt, type, member) \
(((elt)->member.next != 0) ? oc_wasm_list_entry(oc_wasm_list_next((elt)->member), type, member) : 0)
#define oc_wasm_list_prev_entry(list, elt, type, member) \
(((elt)->member.prev != 0) ? oc_wasm_list_entry(oc_wasm_list_prev((elt)->member), type, member) : 0)
#define oc_wasm_list_checked_entry(elt, type, member) \
(((elt) != 0) ? oc_wasm_list_entry(elt, type, member) : 0)
#define oc_wasm_list_first_entry(list, type, member) \
(oc_wasm_list_checked_entry(oc_wasm_list_begin(list), type, member))
#define oc_wasm_list_last_entry(list, type, member) \
(oc_wasm_list_checked_entry(oc_wasm_list_last(list), type, member))
#define oc_wasm_list_for(list, elt, type, member) \
for(type* elt = oc_wasm_list_checked_entry(oc_wasm_list_begin(list), type, member); \
elt != 0; \
elt = oc_wasm_list_checked_entry(oc_wasm_list_next((elt)->member), type, member))
void oc_wasm_list_push(oc_wasm_list* list, oc_wasm_list_elt* elt);
void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt);
//------------------------------------------------------------------------------------
// oc_wasm_str8 helpers
//------------------------------------------------------------------------------------
typedef struct oc_wasm_str8
{
u64 len;
u32 ptr;
} oc_wasm_str8;
typedef struct oc_wasm_str8_elt
{
oc_wasm_list_elt listElt;
oc_wasm_str8 string;
} oc_wasm_str8_elt;
typedef struct oc_wasm_str8_list
{
oc_wasm_list list;
u64 eltCount;
u64 len;
} oc_wasm_str8_list;
#define oc_wasm_str8_to_native(wasmString) ((oc_str8){ .ptr = oc_wasm_address_to_ptr(wasmString.ptr, wasmString.len), .len = wasmString.len })
//------------------------------------------------------------------------------------
// Wasm arenas helpers
//------------------------------------------------------------------------------------
void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size);
#endif //__RUNTIME_MEMORY_H_

View File

@ -1338,7 +1338,7 @@ void oc_ui_draw_box(oc_ui_box* box)
bool draw = true;
{
oc_rect clip = oc_clip();
oc_rect clip = oc_clip_top();
oc_rect expRect = {
box->rect.x - 0.5 * style->borderSize,
box->rect.y - 0.5 * style->borderSize,

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,12 @@
#include "util/debug.h"
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
//-------------------------------------------------------------------------
// Intrusive linked lists
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Intrusive linked lists
//-------------------------------------------------------------------------
#define oc_list_entry(ptr, type, member) \
oc_container_of(ptr, type, member)
@ -62,162 +61,162 @@ extern "C"
#define oc_list_pop_entry(list, type, member) (oc_list_empty(list) ? 0 : oc_list_entry(oc_list_pop(list), type, member))
typedef struct oc_list_elt oc_list_elt;
typedef struct oc_list_elt oc_list_elt;
struct oc_list_elt
{
oc_list_elt* next;
oc_list_elt* prev;
};
struct oc_list_elt
{
oc_list_elt* prev;
oc_list_elt* next;
};
typedef struct oc_list
{
oc_list_elt* first;
oc_list_elt* last;
} oc_list;
typedef struct oc_list
{
oc_list_elt* first;
oc_list_elt* last;
} oc_list;
static inline void oc_list_init(oc_list* list)
static inline void oc_list_init(oc_list* list)
{
list->first = list->last = 0;
}
static inline oc_list_elt* oc_list_begin(oc_list* list)
{
return (list->first);
}
static inline oc_list_elt* oc_list_end(oc_list* list)
{
return (0);
}
static inline oc_list_elt* oc_list_last(oc_list* list)
{
return (list->last);
}
static inline void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt)
{
elt->prev = afterElt;
elt->next = afterElt->next;
if(afterElt->next)
{
list->first = list->last = 0;
afterElt->next->prev = elt;
}
static inline oc_list_elt* oc_list_begin(oc_list* list)
else
{
return (list->first);
list->last = elt;
}
afterElt->next = elt;
static inline oc_list_elt* oc_list_end(oc_list* list)
OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert(): can't insert an element into itself");
}
static inline void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt)
{
elt->next = beforeElt;
elt->prev = beforeElt->prev;
if(beforeElt->prev)
{
beforeElt->prev->next = elt;
}
else
{
list->first = elt;
}
beforeElt->prev = elt;
OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert_before(): can't insert an element into itself");
}
static inline void oc_list_remove(oc_list* list, oc_list_elt* elt)
{
if(elt->prev)
{
elt->prev->next = elt->next;
}
else
{
OC_DEBUG_ASSERT(list->first == elt);
list->first = elt->next;
}
if(elt->next)
{
elt->next->prev = elt->prev;
}
else
{
OC_DEBUG_ASSERT(list->last == elt);
list->last = elt->prev;
}
elt->prev = elt->next = 0;
}
static inline void oc_list_push(oc_list* list, oc_list_elt* elt)
{
elt->next = list->first;
elt->prev = 0;
if(list->first)
{
list->first->prev = elt;
}
else
{
list->last = elt;
}
list->first = elt;
}
static inline oc_list_elt* oc_list_pop(oc_list* list)
{
oc_list_elt* elt = oc_list_begin(list);
if(elt != oc_list_end(list))
{
oc_list_remove(list, elt);
return (elt);
}
else
{
return (0);
}
}
static inline oc_list_elt* oc_list_last(oc_list* list)
static inline void oc_list_push_back(oc_list* list, oc_list_elt* elt)
{
elt->prev = list->last;
elt->next = 0;
if(list->last)
{
return (list->last);
list->last->next = elt;
}
static inline void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt)
else
{
elt->prev = afterElt;
elt->next = afterElt->next;
if(afterElt->next)
{
afterElt->next->prev = elt;
}
else
{
list->last = elt;
}
afterElt->next = elt;
OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert(): can't insert an element into itself");
}
static inline void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt)
{
elt->next = beforeElt;
elt->prev = beforeElt->prev;
if(beforeElt->prev)
{
beforeElt->prev->next = elt;
}
else
{
list->first = elt;
}
beforeElt->prev = elt;
OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert_before(): can't insert an element into itself");
}
static inline void oc_list_remove(oc_list* list, oc_list_elt* elt)
{
if(elt->prev)
{
elt->prev->next = elt->next;
}
else
{
OC_DEBUG_ASSERT(list->first == elt);
list->first = elt->next;
}
if(elt->next)
{
elt->next->prev = elt->prev;
}
else
{
OC_DEBUG_ASSERT(list->last == elt);
list->last = elt->prev;
}
elt->prev = elt->next = 0;
}
static inline void oc_list_push(oc_list* list, oc_list_elt* elt)
{
elt->next = list->first;
elt->prev = 0;
if(list->first)
{
list->first->prev = elt;
}
else
{
list->last = elt;
}
list->first = elt;
}
static inline oc_list_elt* oc_list_pop(oc_list* list)
{
oc_list_elt* elt = oc_list_begin(list);
if(elt != oc_list_end(list))
{
oc_list_remove(list, elt);
return (elt);
}
else
{
return (0);
}
}
static inline void oc_list_push_back(oc_list* list, oc_list_elt* elt)
{
elt->prev = list->last;
elt->next = 0;
if(list->last)
{
list->last->next = elt;
}
else
{
list->first = elt;
}
list->last = elt;
}
list->last = elt;
}
#define oc_list_append(a, b) oc_list_push_back(a, b)
static inline oc_list_elt* oc_list_pop_back(oc_list* list)
static inline oc_list_elt* oc_list_pop_back(oc_list* list)
{
oc_list_elt* elt = oc_list_last(list);
if(elt != oc_list_end(list))
{
oc_list_elt* elt = oc_list_last(list);
if(elt != oc_list_end(list))
{
oc_list_remove(list, elt);
return (elt);
}
else
{
return (0);
}
oc_list_remove(list, elt);
return (elt);
}
else
{
return (0);
}
}
static inline bool oc_list_empty(oc_list* list)
{
return (list->first == 0 || list->last == 0);
}
static inline bool oc_list_empty(oc_list* list)
{
return (list->first == 0 || list->last == 0);
}
#ifdef __cplusplus
} // extern "C"

View File

@ -241,7 +241,7 @@ ORCA_API oc_arena* oc_scratch_next(oc_arena* used)
return (res);
}
ORCA_API oc_arena_scope oc_scratch_begin()
ORCA_API oc_arena_scope oc_scratch_begin(void)
{
oc_arena* scratch = oc_scratch();
oc_arena_scope scope = oc_arena_scope_begin(scratch);

View File

@ -14,94 +14,93 @@
#include "util/typedefs.h"
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
//--------------------------------------------------------------------------------
//NOTE(martin): memory arena
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//NOTE(martin): memory arena
//--------------------------------------------------------------------------------
typedef struct oc_arena_chunk
{
oc_list_elt listElt;
char* ptr;
u64 offset;
u64 committed;
u64 cap;
} oc_arena_chunk;
typedef struct oc_arena_chunk
{
oc_list_elt listElt;
char* ptr;
u64 offset;
u64 committed;
u64 cap;
} oc_arena_chunk;
typedef struct oc_arena
{
oc_base_allocator* base;
oc_list chunks;
oc_arena_chunk* currentChunk;
typedef struct oc_arena
{
oc_base_allocator* base;
oc_list chunks;
oc_arena_chunk* currentChunk;
} oc_arena;
} oc_arena;
typedef struct oc_arena_scope
{
oc_arena* arena;
oc_arena_chunk* chunk;
u64 offset;
} oc_arena_scope;
typedef struct oc_arena_scope
{
oc_arena* arena;
oc_arena_chunk* chunk;
u64 offset;
} oc_arena_scope;
typedef struct oc_arena_options
{
oc_base_allocator* base;
u64 reserve;
} oc_arena_options;
typedef struct oc_arena_options
{
oc_base_allocator* base;
u64 reserve;
} oc_arena_options;
ORCA_API void oc_arena_init(oc_arena* arena);
ORCA_API void oc_arena_init_with_options(oc_arena* arena, oc_arena_options* options);
ORCA_API void oc_arena_cleanup(oc_arena* arena);
ORCA_API void oc_arena_init(oc_arena* arena);
ORCA_API void oc_arena_init_with_options(oc_arena* arena, oc_arena_options* options);
ORCA_API void oc_arena_cleanup(oc_arena* arena);
ORCA_API void* oc_arena_push(oc_arena* arena, u64 size);
ORCA_API void oc_arena_clear(oc_arena* arena);
ORCA_API void* oc_arena_push(oc_arena* arena, u64 size);
ORCA_API void oc_arena_clear(oc_arena* arena);
ORCA_API oc_arena_scope oc_arena_scope_begin(oc_arena* arena);
ORCA_API void oc_arena_scope_end(oc_arena_scope scope);
ORCA_API oc_arena_scope oc_arena_scope_begin(oc_arena* arena);
ORCA_API void oc_arena_scope_end(oc_arena_scope scope);
#define oc_arena_push_type(arena, type) ((type*)oc_arena_push(arena, sizeof(type)))
#define oc_arena_push_array(arena, type, count) ((type*)oc_arena_push(arena, sizeof(type) * (count)))
//--------------------------------------------------------------------------------
//NOTE(martin): memory pool
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//NOTE(martin): memory pool
//--------------------------------------------------------------------------------
//TODO: we could probably remove pool. Most of the time we construct pool on top of
// arenas "manually" with different free lists per object types...
//TODO: we could probably remove pool. Most of the time we construct pool on top of
// arenas "manually" with different free lists per object types...
typedef struct oc_pool
{
oc_arena arena;
oc_list freeList;
u64 blockSize;
} oc_pool;
typedef struct oc_pool
{
oc_arena arena;
oc_list freeList;
u64 blockSize;
} oc_pool;
typedef struct oc_pool_options
{
oc_base_allocator* base;
u64 reserve;
} oc_pool_options;
typedef struct oc_pool_options
{
oc_base_allocator* base;
u64 reserve;
} oc_pool_options;
ORCA_API void oc_pool_init(oc_pool* pool, u64 blockSize);
ORCA_API void oc_pool_init_with_options(oc_pool* pool, u64 blockSize, oc_pool_options* options);
ORCA_API void oc_pool_cleanup(oc_pool* pool);
ORCA_API void oc_pool_init(oc_pool* pool, u64 blockSize);
ORCA_API void oc_pool_init_with_options(oc_pool* pool, u64 blockSize, oc_pool_options* options);
ORCA_API void oc_pool_cleanup(oc_pool* pool);
ORCA_API void* oc_pool_alloc(oc_pool* pool);
ORCA_API void oc_pool_recycle(oc_pool* pool, void* ptr);
ORCA_API void oc_pool_clear(oc_pool* pool);
ORCA_API void* oc_pool_alloc(oc_pool* pool);
ORCA_API void oc_pool_recycle(oc_pool* pool, void* ptr);
ORCA_API void oc_pool_clear(oc_pool* pool);
#define oc_pool_alloc_type(arena, type) ((type*)oc_pool_alloc(arena))
//--------------------------------------------------------------------------------
//NOTE(martin): per-thread implicit scratch arena
//--------------------------------------------------------------------------------
ORCA_API oc_arena* oc_scratch();
ORCA_API oc_arena* oc_scratch_next(oc_arena* used);
ORCA_API oc_arena_scope oc_scratch_begin();
ORCA_API oc_arena_scope oc_scratch_begin_next(oc_arena* used);
//--------------------------------------------------------------------------------
//NOTE(martin): per-thread implicit scratch arena
//--------------------------------------------------------------------------------
ORCA_API oc_arena* oc_scratch();
ORCA_API oc_arena* oc_scratch_next(oc_arena* used);
ORCA_API oc_arena_scope oc_scratch_begin(void);
ORCA_API oc_arena_scope oc_scratch_begin_next(oc_arena* used);
#define oc_scratch_end(scope) oc_arena_scope_end(scope)

View File

@ -17,11 +17,10 @@
#include <string.h>
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
/*NOTE:
/*NOTE:
By convention, functions that take an arena and return a string slice allocated on
this arena, always allocate one more element and null-terminate the string. This is
done so we can pass those strings directly to C APIs that requires C strings without
@ -31,14 +30,14 @@ extern "C"
into the original string. Only the _list nodes_ are allocated on the arena.
*/
//----------------------------------------------------------------------------------
// u8 strings
//----------------------------------------------------------------------------------
typedef struct oc_str8
{
u64 len;
char* ptr;
} oc_str8;
//----------------------------------------------------------------------------------
// u8 strings
//----------------------------------------------------------------------------------
typedef struct oc_str8
{
u64 len;
char* ptr;
} oc_str8;
#define OC_STR8(s) ((oc_str8){ .len = (s) ? strlen(s) : 0, .ptr = (char*)s })
@ -51,109 +50,109 @@ extern "C"
#define oc_str8_lp(s) ((s).len), ((s).ptr)
#define oc_str8_ip(s) (int)oc_str8_lp(s)
ORCA_API oc_str8 oc_str8_from_buffer(u64 len, char* buffer);
ORCA_API oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end);
ORCA_API oc_str8 oc_str8_from_buffer(u64 len, char* buffer);
ORCA_API oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end);
ORCA_API oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer);
ORCA_API oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str);
ORCA_API oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s);
ORCA_API oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end);
ORCA_API oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer);
ORCA_API oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str);
ORCA_API oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s);
ORCA_API oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end);
ORCA_API oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args);
ORCA_API oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...);
ORCA_API oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args);
ORCA_API oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...);
ORCA_API int oc_str8_cmp(oc_str8 s1, oc_str8 s2);
ORCA_API int oc_str8_cmp(oc_str8 s1, oc_str8 s2);
ORCA_API char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string);
ORCA_API char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string);
//----------------------------------------------------------------------------------
// string lists
//----------------------------------------------------------------------------------
typedef struct oc_str8_elt
{
oc_list_elt listElt;
oc_str8 string;
} oc_str8_elt;
//----------------------------------------------------------------------------------
// string lists
//----------------------------------------------------------------------------------
typedef struct oc_str8_elt
{
oc_list_elt listElt;
oc_str8 string;
} oc_str8_elt;
typedef struct oc_str8_list
{
oc_list list;
u64 eltCount;
u64 len;
} oc_str8_list;
typedef struct oc_str8_list
{
oc_list list;
u64 eltCount;
u64 len;
} oc_str8_list;
ORCA_API void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str);
ORCA_API void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...);
ORCA_API void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str);
ORCA_API void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...);
ORCA_API oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix);
ORCA_API oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list);
ORCA_API oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators);
ORCA_API oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix);
ORCA_API oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list);
ORCA_API oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators);
//----------------------------------------------------------------------------------
// u16 strings
//----------------------------------------------------------------------------------
typedef struct oc_str16
{
u64 len;
u16* ptr;
} oc_str16;
//----------------------------------------------------------------------------------
// u16 strings
//----------------------------------------------------------------------------------
typedef struct oc_str16
{
u64 len;
u16* ptr;
} oc_str16;
ORCA_API oc_str16 oc_str16_from_buffer(u64 len, u16* buffer);
ORCA_API oc_str16 oc_str16_slice(oc_str16 s, u64 start, u64 end);
ORCA_API oc_str16 oc_str16_from_buffer(u64 len, u16* buffer);
ORCA_API oc_str16 oc_str16_slice(oc_str16 s, u64 start, u64 end);
ORCA_API oc_str16 oc_str16_push_buffer(oc_arena* arena, u64 len, u16* buffer);
ORCA_API oc_str16 oc_str16_push_copy(oc_arena* arena, oc_str16 s);
ORCA_API oc_str16 oc_str16_push_slice(oc_arena* arena, oc_str16 s, u64 start, u64 end);
ORCA_API oc_str16 oc_str16_push_buffer(oc_arena* arena, u64 len, u16* buffer);
ORCA_API oc_str16 oc_str16_push_copy(oc_arena* arena, oc_str16 s);
ORCA_API oc_str16 oc_str16_push_slice(oc_arena* arena, oc_str16 s, u64 start, u64 end);
typedef struct oc_str16_elt
{
oc_list_elt listElt;
oc_str16 string;
} oc_str16_elt;
typedef struct oc_str16_elt
{
oc_list_elt listElt;
oc_str16 string;
} oc_str16_elt;
typedef struct oc_str16_list
{
oc_list list;
u64 eltCount;
u64 len;
} oc_str16_list;
typedef struct oc_str16_list
{
oc_list list;
u64 eltCount;
u64 len;
} oc_str16_list;
ORCA_API void oc_str16_list_push(oc_arena* arena, oc_str16_list* list, oc_str16 str);
ORCA_API oc_str16 oc_str16_list_join(oc_arena* arena, oc_str16_list list);
ORCA_API oc_str16_list oc_str16_split(oc_arena* arena, oc_str16 str, oc_str16_list separators);
ORCA_API void oc_str16_list_push(oc_arena* arena, oc_str16_list* list, oc_str16 str);
ORCA_API oc_str16 oc_str16_list_join(oc_arena* arena, oc_str16_list list);
ORCA_API oc_str16_list oc_str16_split(oc_arena* arena, oc_str16 str, oc_str16_list separators);
//----------------------------------------------------------------------------------
// u32 strings
//----------------------------------------------------------------------------------
typedef struct oc_str32
{
u64 len;
u32* ptr;
} oc_str32;
//----------------------------------------------------------------------------------
// u32 strings
//----------------------------------------------------------------------------------
typedef struct oc_str32
{
u64 len;
u32* ptr;
} oc_str32;
ORCA_API oc_str32 oc_str32_from_buffer(u64 len, u32* buffer);
ORCA_API oc_str32 oc_str32_slice(oc_str32 s, u64 start, u64 end);
ORCA_API oc_str32 oc_str32_from_buffer(u64 len, u32* buffer);
ORCA_API oc_str32 oc_str32_slice(oc_str32 s, u64 start, u64 end);
ORCA_API oc_str32 oc_str32_push_buffer(oc_arena* arena, u64 len, u32* buffer);
ORCA_API oc_str32 oc_str32_push_copy(oc_arena* arena, oc_str32 s);
ORCA_API oc_str32 oc_str32_push_slice(oc_arena* arena, oc_str32 s, u64 start, u64 end);
ORCA_API oc_str32 oc_str32_push_buffer(oc_arena* arena, u64 len, u32* buffer);
ORCA_API oc_str32 oc_str32_push_copy(oc_arena* arena, oc_str32 s);
ORCA_API oc_str32 oc_str32_push_slice(oc_arena* arena, oc_str32 s, u64 start, u64 end);
typedef struct oc_str32_elt
{
oc_list_elt listElt;
oc_str32 string;
} oc_str32_elt;
typedef struct oc_str32_elt
{
oc_list_elt listElt;
oc_str32 string;
} oc_str32_elt;
typedef struct oc_str32_list
{
oc_list list;
u64 eltCount;
u64 len;
} oc_str32_list;
typedef struct oc_str32_list
{
oc_list list;
u64 eltCount;
u64 len;
} oc_str32_list;
ORCA_API void oc_str32_list_push(oc_arena* arena, oc_str32_list* list, oc_str32 str);
ORCA_API oc_str32 oc_str32_list_join(oc_arena* arena, oc_str32_list list);
ORCA_API oc_str32_list oc_str32_split(oc_arena* arena, oc_str32 str, oc_str32_list separators);
ORCA_API void oc_str32_list_push(oc_arena* arena, oc_str32_list* list, oc_str32 str);
ORCA_API oc_str32 oc_str32_list_join(oc_arena* arena, oc_str32_list list);
ORCA_API oc_str32_list oc_str32_split(oc_arena* arena, oc_str32 str, oc_str32_list separators);
#ifdef __cplusplus
} // extern "C"

View File

@ -1,7 +1,7 @@
[
{
"name": "oc_runtime_log",
"cname": "oc_runtime_log",
"name": "oc_bridge_log",
"cname": "oc_bridge_log",
"ret": {"name": "void", "tag": "v"},
"args": [ {"name": "level",
"type": {"name": "oc_log_level", "tag": "i"}},
@ -29,7 +29,7 @@
"type": {"name": "u64", "tag": "I"}}]
},
{
"name": "oc_runtime_assert_fail",
"name": "oc_bridge_assert_fail",
"cname": "oc_assert_fail",
"ret": {"name": "void", "tag": "v"},
"args": [ {"name": "file",
@ -45,7 +45,7 @@
]
},
{
"name": "oc_runtime_abort_ext",
"name": "oc_bridge_abort_ext",
"cname": "oc_abort_ext",
"ret": {"name": "void", "tag": "v"},
"args": [ {"name": "file",
@ -71,17 +71,17 @@
"args": []
},
{
"name": "oc_runtime_window_set_title",
"cname": "oc_runtime_window_set_title",
"name": "oc_window_set_title",
"cname": "oc_bridge_window_set_title",
"ret": {"name": "void", "tag": "v"},
"args": [
{ "name": "title",
"type": {"name": "oc_str8", "tag": "S"}}
"type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}}
]
},
{
"name": "oc_runtime_window_set_size",
"cname": "oc_runtime_window_set_size",
"name": "oc_window_set_size",
"cname": "oc_bridge_window_set_size",
"ret": {"name": "void", "tag": "v"},
"args": [
{ "name": "size",

View File

@ -1,9 +1,37 @@
[
{
"name": "oc_io_wait_single_req",
"cname": "oc_runtime_io_wait_single_req",
"cname": "oc_bridge_io_single_rect",
"ret": {"name": "oc_io_cmp", "tag": "S"},
"args": [ {"name": "req",
"type": {"name": "oc_io_req*", "tag": "p"}}]
},
{
"name": "oc_file_open_with_request",
"cname": "oc_file_open_with_request_bridge",
"ret": {"name": "oc_file", "tag": "S"},
"args": [
{"name": "path",
"type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}},
{"name": "rights",
"type": {"name": "oc_file_access", "tag": "i"}},
{"name": "flags",
"type": {"name": "oc_file_open_flags", "tag": "i"}}
]
},
{
"name": "oc_file_open_with_dialog",
"cname": "oc_file_open_with_dialog_bridge",
"ret": {"name": "oc_file_open_with_dialog_result", "cname": "oc_wasm_file_open_with_dialog_result", "tag": "S"},
"args": [
{"name": "arena",
"type": {"name": "oc_arena*", "cname": "i32", "tag": "i"}},
{"name": "rights",
"type": {"name": "oc_file_access", "tag": "i"}},
{"name": "flags",
"type": {"name": "oc_file_open_flags", "tag": "i"}},
{"name": "desc",
"type": {"name": "oc_file_dialog_desc*", "cname": "oc_wasm_file_dialog_desc*", "tag": "p"}}
]
}
]

View File

@ -36,6 +36,14 @@
{"name": "pixels",
"type": {"name": "u8*", "tag": "p"}}]
},
{
"name": "oc_surface_get_size",
"cname": "oc_surface_get_size",
"ret": {"name": "oc_vec2", "tag": "S"},
"args": [
{"name": "surface",
"type": {"name": "oc_surface", "tag": "S"}}]
},
{
"name": "oc_surface_contents_scaling",
"cname": "oc_surface_contents_scaling",

1
tests/file_dialog/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bin

View File

@ -0,0 +1,7 @@
set INCLUDES=/I ..\..\src /I ..\..\ext
mkdir bin
cl /we4013 /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% main.c /link /LIBPATH:../../build/bin orca.dll.lib /out:bin/test_file_dialog.exe
copy ..\..\build\bin\orca.dll bin

18
tests/file_dialog/build.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
LIBDIR=../../build/bin
SRCDIR=../../src
INCLUDES="-I$SRCDIR"
LIBS="-L$LIBDIR -lorca"
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
if [ ! \( -e bin \) ] ; then
mkdir ./bin
fi
clang -g $FLAGS $LIBS $INCLUDES -o ./bin/test_file_dialog main.c
cp $LIBDIR/liborca.dylib ./bin/
install_name_tool -add_rpath "@executable_path" ./bin/test_file_dialog

45
tests/file_dialog/main.c Normal file
View File

@ -0,0 +1,45 @@
/************************************************************/ /**
*
* @file: main.c
* @author: Martin Fouilleul
* @date: 26/05/2023
*
*****************************************************************/
#include "orca.h"
int main(int argc, char** argv)
{
oc_init();
oc_str8 path = oc_path_executable_relative(oc_scratch(), OC_STR8("../"));
oc_file dir = oc_file_open(path, OC_FILE_ACCESS_READ, 0);
oc_file_dialog_desc desc = {
.kind = OC_FILE_DIALOG_OPEN,
.flags = OC_FILE_DIALOG_FILES | OC_FILE_DIALOG_MULTIPLE,
.title = OC_STR8("Select Files"),
.okLabel = OC_STR8("Select"),
.startAt = dir,
.startPath = OC_STR8(".."),
};
oc_str8_list_push(oc_scratch(), &desc.filters, OC_STR8("txt"));
oc_file_dialog_result res = oc_file_dialog(oc_scratch(), &desc);
if(res.button == OC_FILE_DIALOG_CANCEL)
{
oc_log_error("Cancel\n");
}
else
{
oc_log_info("Selected files:\n");
oc_list_for(&res.selection.list, elt, oc_str8_elt, listElt)
{
oc_log_info("\t%.*s\n", (int)elt->string.len, elt->string.ptr);
}
}
return (0);
}

View File

@ -0,0 +1 @@
The quick brown fox jumps over the lazy dog

View File

@ -0,0 +1 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit.

1
tests/file_open_dialog/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bin

View File

@ -0,0 +1,5 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/test_open_dialog.exe
copy ..\..\build\bin\orca.dll bin

18
tests/file_open_dialog/build.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
LIBDIR=../../build/bin
SRCDIR=../../src
INCLUDES="-I$SRCDIR"
LIBS="-L$LIBDIR -lorca"
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
if [ ! \( -e bin \) ] ; then
mkdir ./bin
fi
clang -g $FLAGS $LIBS $INCLUDES -o ./bin/test_open_dialog main.c
cp $LIBDIR/liborca.dylib ./bin/
install_name_tool -add_rpath "@executable_path" ./bin/test_open_dialog

View File

@ -0,0 +1,37 @@
/************************************************************/ /**
*
* @file: main.c
* @author: Martin Fouilleul
* @date: 26/05/2023
*
*****************************************************************/
#include "orca.h"
int main(int argc, char** argv)
{
oc_init();
oc_file_dialog_desc desc = {
.kind = OC_FILE_DIALOG_OPEN,
.flags = OC_FILE_DIALOG_FILES,
.title = OC_STR8("Select Files"),
.okLabel = OC_STR8("Select")
};
oc_str8_list_push(oc_scratch(), &desc.filters, OC_STR8("txt"));
oc_file file = oc_file_open_with_dialog(OC_FILE_ACCESS_READ, 0, &desc);
if(oc_file_is_nil(file))
{
oc_log_error("Couldn't open file\n");
}
else
{
char buffer[1024];
u64 len = oc_file_read(file, 1024, buffer);
oc_log_info("file contents: %.*s\n", (int)len, buffer);
}
return (0);
}

View File

@ -0,0 +1 @@
The quick brown fox jumps over the lazy dog

1
tests/file_open_request/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bin

View File

@ -0,0 +1,5 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/test_open_request.exe
copy ..\..\build\bin\orca.dll bin

View File

@ -0,0 +1,18 @@
#!/bin/bash
LIBDIR=../../build/bin
SRCDIR=../../src
INCLUDES="-I$SRCDIR"
LIBS="-L$LIBDIR -lorca"
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
if [ ! \( -e bin \) ] ; then
mkdir ./bin
fi
clang -g $FLAGS $LIBS $INCLUDES -o ./bin/test_open_request main.c
cp $LIBDIR/liborca.dylib ./bin/
install_name_tool -add_rpath "@executable_path" ./bin/test_open_request

View File

@ -0,0 +1,28 @@
/************************************************************/ /**
*
* @file: main.c
* @author: Martin Fouilleul
* @date: 26/05/2023
*
*****************************************************************/
#include "orca.h"
int main(int argc, char** argv)
{
oc_init();
oc_file file = oc_file_open_with_request(OC_STR8("./test.txt"), OC_FILE_ACCESS_READ, 0);
if(oc_file_is_nil(file))
{
oc_log_error("Couldn't open file\n");
}
else
{
char buffer[1024];
u64 len = oc_file_read(file, 1024, buffer);
oc_log_info("file contents: %.*s\n", (int)len, buffer);
}
return (0);
}

View File

@ -0,0 +1 @@
The quick brown fox jumps over the lazy dog