Big renaming and consistency pass, including:
- "Namespacing" the Orca APIs by adding the oc_ prefix everywhere - Naming consistency tweaks, eg create_from_memory vs. create_from_data - Adhering to a more consistent convention when pairing functions defining entities lifetime, eg. create/destroy, push/clear, alloc/recycle, init/cleanup - Preferring oc_str8 to const char*, except when we expect lots of C string literals (e.g. when tagging UI widgets) or when it would be annoying to systematically wrap data we want to read/write into a string - Reorganize macros for asserts/logging, and properly exposing them to the apps with non conflicting names - Generally rearrange some bits and pruning unused stuff to make things more navigable
This commit is contained in:
parent
9ae9562ca7
commit
75621d85a5
|
@ -162,23 +162,23 @@ GLuint compile_shader(const char* vs, const char* fs)
|
|||
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
||||
if(status != GL_TRUE)
|
||||
{
|
||||
log_error("program failed to link: ");
|
||||
oc_log_error("program failed to link: ");
|
||||
int logSize = 0;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logSize);
|
||||
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
char* log = mem_arena_alloc(scratch.arena, logSize);
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
char* log = oc_arena_push(scratch.arena, logSize);
|
||||
|
||||
glGetProgramInfoLog(prog, logSize, 0, log);
|
||||
log_error("%s\n", log);
|
||||
oc_log_error("%s\n", log);
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
}
|
||||
|
||||
int err = glGetError();
|
||||
if(err)
|
||||
{
|
||||
log_error("gl error %i\n", err);
|
||||
oc_log_error("gl error %i\n", err);
|
||||
}
|
||||
|
||||
return(prog);
|
||||
|
@ -186,7 +186,7 @@ GLuint compile_shader(const char* vs, const char* fs)
|
|||
|
||||
void init_advect(advect_program* program)
|
||||
{
|
||||
log_info("compiling advect...");
|
||||
oc_log_info("compiling advect...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_advect);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
|
@ -197,7 +197,7 @@ void init_advect(advect_program* program)
|
|||
|
||||
void init_div(div_program* program)
|
||||
{
|
||||
log_info("compiling div...");
|
||||
oc_log_info("compiling div...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_divergence);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
|
@ -205,7 +205,7 @@ void init_div(div_program* program)
|
|||
|
||||
void init_jacobi(jacobi_program* program)
|
||||
{
|
||||
log_info("compiling jacobi...");
|
||||
oc_log_info("compiling jacobi...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_jacobi_step);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->xTex = glGetUniformLocation(program->prog, "xTex");
|
||||
|
@ -214,7 +214,7 @@ void init_jacobi(jacobi_program* program)
|
|||
|
||||
void init_multigrid_restrict_residual(multigrid_restrict_residual_program* program)
|
||||
{
|
||||
log_info("compiling multigrid restrict residual...");
|
||||
oc_log_info("compiling multigrid restrict residual...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_multigrid_restrict_residual);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->xTex = glGetUniformLocation(program->prog, "xTex");
|
||||
|
@ -223,7 +223,7 @@ void init_multigrid_restrict_residual(multigrid_restrict_residual_program* progr
|
|||
|
||||
void init_multigrid_correct(multigrid_correct_program* program)
|
||||
{
|
||||
log_info("compiling multigrid correct...");
|
||||
oc_log_info("compiling multigrid correct...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_multigrid_correct);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
|
@ -233,7 +233,7 @@ void init_multigrid_correct(multigrid_correct_program* program)
|
|||
|
||||
void init_subtract(subtract_program* program)
|
||||
{
|
||||
log_info("compiling subtract...");
|
||||
oc_log_info("compiling subtract...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_subtract_pressure);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
|
@ -243,7 +243,7 @@ void init_subtract(subtract_program* program)
|
|||
|
||||
void init_splat(splat_program* program)
|
||||
{
|
||||
log_info("compiling splat...");
|
||||
oc_log_info("compiling splat...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_splat);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
|
@ -257,7 +257,7 @@ void init_splat(splat_program* program)
|
|||
|
||||
void init_blit(blit_program* program)
|
||||
{
|
||||
log_info("compiling blit...");
|
||||
oc_log_info("compiling blit...");
|
||||
program->prog = compile_shader(glsl_blit_vertex, glsl_blit_fragment);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||
|
@ -267,7 +267,7 @@ void init_blit(blit_program* program)
|
|||
|
||||
void init_blit_div(blit_program* program)
|
||||
{
|
||||
log_info("compiling blit div...");
|
||||
oc_log_info("compiling blit div...");
|
||||
program->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_div_fragment);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||
|
@ -276,7 +276,7 @@ void init_blit_div(blit_program* program)
|
|||
|
||||
void init_blit_residue(blit_residue_program* program)
|
||||
{
|
||||
log_info("compiling blit residue...");
|
||||
oc_log_info("compiling blit residue...");
|
||||
program->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_residue_fragment);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||
|
@ -325,7 +325,7 @@ void init_frame_buffer(frame_buffer* framebuffer,
|
|||
GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if(err != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
log_info("Frame buffer incomplete, %i", err);
|
||||
oc_log_info("Frame buffer incomplete, %i", err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,7 +372,7 @@ static bool resetCmd = false;
|
|||
void reset()
|
||||
{
|
||||
// resetCmd = true;
|
||||
log_info("reset");
|
||||
oc_log_info("reset");
|
||||
|
||||
reset_texture(colorBuffer.textures[0], texWidth, texHeight, (char*)colorInitData);
|
||||
reset_texture(colorBuffer.textures[1], texWidth, texHeight, (char*)colorInitData);
|
||||
|
@ -407,17 +407,17 @@ int frameWidth = 800;
|
|||
int frameHeight = 600;
|
||||
|
||||
|
||||
ORCA_EXPORT void OnMouseDown(int button)
|
||||
ORCA_EXPORT void oc_on_mouse_down(int button)
|
||||
{
|
||||
mouseInput.down = true;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnMouseUp(int button)
|
||||
ORCA_EXPORT void oc_on_mouse_up(int button)
|
||||
{
|
||||
mouseInput.down = false;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnMouseMove(float x, float y, float dx, float dy)
|
||||
ORCA_EXPORT void oc_on_mouse_move(float x, float y, float dx, float dy)
|
||||
{
|
||||
mouseInput.x = x * 2;
|
||||
mouseInput.y = y * 2;
|
||||
|
@ -611,14 +611,14 @@ void input_splat(float t)
|
|||
|
||||
float testDiv[texWidth/2][texWidth/2][4];
|
||||
|
||||
mg_surface surface;
|
||||
oc_surface surface;
|
||||
|
||||
ORCA_EXPORT void OnInit()
|
||||
ORCA_EXPORT void oc_on_init()
|
||||
{
|
||||
log_info("Hello, world (from C)");
|
||||
oc_log_info("Hello, world (from C)");
|
||||
|
||||
surface = mg_surface_gles();
|
||||
mg_surface_prepare(surface);
|
||||
surface = oc_surface_gles();
|
||||
oc_surface_select(surface);
|
||||
|
||||
// init_color_checker();
|
||||
// init_velocity_vortex();
|
||||
|
@ -637,17 +637,17 @@ ORCA_EXPORT void OnInit()
|
|||
init_blit_div(&blitDivProgram);
|
||||
|
||||
// init frame buffers
|
||||
log_info("create color buffer");
|
||||
oc_log_info("create color buffer");
|
||||
init_frame_buffer(&colorBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)colorInitData);
|
||||
log_info("create velocity buffer");
|
||||
oc_log_info("create velocity buffer");
|
||||
init_frame_buffer(&velocityBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)velocityInitData);
|
||||
|
||||
int gridFactor = 1;
|
||||
for(int i=0; i<MULTIGRID_COUNT; i++)
|
||||
{
|
||||
log_info("create div buffer %i", i);
|
||||
oc_log_info("create div buffer %i", i);
|
||||
init_frame_buffer(&divBuffer[i], texWidth/gridFactor, texHeight/gridFactor, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
|
||||
log_info("create pressure buffer %i", i);
|
||||
oc_log_info("create pressure buffer %i", i);
|
||||
init_frame_buffer(&pressureBuffer[i], texWidth/gridFactor, texHeight/gridFactor, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
|
||||
gridFactor *= 2;
|
||||
}
|
||||
|
@ -682,20 +682,20 @@ ORCA_EXPORT void OnInit()
|
|||
}
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
|
||||
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
|
||||
{
|
||||
frameWidth = width*2;
|
||||
frameHeight = height*2;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameRefresh()
|
||||
ORCA_EXPORT void oc_on_frame_refresh()
|
||||
{
|
||||
float aspectRatio = texWidth/texHeight; //TODO replace with actual aspect ratio?
|
||||
|
||||
static float t = 0;
|
||||
t += 1./60.;
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
oc_surface_select(surface);
|
||||
|
||||
glViewport(0, 0, texWidth, texHeight);
|
||||
|
||||
|
@ -925,5 +925,5 @@ ORCA_EXPORT void OnFrameRefresh()
|
|||
|
||||
//*/
|
||||
|
||||
mg_surface_present(surface);
|
||||
oc_surface_present(surface);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include <orca.h>
|
||||
|
||||
vec2 frameSize = {100, 100};
|
||||
oc_vec2 frameSize = {100, 100};
|
||||
|
||||
mg_surface surface;
|
||||
oc_surface surface;
|
||||
|
||||
unsigned int program;
|
||||
|
||||
|
@ -31,26 +31,24 @@ void compile_shader(GLuint shader, const char* source)
|
|||
int err = glGetError();
|
||||
if(err)
|
||||
{
|
||||
log_info("gl error");
|
||||
oc_log_info("gl error");
|
||||
}
|
||||
}
|
||||
|
||||
char* ORCA_IMPORT(orca_mem_grow)(u64 size);
|
||||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
ORCA_EXPORT void oc_on_init(void)
|
||||
{
|
||||
surface = mg_surface_gles();
|
||||
mg_surface_prepare(surface);
|
||||
surface = oc_surface_gles();
|
||||
oc_surface_select(surface);
|
||||
|
||||
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
|
||||
log_info("GLES extensions: %s\n", extensions);
|
||||
oc_log_info("GLES extensions: %s\n", extensions);
|
||||
|
||||
int extensionCount = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
|
||||
for(int i=0; i<extensionCount; i++)
|
||||
{
|
||||
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||
log_info("GLES extension %i: %s\n", i, extension);
|
||||
oc_log_info("GLES extension %i: %s\n", i, extension);
|
||||
}
|
||||
|
||||
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
|
||||
|
@ -78,18 +76,18 @@ ORCA_EXPORT void OnInit(void)
|
|||
glEnableVertexAttribArray(0);
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
|
||||
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
|
||||
{
|
||||
log_info("frame resize %u, %u", width, height);
|
||||
oc_log_info("frame resize %u, %u", width, height);
|
||||
frameSize.x = width;
|
||||
frameSize.y = height;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameRefresh(void)
|
||||
ORCA_EXPORT void oc_on_frame_refresh(void)
|
||||
{
|
||||
f32 aspect = frameSize.x/frameSize.y;
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
oc_surface_select(surface);
|
||||
|
||||
glClearColor(0, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
@ -108,5 +106,5 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
|||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
mg_surface_present(surface);
|
||||
oc_surface_present(surface);
|
||||
}
|
||||
|
|
|
@ -13,13 +13,13 @@ const f32 BLOCK_WIDTH = (BLOCKS_WIDTH - ((NUM_BLOCKS_PER_ROW + 1) * BLOCKS_PADDI
|
|||
|
||||
#define PADDLE_MAX_LAUNCH_ANGLE 0.7f
|
||||
|
||||
const mg_color paddleColor = {1, 0, 0, 1};
|
||||
mp_rect paddle = {300, 50, 200, 24};
|
||||
const oc_color paddleColor = {1, 0, 0, 1};
|
||||
oc_rect paddle = {300, 50, 200, 24};
|
||||
|
||||
const mg_color ballColor = {1, 1, 0, 1};
|
||||
mp_rect ball = {200, 200, 20, 20};
|
||||
const oc_color ballColor = {1, 1, 0, 1};
|
||||
oc_rect ball = {200, 200, 20, 20};
|
||||
|
||||
vec2 velocity = {5, 5};
|
||||
oc_vec2 velocity = {5, 5};
|
||||
|
||||
// This is upside down from how it will actually be drawn.
|
||||
int blockHealth[NUM_BLOCKS] = {
|
||||
|
@ -31,127 +31,127 @@ int blockHealth[NUM_BLOCKS] = {
|
|||
3, 3, 3, 3, 3, 3, 3,
|
||||
};
|
||||
|
||||
vec2 frameSize = {100, 100};
|
||||
oc_vec2 frameSize = {100, 100};
|
||||
|
||||
bool leftDown = false;
|
||||
bool rightDown = false;
|
||||
|
||||
mg_surface surface;
|
||||
mg_canvas canvas;
|
||||
mg_image waterImage;
|
||||
mg_image ballImage;
|
||||
mg_image paddleImage;
|
||||
mg_font pongFont;
|
||||
oc_surface surface;
|
||||
oc_canvas canvas;
|
||||
oc_image waterImage;
|
||||
oc_image ballImage;
|
||||
oc_image paddleImage;
|
||||
oc_font pongFont;
|
||||
|
||||
f32 lerp(f32 a, f32 b, f32 t);
|
||||
mp_rect blockRect(int i);
|
||||
int checkCollision(mp_rect block);
|
||||
mg_mat2x3 flipY(mp_rect r);
|
||||
mg_mat2x3 flipYAt(vec2 pos);
|
||||
oc_rect blockRect(int i);
|
||||
int checkCollision(oc_rect block);
|
||||
oc_mat2x3 flipY(oc_rect r);
|
||||
oc_mat2x3 flipYAt(oc_vec2 pos);
|
||||
|
||||
str8 loadFile(mem_arena* arena, str8 filename) {
|
||||
file_handle file = file_open(filename, FILE_ACCESS_READ, 0);
|
||||
if(file_last_error(file) != IO_OK)
|
||||
oc_str8 loadFile(oc_arena* arena, oc_str8 filename) {
|
||||
oc_file file = oc_file_open(filename, OC_FILE_ACCESS_READ, 0);
|
||||
if(oc_file_last_error(file) != OC_IO_OK)
|
||||
{
|
||||
log_error("Couldn't open file %s\n", str8_to_cstring(mem_scratch(), filename));
|
||||
oc_log_error("Couldn't open file %s\n", oc_str8_to_cstring(oc_scratch(), filename));
|
||||
}
|
||||
u64 size = file_size(file);
|
||||
char* buffer = mem_arena_alloc(arena, size);
|
||||
file_read(file, size, buffer);
|
||||
file_close(file);
|
||||
return str8_from_buffer(size, buffer);
|
||||
u64 size = oc_file_size(file);
|
||||
char* buffer = oc_arena_push(arena, size);
|
||||
oc_file_read(file, size, buffer);
|
||||
oc_file_close(file);
|
||||
return oc_str8_from_buffer(size, buffer);
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
ORCA_EXPORT void oc_on_init(void)
|
||||
{
|
||||
surface = mg_surface_canvas();
|
||||
canvas = mg_canvas_create();
|
||||
surface = oc_surface_canvas();
|
||||
canvas = oc_canvas_create();
|
||||
|
||||
waterImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/underwater.jpg")), false);
|
||||
ballImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/ball.png")), false);
|
||||
paddleImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/wall.png")), false);
|
||||
waterImage = oc_image_create_from_memory(surface, loadFile(oc_scratch(), OC_STR8("/underwater.jpg")), false);
|
||||
ballImage = oc_image_create_from_memory(surface, loadFile(oc_scratch(), OC_STR8("/ball.png")), false);
|
||||
paddleImage = oc_image_create_from_memory(surface, loadFile(oc_scratch(), OC_STR8("/wall.png")), false);
|
||||
|
||||
if(mg_image_is_nil(waterImage))
|
||||
if(oc_image_is_nil(waterImage))
|
||||
{
|
||||
log_error("couldn't load water image\n");
|
||||
oc_log_error("couldn't load water image\n");
|
||||
}
|
||||
if(mg_image_is_nil(ballImage))
|
||||
if(oc_image_is_nil(ballImage))
|
||||
{
|
||||
log_error("couldn't load ball image\n");
|
||||
oc_log_error("couldn't load ball image\n");
|
||||
}
|
||||
if(mg_image_is_nil(paddleImage))
|
||||
if(oc_image_is_nil(paddleImage))
|
||||
{
|
||||
log_error("couldn't load paddle image\n");
|
||||
oc_log_error("couldn't load paddle image\n");
|
||||
}
|
||||
|
||||
str8 fontStr = loadFile(mem_scratch(), STR8("/Literata-SemiBoldItalic.ttf"));
|
||||
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
|
||||
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||
UNICODE_RANGE_LATIN_EXTENDED_A,
|
||||
UNICODE_RANGE_LATIN_EXTENDED_B,
|
||||
UNICODE_RANGE_SPECIALS};
|
||||
oc_str8 fontStr = loadFile(oc_scratch(), OC_STR8("/Literata-SemiBoldItalic.ttf"));
|
||||
oc_unicode_range ranges[5] = {OC_UNICODE_BASIC_LATIN,
|
||||
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||
OC_UNICODE_LATIN_EXTENDED_A,
|
||||
OC_UNICODE_LATIN_EXTENDED_B,
|
||||
OC_UNICODE_SPECIALS};
|
||||
// NOTE(ben): Weird that images are "create from data" but fonts are "create from memory"
|
||||
// TODO: Decide whether we're using strings or explicit pointer + length
|
||||
pongFont = mg_font_create_from_memory(fontStr.len, (byte*)fontStr.ptr, 5, ranges);
|
||||
pongFont = oc_font_create_from_memory(fontStr, 5, ranges);
|
||||
|
||||
mem_arena_clear(mem_scratch());
|
||||
oc_arena_clear(oc_scratch());
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
|
||||
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
|
||||
{
|
||||
log_info("frame resize %u, %u", width, height);
|
||||
oc_log_info("frame resize %u, %u", width, height);
|
||||
frameSize.x = width;
|
||||
frameSize.y = height;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnMouseDown(int button)
|
||||
ORCA_EXPORT void oc_on_mouse_down(int button)
|
||||
{
|
||||
log_info("mouse down!");
|
||||
oc_log_info("mouse down!");
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnKeyDown(int key)
|
||||
ORCA_EXPORT void oc_on_key_down(int key)
|
||||
{
|
||||
if(key == MP_KEY_SPACE)
|
||||
if(key == OC_KEY_SPACE)
|
||||
{
|
||||
log_error("(this is just for testing errors)");
|
||||
oc_log_error("(this is just for testing errors)");
|
||||
return;
|
||||
}
|
||||
if(key == MP_KEY_ENTER)
|
||||
if(key == OC_KEY_ENTER)
|
||||
{
|
||||
log_warning("(this is just for testing warning)");
|
||||
oc_log_warning("(this is just for testing warning)");
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("key down: %i", key);
|
||||
if(key == MP_KEY_LEFT)
|
||||
oc_log_info("key down: %i", key);
|
||||
if(key == OC_KEY_LEFT)
|
||||
{
|
||||
leftDown = true;
|
||||
}
|
||||
if(key == MP_KEY_RIGHT)
|
||||
if(key == OC_KEY_RIGHT)
|
||||
{
|
||||
rightDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnKeyUp(int key)
|
||||
ORCA_EXPORT void oc_on_key_up(int key)
|
||||
{
|
||||
if(key == MP_KEY_ENTER || key == MP_KEY_SPACE)
|
||||
if(key == OC_KEY_ENTER || key == OC_KEY_SPACE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("key up: %i", key);
|
||||
if(key == MP_KEY_LEFT)
|
||||
oc_log_info("key up: %i", key);
|
||||
if(key == OC_KEY_LEFT)
|
||||
{
|
||||
leftDown = false;
|
||||
}
|
||||
if(key == MP_KEY_RIGHT)
|
||||
if(key == OC_KEY_RIGHT)
|
||||
{
|
||||
rightDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameRefresh(void)
|
||||
ORCA_EXPORT void oc_on_frame_refresh(void)
|
||||
{
|
||||
f32 aspect = frameSize.x/frameSize.y;
|
||||
|
||||
|
@ -163,12 +163,12 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
|||
{
|
||||
paddle.x += 10;
|
||||
}
|
||||
paddle.x = Clamp(paddle.x, 0, frameSize.x - paddle.w);
|
||||
paddle.x = oc_clamp(paddle.x, 0, frameSize.x - paddle.w);
|
||||
|
||||
ball.x += velocity.x;
|
||||
ball.y += velocity.y;
|
||||
ball.x = Clamp(ball.x, 0, frameSize.x - ball.w);
|
||||
ball.y = Clamp(ball.y, 0, frameSize.y - ball.h);
|
||||
ball.x = oc_clamp(ball.x, 0, frameSize.x - ball.w);
|
||||
ball.y = oc_clamp(ball.y, 0, frameSize.y - ball.h);
|
||||
|
||||
if (ball.x + ball.w >= frameSize.x) {
|
||||
velocity.x = -velocity.x;
|
||||
|
@ -189,13 +189,13 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
|||
f32 t = ((ball.x + ball.w/2) - paddle.x) / paddle.w;
|
||||
f32 launchAngle = lerp(-PADDLE_MAX_LAUNCH_ANGLE, PADDLE_MAX_LAUNCH_ANGLE, t);
|
||||
f32 speed = sqrtf(velocity.x*velocity.x + velocity.y*velocity.y);
|
||||
velocity = (vec2){
|
||||
velocity = (oc_vec2){
|
||||
sinf(launchAngle) * speed,
|
||||
cosf(launchAngle) * speed,
|
||||
};
|
||||
ball.y = paddle.y + paddle.h;
|
||||
|
||||
log_info("PONG!");
|
||||
oc_log_info("PONG!");
|
||||
}
|
||||
|
||||
if (ball.y <= 0) {
|
||||
|
@ -208,10 +208,10 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
mp_rect r = blockRect(i);
|
||||
oc_rect r = blockRect(i);
|
||||
int result = checkCollision(r);
|
||||
if (result) {
|
||||
log_info("Collision! direction=%d", result);
|
||||
oc_log_info("Collision! direction=%d", result);
|
||||
blockHealth[i] -= 1;
|
||||
|
||||
f32 vx = velocity.x;
|
||||
|
@ -241,74 +241,74 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
|||
|
||||
}
|
||||
|
||||
mg_canvas_set_current(canvas);
|
||||
oc_canvas_set_current(canvas);
|
||||
|
||||
mg_set_color_rgba(10.0f/255.0f, 31.0f/255.0f, 72.0f/255.0f, 1);
|
||||
mg_clear();
|
||||
oc_set_color_rgba(10.0f/255.0f, 31.0f/255.0f, 72.0f/255.0f, 1);
|
||||
oc_clear();
|
||||
|
||||
mg_image_draw(waterImage, (mp_rect){0, 0, frameSize.x, frameSize.y});
|
||||
oc_image_draw(waterImage, (oc_rect){0, 0, frameSize.x, frameSize.y});
|
||||
|
||||
mg_mat2x3 yUp = {
|
||||
oc_mat2x3 yUp = {
|
||||
1, 0, 0,
|
||||
0, -1, frameSize.y,
|
||||
};
|
||||
|
||||
mg_matrix_push(yUp);
|
||||
oc_matrix_push(yUp);
|
||||
{
|
||||
for (int i = 0; i < NUM_BLOCKS; i++) {
|
||||
if (blockHealth[i] <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mp_rect r = blockRect(i);
|
||||
mg_set_color_rgba(0, 0, 0, 0.2);
|
||||
mg_rounded_rectangle_fill(r.x, r.y-2, r.w, r.h, 4);
|
||||
mg_set_color_rgba(0.9, 0.9, 0.9, 1);
|
||||
mg_rounded_rectangle_fill(r.x, r.y, r.w, r.h, 4);
|
||||
oc_rect r = blockRect(i);
|
||||
oc_set_color_rgba(0, 0, 0, 0.2);
|
||||
oc_rounded_rectangle_fill(r.x, r.y-2, r.w, r.h, 4);
|
||||
oc_set_color_rgba(0.9, 0.9, 0.9, 1);
|
||||
oc_rounded_rectangle_fill(r.x, r.y, r.w, r.h, 4);
|
||||
|
||||
int fontSize = 18;
|
||||
str8 text = str8_pushf(mem_scratch(),
|
||||
oc_str8 text = oc_str8_pushf(oc_scratch(),
|
||||
"%d", blockHealth[i]
|
||||
);
|
||||
mp_rect textRect = mg_text_bounding_box(pongFont, fontSize, text);
|
||||
oc_rect textRect = oc_text_bounding_box(pongFont, fontSize, text);
|
||||
|
||||
vec2 textPos = {
|
||||
oc_vec2 textPos = {
|
||||
r.x + r.w/2 - textRect.w/2,
|
||||
r.y + 9, // TODO: mg_text_bounding_box is returning extremely wack results for height.
|
||||
r.y + 9, // TODO: oc_text_bounding_box is returning extremely wack results for height.
|
||||
};
|
||||
|
||||
mg_set_color_rgba(0, 0, 0, 1);
|
||||
mg_set_font(pongFont);
|
||||
mg_set_font_size(18);
|
||||
mg_move_to(textPos.x, textPos.y);
|
||||
mg_matrix_push(flipYAt(textPos));
|
||||
oc_set_color_rgba(0, 0, 0, 1);
|
||||
oc_set_font(pongFont);
|
||||
oc_set_font_size(18);
|
||||
oc_move_to(textPos.x, textPos.y);
|
||||
oc_matrix_push(flipYAt(textPos));
|
||||
{
|
||||
mg_text_outlines(text);
|
||||
mg_fill();
|
||||
oc_text_outlines(text);
|
||||
oc_fill();
|
||||
}
|
||||
mg_matrix_pop();
|
||||
oc_matrix_pop();
|
||||
}
|
||||
|
||||
mg_set_color_rgba(0.9, 0.9, 0.9, 1);
|
||||
mg_rounded_rectangle_fill(paddle.x, paddle.y, paddle.w, paddle.h, 4);
|
||||
oc_set_color_rgba(0.9, 0.9, 0.9, 1);
|
||||
oc_rounded_rectangle_fill(paddle.x, paddle.y, paddle.w, paddle.h, 4);
|
||||
|
||||
mg_matrix_push(flipY(ball));
|
||||
oc_matrix_push(flipY(ball));
|
||||
{
|
||||
mg_image_draw(ballImage, ball);
|
||||
oc_image_draw(ballImage, ball);
|
||||
}
|
||||
mg_matrix_pop();
|
||||
oc_matrix_pop();
|
||||
}
|
||||
mg_matrix_pop();
|
||||
oc_matrix_pop();
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
mg_render(surface, canvas);
|
||||
mg_surface_present(surface);
|
||||
oc_surface_select(surface);
|
||||
oc_render(surface, canvas);
|
||||
oc_surface_present(surface);
|
||||
}
|
||||
|
||||
mp_rect blockRect(int i) {
|
||||
oc_rect blockRect(int i) {
|
||||
int row = i / NUM_BLOCKS_PER_ROW;
|
||||
int col = i % NUM_BLOCKS_PER_ROW;
|
||||
return (mp_rect){
|
||||
return (oc_rect){
|
||||
BLOCKS_PADDING + (BLOCKS_PADDING + BLOCK_WIDTH) * col,
|
||||
BLOCKS_BOTTOM + (BLOCKS_PADDING + BLOCK_HEIGHT) * row,
|
||||
BLOCK_WIDTH,
|
||||
|
@ -318,7 +318,7 @@ mp_rect blockRect(int i) {
|
|||
|
||||
// Returns a cardinal direction 1-8 for the collision with the block, or zero
|
||||
// if no collision. 1 is straight up and directions proceed clockwise.
|
||||
int checkCollision(mp_rect block) {
|
||||
int checkCollision(oc_rect block) {
|
||||
// Note that all the logic for this game has the origin in the bottom left.
|
||||
|
||||
f32 ballx2 = ball.x + ball.w;
|
||||
|
@ -355,8 +355,8 @@ int checkCollision(mp_rect block) {
|
|||
//
|
||||
// We assume significant tunneling can't happen.
|
||||
|
||||
vec2 ballCenter = (vec2){ball.x + ball.w/2, ball.y + ball.h/2};
|
||||
vec2 blockCenter = (vec2){block.x + block.w/2, block.y + block.h/2};
|
||||
oc_vec2 ballCenter = (oc_vec2){ball.x + ball.w/2, ball.y + ball.h/2};
|
||||
oc_vec2 blockCenter = (oc_vec2){block.x + block.w/2, block.y + block.h/2};
|
||||
|
||||
// Moving right
|
||||
if (velocity.x > 0) {
|
||||
|
@ -445,15 +445,15 @@ f32 lerp(f32 a, f32 b, f32 t) {
|
|||
return (1 - t) * a + t * b;
|
||||
}
|
||||
|
||||
mg_mat2x3 flipY(mp_rect r) {
|
||||
return (mg_mat2x3){
|
||||
oc_mat2x3 flipY(oc_rect r) {
|
||||
return (oc_mat2x3){
|
||||
1, 0, 0,
|
||||
0, -1, 2 * r.y + r.h,
|
||||
};
|
||||
}
|
||||
|
||||
mg_mat2x3 flipYAt(vec2 pos) {
|
||||
return (mg_mat2x3){
|
||||
oc_mat2x3 flipYAt(oc_vec2 pos) {
|
||||
return (oc_mat2x3){
|
||||
1, 0, 0,
|
||||
0, -1, 2 * pos.y,
|
||||
};
|
||||
|
|
|
@ -1,230 +1,229 @@
|
|||
#include"orca.h"
|
||||
|
||||
vec2 frameSize = {100, 100};
|
||||
oc_vec2 frameSize = {100, 100};
|
||||
|
||||
mg_surface surface;
|
||||
mg_canvas canvas;
|
||||
mg_font font;
|
||||
ui_context ui;
|
||||
mem_arena textArena = {0};
|
||||
oc_surface surface;
|
||||
oc_canvas canvas;
|
||||
oc_font font;
|
||||
oc_ui_context ui;
|
||||
oc_arena textArena = {0};
|
||||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
ORCA_EXPORT void oc_on_init(void)
|
||||
{
|
||||
//TODO create surface for main window
|
||||
surface = mg_surface_canvas();
|
||||
canvas = mg_canvas_create();
|
||||
ui_init(&ui);
|
||||
surface = oc_surface_canvas();
|
||||
canvas = oc_canvas_create();
|
||||
oc_ui_init(&ui);
|
||||
|
||||
//NOTE: load font
|
||||
{
|
||||
file_handle file = file_open(STR8("/OpenSansLatinSubset.ttf"), FILE_ACCESS_READ, 0);
|
||||
if(file_last_error(file) != IO_OK)
|
||||
oc_file file = oc_file_open(OC_STR8("/OpenSansLatinSubset.ttf"), OC_FILE_ACCESS_READ, 0);
|
||||
if(oc_file_last_error(file) != OC_IO_OK)
|
||||
{
|
||||
log_error("Couldn't open file OpenSansLatinSubset.ttf\n");
|
||||
oc_log_error("Couldn't open file OpenSansLatinSubset.ttf\n");
|
||||
}
|
||||
u64 size = file_size(file);
|
||||
char* buffer = mem_arena_alloc(mem_scratch(), size);
|
||||
file_read(file, size, buffer);
|
||||
file_close(file);
|
||||
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
|
||||
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||
UNICODE_RANGE_LATIN_EXTENDED_A,
|
||||
UNICODE_RANGE_LATIN_EXTENDED_B,
|
||||
UNICODE_RANGE_SPECIALS};
|
||||
u64 size = oc_file_size(file);
|
||||
char* buffer = oc_arena_push(oc_scratch(), size);
|
||||
oc_file_read(file, size, buffer);
|
||||
oc_file_close(file);
|
||||
oc_unicode_range ranges[5] = {OC_UNICODE_BASIC_LATIN,
|
||||
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||
OC_UNICODE_LATIN_EXTENDED_A,
|
||||
OC_UNICODE_LATIN_EXTENDED_B,
|
||||
OC_UNICODE_SPECIALS};
|
||||
// TODO: Decide whether we're using strings or explicit pointer + length
|
||||
font = mg_font_create_from_memory(size, (byte*)buffer, 5, ranges);
|
||||
font = oc_font_create_from_memory(oc_str8_from_buffer(size, buffer), 5, ranges);
|
||||
}
|
||||
|
||||
mem_arena_clear(mem_scratch());
|
||||
mem_arena_init(&textArena);
|
||||
oc_arena_clear(oc_scratch());
|
||||
oc_arena_init(&textArena);
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
|
||||
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
|
||||
{
|
||||
log_info("frame resize %u, %u", width, height);
|
||||
oc_log_info("frame resize %u, %u", width, height);
|
||||
frameSize.x = width;
|
||||
frameSize.y = height;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnRawEvent(mp_event *event)
|
||||
ORCA_EXPORT void oc_on_raw_event(oc_event *event)
|
||||
{
|
||||
ui_process_event(event);
|
||||
oc_ui_process_event(event);
|
||||
}
|
||||
|
||||
void widget_begin_view(char* str)
|
||||
{
|
||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_Y,
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_Y,
|
||||
.layout.spacing = 10,
|
||||
.layout.margin.x = 10,
|
||||
.layout.margin.y = 10,
|
||||
.layout.align.x = UI_ALIGN_CENTER,
|
||||
.layout.align.y = UI_ALIGN_START},
|
||||
UI_STYLE_LAYOUT);
|
||||
.layout.align.x = OC_UI_ALIGN_CENTER,
|
||||
.layout.align.y = OC_UI_ALIGN_START},
|
||||
OC_UI_STYLE_LAYOUT);
|
||||
|
||||
ui_box_begin(str, UI_FLAG_DRAW_BORDER);
|
||||
ui_label(str);
|
||||
oc_ui_box_begin(str, OC_UI_FLAG_DRAW_BORDER);
|
||||
oc_ui_label(str);
|
||||
|
||||
}
|
||||
|
||||
void widget_end_view(void)
|
||||
{
|
||||
ui_box_end();
|
||||
oc_ui_box_end();
|
||||
}
|
||||
|
||||
#define widget_view(s) defer_loop(widget_begin_view(s), widget_end_view())
|
||||
#define widget_view(s) oc_defer_loop(widget_begin_view(s), widget_end_view())
|
||||
|
||||
ORCA_EXPORT void OnFrameRefresh(void)
|
||||
ORCA_EXPORT void oc_on_frame_refresh(void)
|
||||
{
|
||||
ui_style defaultStyle = {.bgColor = {0},
|
||||
oc_ui_style defaultStyle = {.bgColor = {0},
|
||||
.color = {1, 1, 1, 1},
|
||||
.font = font,
|
||||
.fontSize = 16,
|
||||
.borderColor = {0.278, 0.333, 0.412, 1},
|
||||
.borderSize = 2};
|
||||
|
||||
ui_style_mask defaultMask = UI_STYLE_BG_COLOR
|
||||
| UI_STYLE_COLOR
|
||||
| UI_STYLE_BORDER_COLOR
|
||||
| UI_STYLE_BORDER_SIZE
|
||||
| UI_STYLE_FONT
|
||||
| UI_STYLE_FONT_SIZE;
|
||||
oc_ui_style_mask defaultMask = OC_UI_STYLE_BG_COLOR
|
||||
| OC_UI_STYLE_COLOR
|
||||
| OC_UI_STYLE_BORDER_COLOR
|
||||
| OC_UI_STYLE_BORDER_SIZE
|
||||
| OC_UI_STYLE_FONT
|
||||
| OC_UI_STYLE_FONT_SIZE;
|
||||
|
||||
ui_frame(frameSize, &defaultStyle, defaultMask)
|
||||
oc_ui_frame(frameSize, &defaultStyle, defaultMask)
|
||||
{
|
||||
ui_style_match_before(ui_pattern_all(), &defaultStyle, defaultMask);
|
||||
oc_ui_style_match_before(oc_ui_pattern_all(), &defaultStyle, defaultMask);
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 1},
|
||||
.layout.axis = UI_AXIS_Y,
|
||||
.layout.align.x = UI_ALIGN_CENTER,
|
||||
.layout.align.y = UI_ALIGN_START,
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1},
|
||||
.layout.axis = OC_UI_AXIS_Y,
|
||||
.layout.align.x = OC_UI_ALIGN_CENTER,
|
||||
.layout.align.y = OC_UI_ALIGN_START,
|
||||
.layout.spacing = 10,
|
||||
.layout.margin.x = 10,
|
||||
.layout.margin.y = 10,
|
||||
.bgColor = {0.11, 0.11, 0.11, 1}},
|
||||
UI_STYLE_SIZE
|
||||
| UI_STYLE_LAYOUT
|
||||
| UI_STYLE_BG_COLOR);
|
||||
OC_UI_STYLE_SIZE
|
||||
| OC_UI_STYLE_LAYOUT
|
||||
| OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
ui_container("background", UI_FLAG_DRAW_BACKGROUND)
|
||||
oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND)
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_CHILDREN},
|
||||
.layout.align.x = UI_ALIGN_CENTER},
|
||||
UI_STYLE_SIZE
|
||||
|UI_STYLE_LAYOUT_ALIGN_X);
|
||||
ui_container("title", 0)
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_CHILDREN},
|
||||
.layout.align.x = OC_UI_ALIGN_CENTER},
|
||||
OC_UI_STYLE_SIZE
|
||||
|OC_UI_STYLE_LAYOUT_ALIGN_X);
|
||||
oc_ui_container("title", 0)
|
||||
{
|
||||
ui_style_next(&(ui_style){.fontSize = 26}, UI_STYLE_FONT_SIZE);
|
||||
ui_label("Orca UI Demo");
|
||||
oc_ui_style_next(&(oc_ui_style){.fontSize = 26}, OC_UI_STYLE_FONT_SIZE);
|
||||
oc_ui_label("Orca UI Demo");
|
||||
|
||||
if(ui_box_sig(ui_box_top()).hovering)
|
||||
if(oc_ui_box_sig(oc_ui_box_top()).hovering)
|
||||
{
|
||||
ui_tooltip("tooltip")
|
||||
oc_ui_tooltip("tooltip")
|
||||
{
|
||||
ui_style_next(&(ui_style){.bgColor = {1, 0.99, 0.82, 1}},
|
||||
UI_STYLE_BG_COLOR);
|
||||
oc_ui_style_next(&(oc_ui_style){.bgColor = {1, 0.99, 0.82, 1}},
|
||||
OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
ui_container("background", UI_FLAG_DRAW_BACKGROUND)
|
||||
oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND)
|
||||
{
|
||||
ui_style_next(&(ui_style){.color = {0, 0, 0, 1}},
|
||||
UI_STYLE_COLOR);
|
||||
oc_ui_style_next(&(oc_ui_style){.color = {0, 0, 0, 1}},
|
||||
OC_UI_STYLE_COLOR);
|
||||
|
||||
ui_label("That is a tooltip!");
|
||||
oc_ui_label("That is a tooltip!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui_menu_bar("Menu bar")
|
||||
oc_ui_menu_bar("Menu bar")
|
||||
{
|
||||
ui_menu("Menu 1")
|
||||
oc_ui_menu("Menu 1")
|
||||
{
|
||||
if(ui_menu_button("Option 1.1").pressed)
|
||||
if(oc_ui_menu_button("Option 1.1").pressed)
|
||||
{
|
||||
log_info("Pressed option 1.1\n");
|
||||
oc_log_info("Pressed option 1.1\n");
|
||||
}
|
||||
ui_menu_button("Option 1.2");
|
||||
ui_menu_button("Option 1.3");
|
||||
ui_menu_button("Option 1.4");
|
||||
oc_ui_menu_button("Option 1.2");
|
||||
oc_ui_menu_button("Option 1.3");
|
||||
oc_ui_menu_button("Option 1.4");
|
||||
}
|
||||
|
||||
ui_menu("Menu 2")
|
||||
oc_ui_menu("Menu 2")
|
||||
{
|
||||
ui_menu_button("Option 2.1");
|
||||
ui_menu_button("Option 2.2");
|
||||
ui_menu_button("Option 2.3");
|
||||
ui_menu_button("Option 2.4");
|
||||
oc_ui_menu_button("Option 2.1");
|
||||
oc_ui_menu_button("Option 2.2");
|
||||
oc_ui_menu_button("Option 2.3");
|
||||
oc_ui_menu_button("Option 2.4");
|
||||
}
|
||||
|
||||
ui_menu("Menu 3")
|
||||
oc_ui_menu("Menu 3")
|
||||
{
|
||||
ui_menu_button("Option 3.1");
|
||||
ui_menu_button("Option 3.2");
|
||||
ui_menu_button("Option 3.3");
|
||||
ui_menu_button("Option 3.4");
|
||||
oc_ui_menu_button("Option 3.1");
|
||||
oc_ui_menu_button("Option 3.2");
|
||||
oc_ui_menu_button("Option 3.3");
|
||||
oc_ui_menu_button("Option 3.4");
|
||||
}
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 1, 1}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1, 1}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X}, UI_STYLE_LAYOUT_AXIS);
|
||||
ui_container("contents", 0)
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X}, OC_UI_STYLE_LAYOUT_AXIS);
|
||||
oc_ui_container("contents", 0)
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {UI_SIZE_PARENT, 1}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
ui_container("left", 0)
|
||||
oc_ui_container("left", 0)
|
||||
{
|
||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X,
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X,
|
||||
.layout.spacing = 10,
|
||||
.layout.margin.x = 10,
|
||||
.layout.margin.y = 10,
|
||||
.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 0.5}},
|
||||
UI_STYLE_LAYOUT_AXIS
|
||||
|UI_STYLE_LAYOUT_SPACING
|
||||
|UI_STYLE_LAYOUT_MARGIN_X
|
||||
|UI_STYLE_LAYOUT_MARGIN_Y
|
||||
|UI_STYLE_SIZE);
|
||||
.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 0.5}},
|
||||
OC_UI_STYLE_LAYOUT_AXIS
|
||||
|OC_UI_STYLE_LAYOUT_SPACING
|
||||
|OC_UI_STYLE_LAYOUT_MARGIN_X
|
||||
|OC_UI_STYLE_LAYOUT_MARGIN_Y
|
||||
|OC_UI_STYLE_SIZE);
|
||||
|
||||
ui_container("up", 0)
|
||||
oc_ui_container("up", 0)
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {UI_SIZE_PARENT, 1}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
widget_view("Buttons")
|
||||
{
|
||||
if(ui_button("Button A").clicked)
|
||||
if(oc_ui_button("Button A").clicked)
|
||||
{
|
||||
log_info("A clicked");
|
||||
oc_log_info("A clicked");
|
||||
}
|
||||
|
||||
if(ui_button("Button B").clicked)
|
||||
if(oc_ui_button("Button B").clicked)
|
||||
{
|
||||
log_info("B clicked");
|
||||
oc_log_info("B clicked");
|
||||
}
|
||||
|
||||
if(ui_button("Button C").clicked)
|
||||
if(oc_ui_button("Button C").clicked)
|
||||
{
|
||||
log_info("C clicked");
|
||||
oc_log_info("C clicked");
|
||||
}
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {UI_SIZE_PARENT, 1}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
|
||||
ui_pattern pattern = {0};
|
||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("checkbox")});
|
||||
ui_style_match_after(pattern,
|
||||
&(ui_style){.bgColor = {0, 1, 0, 1},
|
||||
oc_ui_pattern pattern = {0};
|
||||
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_TAG, .tag = oc_ui_tag_make("checkbox")});
|
||||
oc_ui_style_match_after(pattern,
|
||||
&(oc_ui_style){.bgColor = {0, 1, 0, 1},
|
||||
.color = {1, 1, 1, 1}},
|
||||
UI_STYLE_COLOR | UI_STYLE_BG_COLOR);
|
||||
OC_UI_STYLE_COLOR | OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
widget_view("checkboxes")
|
||||
{
|
||||
|
@ -232,156 +231,156 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
|||
static bool check2 = false;
|
||||
static bool check3 = false;
|
||||
|
||||
ui_checkbox("check1", &check1);
|
||||
ui_checkbox("check2", &check2);
|
||||
ui_checkbox("check3", &check3);
|
||||
oc_ui_checkbox("check1", &check1);
|
||||
oc_ui_checkbox("check2", &check2);
|
||||
oc_ui_checkbox("check3", &check3);
|
||||
}
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X,
|
||||
.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 0.5}},
|
||||
UI_STYLE_LAYOUT_AXIS
|
||||
|UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X,
|
||||
.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 0.5}},
|
||||
OC_UI_STYLE_LAYOUT_AXIS
|
||||
|OC_UI_STYLE_SIZE);
|
||||
|
||||
ui_container("down", 0)
|
||||
oc_ui_container("down", 0)
|
||||
{
|
||||
widget_view("Vertical Sliders")
|
||||
{
|
||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X,
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X,
|
||||
.layout.spacing = 10},
|
||||
UI_STYLE_LAYOUT_AXIS
|
||||
|UI_STYLE_LAYOUT_SPACING);
|
||||
ui_container("contents", 0)
|
||||
OC_UI_STYLE_LAYOUT_AXIS
|
||||
|OC_UI_STYLE_LAYOUT_SPACING);
|
||||
oc_ui_container("contents", 0)
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20},
|
||||
.size.height = {UI_SIZE_PIXELS, 200}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20},
|
||||
.size.height = {OC_UI_SIZE_PIXELS, 200}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
static f32 slider1 = 0;
|
||||
ui_slider("slider1", 0.2, &slider1);
|
||||
oc_ui_slider("slider1", 0.2, &slider1);
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20},
|
||||
.size.height = {UI_SIZE_PIXELS, 200}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20},
|
||||
.size.height = {OC_UI_SIZE_PIXELS, 200}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
static f32 slider2 = 0;
|
||||
ui_slider("slider2", 0.2, &slider2);
|
||||
oc_ui_slider("slider2", 0.2, &slider2);
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20},
|
||||
.size.height = {UI_SIZE_PIXELS, 200}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20},
|
||||
.size.height = {OC_UI_SIZE_PIXELS, 200}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
static f32 slider3 = 0;
|
||||
ui_slider("slider3", 0.2, &slider3);
|
||||
oc_ui_slider("slider3", 0.2, &slider3);
|
||||
}
|
||||
}
|
||||
|
||||
widget_view("Horizontal Sliders")
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 200},
|
||||
.size.height = {UI_SIZE_PIXELS, 20}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200},
|
||||
.size.height = {OC_UI_SIZE_PIXELS, 20}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
static f32 slider1 = 0;
|
||||
ui_slider("slider1", 0.2, &slider1);
|
||||
oc_ui_slider("slider1", 0.2, &slider1);
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 200},
|
||||
.size.height = {UI_SIZE_PIXELS, 20}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200},
|
||||
.size.height = {OC_UI_SIZE_PIXELS, 20}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
static f32 slider2 = 0;
|
||||
ui_slider("slider2", 0.2, &slider2);
|
||||
oc_ui_slider("slider2", 0.2, &slider2);
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 200},
|
||||
.size.height = {UI_SIZE_PIXELS, 20}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200},
|
||||
.size.height = {OC_UI_SIZE_PIXELS, 20}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
static f32 slider3 = 0;
|
||||
ui_slider("slider3", 0.2, &slider3);
|
||||
oc_ui_slider("slider3", 0.2, &slider3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {UI_SIZE_PARENT, 1}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
ui_container("right", 0)
|
||||
oc_ui_container("right", 0)
|
||||
{
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 0.33}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 0.33}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
widget_view("Text box")
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 300},
|
||||
.size.height = {UI_SIZE_TEXT}},
|
||||
UI_STYLE_SIZE);
|
||||
static str8 text = {0};
|
||||
ui_text_box_result res = ui_text_box("textbox", mem_scratch(), text);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 300},
|
||||
.size.height = {OC_UI_SIZE_TEXT}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
static oc_str8 text = {0};
|
||||
oc_ui_text_box_result res = oc_ui_text_box("textbox", oc_scratch(), text);
|
||||
if(res.changed)
|
||||
{
|
||||
mem_arena_clear(&textArena);
|
||||
text = str8_push_copy(&textArena, res.text);
|
||||
oc_arena_clear(&textArena);
|
||||
text = oc_str8_push_copy(&textArena, res.text);
|
||||
}
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 0.33}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 0.33}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
widget_view("Test")
|
||||
{
|
||||
ui_pattern pattern = {0};
|
||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("panel")});
|
||||
ui_style_match_after(pattern, &(ui_style){.bgColor = {0.3, 0.3, 1, 1}}, UI_STYLE_BG_COLOR);
|
||||
oc_ui_pattern pattern = {0};
|
||||
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_TEXT, .text = OC_STR8("panel")});
|
||||
oc_ui_style_match_after(pattern, &(oc_ui_style){.bgColor = {0.3, 0.3, 1, 1}}, OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
static int selected = 0;
|
||||
str8 options[] = {STR8("option 1"),
|
||||
STR8("option 2"),
|
||||
STR8("long option 3"),
|
||||
STR8("option 4"),
|
||||
STR8("option 5")};
|
||||
ui_select_popup_info info = {.selectedIndex = selected,
|
||||
oc_str8 options[] = {OC_STR8("option 1"),
|
||||
OC_STR8("option 2"),
|
||||
OC_STR8("long option 3"),
|
||||
OC_STR8("option 4"),
|
||||
OC_STR8("option 5")};
|
||||
oc_ui_select_popup_info info = {.selectedIndex = selected,
|
||||
.optionCount = 5,
|
||||
.options = options};
|
||||
|
||||
ui_select_popup_info result = ui_select_popup("popup", &info);
|
||||
oc_ui_select_popup_info result = oc_ui_select_popup("popup", &info);
|
||||
selected = result.selectedIndex;
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 0.33}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 0.33}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
widget_view("Color")
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 0.7},
|
||||
.layout.axis = UI_AXIS_X},
|
||||
UI_STYLE_SIZE
|
||||
|UI_STYLE_LAYOUT_AXIS);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 0.7},
|
||||
.layout.axis = OC_UI_AXIS_X},
|
||||
OC_UI_STYLE_SIZE
|
||||
|OC_UI_STYLE_LAYOUT_AXIS);
|
||||
|
||||
ui_panel("Panel", UI_FLAG_DRAW_BORDER)
|
||||
oc_ui_panel("Panel", OC_UI_FLAG_DRAW_BORDER)
|
||||
{
|
||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X},
|
||||
UI_STYLE_LAYOUT_AXIS);
|
||||
ui_container("contents", 0)
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X},
|
||||
OC_UI_STYLE_LAYOUT_AXIS);
|
||||
oc_ui_container("contents", 0)
|
||||
{
|
||||
ui_style_next(&(ui_style){.layout.spacing = 20},
|
||||
UI_STYLE_LAYOUT_SPACING);
|
||||
ui_container("buttons", 0)
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.spacing = 20},
|
||||
OC_UI_STYLE_LAYOUT_SPACING);
|
||||
oc_ui_container("buttons", 0)
|
||||
{
|
||||
ui_button("Button A");
|
||||
ui_button("Button B");
|
||||
ui_button("Button C");
|
||||
ui_button("Button D");
|
||||
oc_ui_button("Button A");
|
||||
oc_ui_button("Button B");
|
||||
oc_ui_button("Button C");
|
||||
oc_ui_button("Button D");
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X,
|
||||
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X,
|
||||
.layout.spacing = 20},
|
||||
UI_STYLE_LAYOUT_SPACING
|
||||
|UI_STYLE_LAYOUT_AXIS);
|
||||
OC_UI_STYLE_LAYOUT_SPACING
|
||||
|OC_UI_STYLE_LAYOUT_AXIS);
|
||||
|
||||
ui_container("buttons2", 0)
|
||||
oc_ui_container("buttons2", 0)
|
||||
{
|
||||
ui_button("Button A");
|
||||
ui_button("Button B");
|
||||
ui_button("Button C");
|
||||
ui_button("Button D");
|
||||
oc_ui_button("Button A");
|
||||
oc_ui_button("Button B");
|
||||
oc_ui_button("Button C");
|
||||
oc_ui_button("Button D");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -393,9 +392,9 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
|||
}
|
||||
|
||||
|
||||
mg_canvas_set_current(canvas);
|
||||
mg_surface_prepare(surface);
|
||||
ui_draw();
|
||||
mg_render(surface, canvas);
|
||||
mg_surface_present(surface);
|
||||
oc_canvas_set_current(canvas);
|
||||
oc_surface_select(surface);
|
||||
oc_ui_draw();
|
||||
oc_render(surface, canvas);
|
||||
oc_surface_present(surface);
|
||||
}
|
||||
|
|
|
@ -155,8 +155,8 @@ def bindgen(apiName, spec, **kwargs):
|
|||
if argTag == 'p' and argLen != None:
|
||||
|
||||
s += '\t{\n'
|
||||
s += '\t\tORCA_ASSERT(((char*)'+ argName + ' >= (char*)_mem) && (((char*)'+ argName +' - (char*)_mem) < m3_GetMemorySize(runtime)), "parameter \''+argName+'\' is out of bounds");\n'
|
||||
s += '\t\tORCA_ASSERT((char*)' + argName + ' + '
|
||||
s += '\t\tOC_ASSERT(((char*)'+ argName + ' >= (char*)_mem) && (((char*)'+ argName +' - (char*)_mem) < m3_GetMemorySize(runtime)), "parameter \''+argName+'\' is out of bounds");\n'
|
||||
s += '\t\tOC_ASSERT((char*)' + argName + ' + '
|
||||
|
||||
proc = argLen.get('proc')
|
||||
if proc != None:
|
||||
|
@ -245,7 +245,7 @@ def bindgen(apiName, spec, **kwargs):
|
|||
s += ' res = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3Sig + '", ' + cname + '_stub);\n'
|
||||
s += ' if(res != m3Err_none && res != m3Err_functionLookupFailed)\n'
|
||||
s += ' {\n'
|
||||
s += ' log_error("Couldn\'t link function ' + name + ' (%s)\\n", res);\n'
|
||||
s += ' oc_log_error("Couldn\'t link function ' + name + ' (%s)\\n", res);\n'
|
||||
s += ' ret = -1;\n'
|
||||
s += ' }\n\n'
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ def build_platform_layer_lib_win(release):
|
|||
subprocess.run([
|
||||
"cl", "/nologo",
|
||||
"/we4013", "/Zi", "/Zc:preprocessor",
|
||||
"/DMP_BUILD_DLL",
|
||||
"/DOC_BUILD_DLL",
|
||||
"/std:c11", "/experimental:c11atomics",
|
||||
*includes,
|
||||
"src/orca.c", "/Fo:build/bin/orca.o",
|
||||
|
@ -154,7 +154,7 @@ def build_platform_layer_lib_mac(release):
|
|||
|
||||
flags = ["-mmacos-version-min=10.15.4", "-maes"]
|
||||
cflags = ["-std=c11"]
|
||||
debug_flags = ["-O3"] if release else ["-g", "-DDEBUG", "-DLOG_COMPILE_DEBUG"]
|
||||
debug_flags = ["-O3"] if release else ["-g", "-DOC_DEBUG", "-DOC_LOG_COMPILE_DEBUG"]
|
||||
ldflags = [f"-L{sdk_dir}/usr/lib", f"-F{sdk_dir}/System/Library/Frameworks/"]
|
||||
includes = ["-Isrc", "-Isrc/util", "-Isrc/platform", "-Iext", "-Iext/angle/include"]
|
||||
|
||||
|
@ -327,7 +327,7 @@ def build_orca_mac(release):
|
|||
"-Iext/wasm3/source"
|
||||
]
|
||||
libs = ["-Lbuild/bin", "-Lbuild/lib", "-lorca", "-lwasm3"]
|
||||
debug_flags = ["-O2"] if release else ["-g", "-DLOG_COMPILE_DEBUG"]
|
||||
debug_flags = ["-O2"] if release else ["-g", "-DOC_DEBUG -DOC_LOG_COMPILE_DEBUG"]
|
||||
flags = [
|
||||
*debug_flags,
|
||||
"-mmacos-version-min=10.15.4",
|
||||
|
|
|
@ -99,21 +99,21 @@ f.write('#include"GL/glcorearb.h"\n')
|
|||
f.write('#include"GLES3/gl32.h"\n\n')
|
||||
|
||||
# generate interface struct
|
||||
f.write('typedef struct mg_gl_api\n{\n')
|
||||
f.write('typedef struct oc_gl_api\n{\n')
|
||||
|
||||
f.write(' const char* name;\n')
|
||||
|
||||
for func in glall:
|
||||
f.write('\t' + 'PFN' + func.upper() + 'PROC ' + remove_prefix(func, 'gl') + ';\n')
|
||||
|
||||
f.write('} mg_gl_api;\n\n')
|
||||
f.write('} oc_gl_api;\n\n')
|
||||
|
||||
# generate interface macros
|
||||
# TODO guard for different api/versions and only #define functions present in desired version
|
||||
f.write("MP_API mg_gl_api* mg_gl_get_api(void);\n\n")
|
||||
f.write("ORCA_API oc_gl_api* oc_gl_get_api(void);\n\n")
|
||||
|
||||
for func in glall:
|
||||
f.write('#define ' + func + ' mg_gl_get_api()->' + remove_prefix(func, 'gl') + '\n')
|
||||
f.write('#define ' + func + ' oc_gl_get_api()->' + remove_prefix(func, 'gl') + '\n')
|
||||
|
||||
emit_end_guard(f, apiName)
|
||||
f.close()
|
||||
|
@ -129,15 +129,15 @@ emit_begin_guard(f, loaderName)
|
|||
|
||||
f.write('#include"gl_api.h"\n\n')
|
||||
|
||||
f.write("typedef void*(*mg_gl_load_proc)(const char* name);\n\n")
|
||||
f.write("typedef void*(*oc_gl_load_proc)(const char* name);\n\n")
|
||||
|
||||
f.write("void mg_gl_load_gl41(mg_gl_api* api, mg_gl_load_proc loadProc);\n")
|
||||
f.write("void mg_gl_load_gl43(mg_gl_api* api, mg_gl_load_proc loadProc);\n")
|
||||
f.write("void mg_gl_load_gl44(mg_gl_api* api, mg_gl_load_proc loadProc);\n")
|
||||
f.write("void mg_gl_load_gles30(mg_gl_api* api, mg_gl_load_proc loadProc);\n")
|
||||
f.write("void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);\n\n")
|
||||
f.write("void oc_gl_load_gl41(oc_gl_api* api, oc_gl_load_proc loadProc);\n")
|
||||
f.write("void oc_gl_load_gl43(oc_gl_api* api, oc_gl_load_proc loadProc);\n")
|
||||
f.write("void oc_gl_load_gl44(oc_gl_api* api, oc_gl_load_proc loadProc);\n")
|
||||
f.write("void oc_gl_load_gles30(oc_gl_api* api, oc_gl_load_proc loadProc);\n")
|
||||
f.write("void oc_gl_load_gles31(oc_gl_api* api, oc_gl_load_proc loadProc);\n\n")
|
||||
|
||||
f.write("void mg_gl_select_api(mg_gl_api* api);\n\n")
|
||||
f.write("void oc_gl_select_api(oc_gl_api* api);\n\n")
|
||||
|
||||
emit_end_guard(f, loaderName)
|
||||
f.close()
|
||||
|
@ -146,7 +146,7 @@ f.close()
|
|||
#---------------------------------------------------------------
|
||||
|
||||
def emit_loader(f, name, procs):
|
||||
f.write('void mg_gl_load_'+ name +'(mg_gl_api* api, mg_gl_load_proc loadProc)\n')
|
||||
f.write('void oc_gl_load_'+ name +'(oc_gl_api* api, oc_gl_load_proc loadProc)\n')
|
||||
f.write("{\n")
|
||||
f.write(' api->name = "'+ name +'";\n')
|
||||
|
||||
|
@ -154,14 +154,14 @@ def emit_loader(f, name, procs):
|
|||
if proc in procs:
|
||||
f.write(' api->' + remove_prefix(proc, 'gl') + ' = loadProc("' + proc + '");\n')
|
||||
else:
|
||||
f.write(' api->' + remove_prefix(proc, 'gl') + ' = mg_' + proc + '_noimpl;\n')
|
||||
f.write(' api->' + remove_prefix(proc, 'gl') + ' = oc_' + proc + '_noimpl;\n')
|
||||
|
||||
f.write("}\n\n")
|
||||
|
||||
|
||||
def emit_null_api(f, procs):
|
||||
|
||||
f.write('mg_gl_api __mgGLNoAPI;\n\n')
|
||||
f.write('oc_gl_api oc_glNoAPI;\n\n')
|
||||
|
||||
for name in procs:
|
||||
|
||||
|
@ -185,7 +185,7 @@ def emit_null_api(f, procs):
|
|||
|
||||
retType = retType.strip()
|
||||
|
||||
f.write(retType + ' mg_' + name + '_noimpl(')
|
||||
f.write(retType + ' oc_' + name + '_noimpl(')
|
||||
|
||||
params = command.findall('param')
|
||||
|
||||
|
@ -217,21 +217,21 @@ def emit_null_api(f, procs):
|
|||
|
||||
f.write(')\n')
|
||||
f.write('{\n')
|
||||
f.write(' if(__mgGLAPI == &__mgGLNoAPI)\n')
|
||||
f.write(' if(oc_glAPI == &oc_glNoAPI)\n')
|
||||
f.write(' {\n')
|
||||
f.write(' log_error("No GL or GLES API is selected. Make sure you call mg_surface_prepare() before calling OpenGL API functions.\\n");\n')
|
||||
f.write(' oc_log_error("No GL or GLES API is selected. Make sure you call oc_surface_prepare() before calling OpenGL API functions.\\n");\n')
|
||||
f.write(' }\n')
|
||||
f.write(' else\n')
|
||||
f.write(' {\n')
|
||||
f.write(' log_error("'+ name +' is not part of currently selected %s API\\n", __mgGLAPI->name);\n')
|
||||
f.write(' oc_log_error("'+ name +' is not part of currently selected %s API\\n", oc_glAPI->name);\n')
|
||||
f.write(' }\n')
|
||||
if retType != 'void':
|
||||
f.write(' return(('+ retType +')0);\n')
|
||||
f.write('}\n')
|
||||
|
||||
f.write('mg_gl_api __mgGLNoAPI = {\n')
|
||||
f.write('oc_gl_api oc_glNoAPI = {\n')
|
||||
for proc in procs:
|
||||
f.write(' .' + remove_prefix(proc, 'gl') + ' = mg_' + proc + '_noimpl,\n')
|
||||
f.write(' .' + remove_prefix(proc, 'gl') + ' = oc_' + proc + '_noimpl,\n')
|
||||
f.write("};\n\n")
|
||||
|
||||
f = open(loaderCPath, 'w')
|
||||
|
@ -241,7 +241,7 @@ emit_doc(f, loaderName, '.c')
|
|||
f.write('#include"' + loaderName + '.h"\n')
|
||||
f.write('#include"platform/platform.h"\n\n')
|
||||
|
||||
f.write("mp_thread_local mg_gl_api* __mgGLAPI = 0;\n")
|
||||
f.write("oc_thread_local oc_gl_api* oc_glAPI = 0;\n")
|
||||
|
||||
emit_null_api(f, glall)
|
||||
emit_loader(f, 'gl41', gl41)
|
||||
|
@ -250,8 +250,8 @@ emit_loader(f, 'gl44', gl44)
|
|||
emit_loader(f, 'gles31', gles31)
|
||||
emit_loader(f, 'gles32', gles32)
|
||||
|
||||
f.write("void mg_gl_select_api(mg_gl_api* api){ __mgGLAPI = api; }\n")
|
||||
f.write("void mg_gl_deselect_api(){ __mgGLAPI = &__mgGLNoAPI; }\n")
|
||||
f.write("mg_gl_api* mg_gl_get_api(void) { return(__mgGLAPI); }\n\n")
|
||||
f.write("void oc_gl_select_api(oc_gl_api* api){ oc_glAPI = api; }\n")
|
||||
f.write("void oc_gl_deselect_api(){ oc_glAPI = &oc_glNoAPI; }\n")
|
||||
f.write("oc_gl_api* oc_gl_get_api(void) { return(oc_glAPI); }\n\n")
|
||||
|
||||
f.close()
|
||||
|
|
|
@ -6,7 +6,7 @@ SRCDIR=../../src
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_atlas main.c
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ EXTDIR=../../ext
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$EXTDIR"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_canvas main.c
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ SRCDIR=../../src
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_image main.c
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ EXTDIR=../../ext
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_multi_surface main.c
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ SRCDIR=../../src
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_polygon main.c
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ EXTDIR=../../ext
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_render_thread main.c
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ EXTDIR=../../ext
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS -Wl,-dead_strip $LIBS $INCLUDES -o $BINDIR/example_simple_window main.c
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ SRCDIR=../../src
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_smooth_resize main.c
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ EXTDIR=../../ext
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_surface_sharing main.c
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ EXTDIR=../../ext
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$EXTDIR"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_tiger main.c
|
||||
|
||||
|
|
|
@ -6,6 +6,6 @@ SRCDIR=../../src
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o test main.c
|
||||
|
|
|
@ -7,7 +7,7 @@ EXTDIR=../../ext
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_gles_triangle main.c
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ SRCDIR=../../src
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost -framework Foundation -framework Metal"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
xcrun -sdk macosx metal -c -o shader.air shader.metal
|
||||
xcrun -sdk macosx metallib -o shader.metallib shader.air
|
||||
|
|
|
@ -6,7 +6,7 @@ SRCDIR=../../src
|
|||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_ui main.c
|
||||
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: app.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 23/12/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#include"platform/platform_debug.h"
|
||||
#include"app_internal.h"
|
||||
|
||||
oc_app oc_appData = {0};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Window handles
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void oc_init_window_handles()
|
||||
{
|
||||
oc_list_init(&oc_appData.windowFreeList);
|
||||
for(int i=0; i<OC_APP_MAX_WINDOWS; i++)
|
||||
{
|
||||
oc_appData.windowPool[i].generation = 1;
|
||||
oc_list_append(&oc_appData.windowFreeList, &oc_appData.windowPool[i].freeListElt);
|
||||
}
|
||||
}
|
||||
|
||||
bool oc_window_handle_is_null(oc_window window)
|
||||
{
|
||||
return(window.h == 0);
|
||||
}
|
||||
|
||||
oc_window oc_window_null_handle()
|
||||
{
|
||||
return((oc_window){.h = 0});
|
||||
}
|
||||
|
||||
oc_window_data* oc_window_alloc()
|
||||
{
|
||||
return(oc_list_pop_entry(&oc_appData.windowFreeList, oc_window_data, freeListElt));
|
||||
}
|
||||
|
||||
oc_window_data* oc_window_ptr_from_handle(oc_window handle)
|
||||
{
|
||||
u32 index = handle.h>>32;
|
||||
u32 generation = handle.h & 0xffffffff;
|
||||
if(index >= OC_APP_MAX_WINDOWS)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
oc_window_data* window = &oc_appData.windowPool[index];
|
||||
if(window->generation != generation)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(window);
|
||||
}
|
||||
}
|
||||
|
||||
oc_window oc_window_handle_from_ptr(oc_window_data* window)
|
||||
{
|
||||
OC_DEBUG_ASSERT( (window - oc_appData.windowPool) >= 0
|
||||
&& (window - oc_appData.windowPool) < OC_APP_MAX_WINDOWS);
|
||||
|
||||
u64 h = ((u64)(window - oc_appData.windowPool))<<32
|
||||
| ((u64)window->generation);
|
||||
|
||||
return((oc_window){h});
|
||||
}
|
||||
|
||||
void oc_window_recycle_ptr(oc_window_data* window)
|
||||
{
|
||||
window->generation++;
|
||||
oc_list_push(&oc_appData.windowFreeList, &window->freeListElt);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Init
|
||||
//---------------------------------------------------------------
|
||||
|
||||
static void oc_init_common()
|
||||
{
|
||||
oc_init_window_handles();
|
||||
oc_ringbuffer_init(&oc_appData.eventQueue, 16);
|
||||
}
|
||||
|
||||
static void oc_terminate_common()
|
||||
{
|
||||
oc_ringbuffer_cleanup(&oc_appData.eventQueue);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Event handling
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void oc_queue_event(oc_event* event)
|
||||
{
|
||||
oc_ringbuffer* queue = &oc_appData.eventQueue;
|
||||
|
||||
if(oc_ringbuffer_write_available(queue) < sizeof(oc_event))
|
||||
{
|
||||
oc_log_error("event queue full\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool error = false;
|
||||
oc_ringbuffer_reserve(queue, sizeof(oc_event), (u8*)event);
|
||||
|
||||
if(event->type == OC_EVENT_PATHDROP)
|
||||
{
|
||||
oc_list_for(&event->paths.list, elt, oc_str8_elt, listElt)
|
||||
{
|
||||
oc_str8* path = &elt->string;
|
||||
if(oc_ringbuffer_write_available(queue) < (sizeof(u64) + path->len))
|
||||
{
|
||||
oc_log_error("event queue full\n");
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
oc_ringbuffer_reserve(queue, sizeof(u64), (u8*)&path->len);
|
||||
oc_ringbuffer_reserve(queue, path->len, (u8*)path->ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(error)
|
||||
{
|
||||
oc_ringbuffer_rewind(queue);
|
||||
}
|
||||
else
|
||||
{
|
||||
oc_ringbuffer_commit(queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oc_event* oc_next_event(oc_arena* arena)
|
||||
{
|
||||
//NOTE: pop and return event from queue
|
||||
oc_event* event = 0;
|
||||
oc_ringbuffer* queue = &oc_appData.eventQueue;
|
||||
|
||||
if(oc_ringbuffer_read_available(queue) >= sizeof(oc_event))
|
||||
{
|
||||
event = oc_arena_push_type(arena, oc_event);
|
||||
u64 read = oc_ringbuffer_read(queue, sizeof(oc_event), (u8*)event);
|
||||
OC_DEBUG_ASSERT(read == sizeof(oc_event));
|
||||
|
||||
if(event->type == OC_EVENT_PATHDROP)
|
||||
{
|
||||
u64 pathCount = event->paths.eltCount;
|
||||
event->paths = (oc_str8_list){0};
|
||||
|
||||
for(int i=0; i<pathCount; i++)
|
||||
{
|
||||
if(oc_ringbuffer_read_available(queue) < sizeof(u64))
|
||||
{
|
||||
oc_log_error("malformed path payload: no string size\n");
|
||||
break;
|
||||
}
|
||||
|
||||
u64 len = 0;
|
||||
oc_ringbuffer_read(queue, sizeof(u64), (u8*)&len);
|
||||
if(oc_ringbuffer_read_available(queue) < len)
|
||||
{
|
||||
oc_log_error("malformed path payload: string shorter than expected\n");
|
||||
break;
|
||||
}
|
||||
|
||||
char* buffer = oc_arena_push_array(arena, char, len);
|
||||
oc_ringbuffer_read(queue, len, (u8*)buffer);
|
||||
|
||||
oc_str8_list_push(arena, &event->paths, oc_str8_from_buffer(len, buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(event);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// window rects helpers
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void oc_window_set_content_position(oc_window window, oc_vec2 position)
|
||||
{
|
||||
oc_rect rect = oc_window_get_content_rect(window);
|
||||
rect.x = position.x;
|
||||
rect.y = position.y;
|
||||
oc_window_set_content_rect(window, rect);
|
||||
}
|
||||
|
||||
void oc_window_set_content_size(oc_window window, oc_vec2 size)
|
||||
{
|
||||
oc_rect rect = oc_window_get_content_rect(window);
|
||||
rect.w = size.x;
|
||||
rect.h = size.y;
|
||||
oc_window_set_content_rect(window, rect);
|
||||
}
|
||||
|
||||
void oc_window_set_frame_position(oc_window window, oc_vec2 position)
|
||||
{
|
||||
oc_rect frame = oc_window_get_frame_rect(window);
|
||||
frame.x = position.x;
|
||||
frame.y = position.y;
|
||||
oc_window_set_frame_rect(window, frame);
|
||||
}
|
||||
|
||||
void oc_window_set_frame_size(oc_window window, oc_vec2 size)
|
||||
{
|
||||
oc_rect frame = oc_window_get_frame_rect(window);
|
||||
frame.w = size.x;
|
||||
frame.h = size.y;
|
||||
oc_window_set_frame_rect(window, frame);
|
||||
}
|
|
@ -0,0 +1,392 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: platform_app.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 16/05/2020
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __APP_H_
|
||||
#define __APP_H_
|
||||
|
||||
#include"util/typedefs.h"
|
||||
#include"util/utf8.h"
|
||||
#include"util/lists.h"
|
||||
#include"util/memory.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Typedefs, enums and constants
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
typedef struct oc_window { u64 h; } oc_window;
|
||||
|
||||
typedef enum { OC_MOUSE_CURSOR_ARROW,
|
||||
OC_MOUSE_CURSOR_RESIZE_0,
|
||||
OC_MOUSE_CURSOR_RESIZE_90,
|
||||
OC_MOUSE_CURSOR_RESIZE_45,
|
||||
OC_MOUSE_CURSOR_RESIZE_135,
|
||||
OC_MOUSE_CURSOR_TEXT } oc_mouse_cursor;
|
||||
|
||||
typedef i32 oc_window_style;
|
||||
static const oc_window_style OC_WINDOW_STYLE_NO_TITLE = 0x01<<0,
|
||||
OC_WINDOW_STYLE_FIXED_SIZE = 0x01<<1,
|
||||
OC_WINDOW_STYLE_NO_CLOSE = 0x01<<2,
|
||||
OC_WINDOW_STYLE_NO_MINIFY = 0x01<<3,
|
||||
OC_WINDOW_STYLE_NO_FOCUS = 0x01<<4,
|
||||
OC_WINDOW_STYLE_FLOAT = 0x01<<5,
|
||||
OC_WINDOW_STYLE_POPUPMENU = 0x01<<6,
|
||||
OC_WINDOW_STYLE_NO_BUTTONS = 0x01<<7;
|
||||
|
||||
typedef enum { OC_EVENT_NONE,
|
||||
OC_EVENT_KEYBOARD_MODS, //TODO: remove, keep only key?
|
||||
OC_EVENT_KEYBOARD_KEY,
|
||||
OC_EVENT_KEYBOARD_CHAR,
|
||||
OC_EVENT_MOUSE_BUTTON,
|
||||
OC_EVENT_MOUSE_MOVE,
|
||||
OC_EVENT_MOUSE_WHEEL,
|
||||
OC_EVENT_MOUSE_ENTER,
|
||||
OC_EVENT_MOUSE_LEAVE,
|
||||
OC_EVENT_WINDOW_RESIZE,
|
||||
OC_EVENT_WINDOW_MOVE,
|
||||
OC_EVENT_WINDOW_FOCUS,
|
||||
OC_EVENT_WINDOW_UNFOCUS,
|
||||
OC_EVENT_WINDOW_HIDE, // rename to minimize?
|
||||
OC_EVENT_WINDOW_SHOW, // rename to restore?
|
||||
OC_EVENT_WINDOW_CLOSE,
|
||||
OC_EVENT_PATHDROP,
|
||||
OC_EVENT_FRAME,
|
||||
OC_EVENT_QUIT } oc_event_type;
|
||||
|
||||
typedef enum { OC_KEY_NO_ACTION,
|
||||
OC_KEY_PRESS,
|
||||
OC_KEY_RELEASE,
|
||||
OC_KEY_REPEAT } oc_key_action;
|
||||
|
||||
typedef enum { OC_KEY_UNKNOWN = 0,
|
||||
OC_KEY_SPACE = 32,
|
||||
OC_KEY_APOSTROPHE = 39, /* ' */
|
||||
OC_KEY_COMMA = 44, /* , */
|
||||
OC_KEY_MINUS = 45, // -
|
||||
OC_KEY_PERIOD = 46, // .
|
||||
OC_KEY_SLASH = 47, // /
|
||||
OC_KEY_0 = 48,
|
||||
OC_KEY_1 = 49,
|
||||
OC_KEY_2 = 50,
|
||||
OC_KEY_3 = 51,
|
||||
OC_KEY_4 = 52,
|
||||
OC_KEY_5 = 53,
|
||||
OC_KEY_6 = 54,
|
||||
OC_KEY_7 = 55,
|
||||
OC_KEY_8 = 56,
|
||||
OC_KEY_9 = 57,
|
||||
OC_KEY_SEMICOLON = 59, // ;
|
||||
OC_KEY_EQUAL = 61, // =
|
||||
OC_KEY_A = 65,
|
||||
OC_KEY_B = 66,
|
||||
OC_KEY_C = 67,
|
||||
OC_KEY_D = 68,
|
||||
OC_KEY_E = 69,
|
||||
OC_KEY_F = 70,
|
||||
OC_KEY_G = 71,
|
||||
OC_KEY_H = 72,
|
||||
OC_KEY_I = 73,
|
||||
OC_KEY_J = 74,
|
||||
OC_KEY_K = 75,
|
||||
OC_KEY_L = 76,
|
||||
OC_KEY_M = 77,
|
||||
OC_KEY_N = 78,
|
||||
OC_KEY_O = 79,
|
||||
OC_KEY_P = 80,
|
||||
OC_KEY_Q = 81,
|
||||
OC_KEY_R = 82,
|
||||
OC_KEY_S = 83,
|
||||
OC_KEY_T = 84,
|
||||
OC_KEY_U = 85,
|
||||
OC_KEY_V = 86,
|
||||
OC_KEY_W = 87,
|
||||
OC_KEY_X = 88,
|
||||
OC_KEY_Y = 89,
|
||||
OC_KEY_Z = 90,
|
||||
OC_KEY_LEFT_BRACKET = 91, // [
|
||||
OC_KEY_BACKSLASH = 92, // \ */
|
||||
OC_KEY_RIGHT_BRACKET = 93, // ]
|
||||
OC_KEY_GRAVE_ACCENT = 96, // `
|
||||
OC_KEY_WORLD_1 = 161, // non-US #1
|
||||
OC_KEY_WORLD_2 = 162, // non-US #2
|
||||
OC_KEY_ESCAPE = 256,
|
||||
OC_KEY_ENTER = 257,
|
||||
OC_KEY_TAB = 258,
|
||||
OC_KEY_BACKSPACE = 259,
|
||||
OC_KEY_INSERT = 260,
|
||||
OC_KEY_DELETE = 261,
|
||||
OC_KEY_RIGHT = 262,
|
||||
OC_KEY_LEFT = 263,
|
||||
OC_KEY_DOWN = 264,
|
||||
OC_KEY_UP = 265,
|
||||
OC_KEY_PAGE_UP = 266,
|
||||
OC_KEY_PAGE_DOWN = 267,
|
||||
OC_KEY_HOME = 268,
|
||||
OC_KEY_END = 269,
|
||||
OC_KEY_CAPS_LOCK = 280,
|
||||
OC_KEY_SCROLL_LOCK = 281,
|
||||
OC_KEY_NUM_LOCK = 282,
|
||||
OC_KEY_PRINT_SCREEN = 283,
|
||||
OC_KEY_PAUSE = 284,
|
||||
OC_KEY_F1 = 290,
|
||||
OC_KEY_F2 = 291,
|
||||
OC_KEY_F3 = 292,
|
||||
OC_KEY_F4 = 293,
|
||||
OC_KEY_F5 = 294,
|
||||
OC_KEY_F6 = 295,
|
||||
OC_KEY_F7 = 296,
|
||||
OC_KEY_F8 = 297,
|
||||
OC_KEY_F9 = 298,
|
||||
OC_KEY_F10 = 299,
|
||||
OC_KEY_F11 = 300,
|
||||
OC_KEY_F12 = 301,
|
||||
OC_KEY_F13 = 302,
|
||||
OC_KEY_F14 = 303,
|
||||
OC_KEY_F15 = 304,
|
||||
OC_KEY_F16 = 305,
|
||||
OC_KEY_F17 = 306,
|
||||
OC_KEY_F18 = 307,
|
||||
OC_KEY_F19 = 308,
|
||||
OC_KEY_F20 = 309,
|
||||
OC_KEY_F21 = 310,
|
||||
OC_KEY_F22 = 311,
|
||||
OC_KEY_F23 = 312,
|
||||
OC_KEY_F24 = 313,
|
||||
OC_KEY_F25 = 314,
|
||||
OC_KEY_KP_0 = 320,
|
||||
OC_KEY_KP_1 = 321,
|
||||
OC_KEY_KP_2 = 322,
|
||||
OC_KEY_KP_3 = 323,
|
||||
OC_KEY_KP_4 = 324,
|
||||
OC_KEY_KP_5 = 325,
|
||||
OC_KEY_KP_6 = 326,
|
||||
OC_KEY_KP_7 = 327,
|
||||
OC_KEY_KP_8 = 328,
|
||||
OC_KEY_KP_9 = 329,
|
||||
OC_KEY_KP_DECIMAL = 330,
|
||||
OC_KEY_KP_DIVIDE = 331,
|
||||
OC_KEY_KP_MULTIPLY = 332,
|
||||
OC_KEY_KP_SUBTRACT = 333,
|
||||
OC_KEY_KP_ADD = 334,
|
||||
OC_KEY_KP_ENTER = 335,
|
||||
OC_KEY_KP_EQUAL = 336,
|
||||
OC_KEY_LEFT_SHIFT = 340,
|
||||
OC_KEY_LEFT_CONTROL = 341,
|
||||
OC_KEY_LEFT_ALT = 342,
|
||||
OC_KEY_LEFT_SUPER = 343,
|
||||
OC_KEY_RIGHT_SHIFT = 344,
|
||||
OC_KEY_RIGHT_CONTROL = 345,
|
||||
OC_KEY_RIGHT_ALT = 346,
|
||||
OC_KEY_RIGHT_SUPER = 347,
|
||||
OC_KEY_MENU = 348,
|
||||
OC_KEY_COUNT } oc_key_code;
|
||||
|
||||
typedef enum {
|
||||
OC_KEYMOD_NONE = 0x00,
|
||||
OC_KEYMOD_ALT = 0x01,
|
||||
OC_KEYMOD_SHIFT = 0x02,
|
||||
OC_KEYMOD_CTRL = 0x04,
|
||||
OC_KEYMOD_CMD = 0x08,
|
||||
OC_KEYMOD_MAIN_MODIFIER = 0x16 /* CMD on Mac, CTRL on Win32 */ } oc_keymod_flags;
|
||||
|
||||
typedef enum {
|
||||
OC_MOUSE_LEFT = 0x00,
|
||||
OC_MOUSE_RIGHT = 0x01,
|
||||
OC_MOUSE_MIDDLE = 0x02,
|
||||
OC_MOUSE_EXT1 = 0x03,
|
||||
OC_MOUSE_EXT2 = 0x04,
|
||||
OC_MOUSE_BUTTON_COUNT } oc_mouse_button;
|
||||
|
||||
typedef struct oc_key_event // keyboard and mouse buttons input
|
||||
{
|
||||
oc_key_action action;
|
||||
i32 code;
|
||||
oc_keymod_flags mods;
|
||||
char label[8];
|
||||
u8 labelLen;
|
||||
int clickCount;
|
||||
} oc_key_event;
|
||||
|
||||
typedef struct oc_char_event // character input
|
||||
{
|
||||
oc_utf32 codepoint;
|
||||
char sequence[8];
|
||||
u8 seqLen;
|
||||
} oc_char_event;
|
||||
|
||||
typedef struct oc_mouse_event // mouse move/scroll
|
||||
{
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 deltaX;
|
||||
f32 deltaY;
|
||||
oc_keymod_flags mods;
|
||||
} oc_mouse_event;
|
||||
|
||||
typedef struct oc_move_event // window resize / move
|
||||
{
|
||||
oc_rect frame;
|
||||
oc_rect content;
|
||||
} oc_move_event;
|
||||
|
||||
typedef struct oc_event
|
||||
{
|
||||
//TODO clipboard and path drop
|
||||
oc_window window;
|
||||
oc_event_type type;
|
||||
|
||||
union
|
||||
{
|
||||
oc_key_event key;
|
||||
oc_char_event character;
|
||||
oc_mouse_event mouse;
|
||||
oc_move_event move;
|
||||
oc_str8_list paths;
|
||||
};
|
||||
|
||||
} oc_event;
|
||||
|
||||
//NOTE: these APIs are not directly available to Orca apps
|
||||
#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
|
||||
//--------------------------------------------------------------------
|
||||
// app management
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
ORCA_API void oc_init(void);
|
||||
ORCA_API void oc_terminate(void);
|
||||
|
||||
ORCA_API bool oc_should_quit(void);
|
||||
ORCA_API void oc_cancel_quit(void);
|
||||
ORCA_API void oc_request_quit(void);
|
||||
|
||||
ORCA_API void oc_set_cursor(oc_mouse_cursor cursor);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Main loop and events handling
|
||||
//--------------------------------------------------------------------
|
||||
/*NOTE:
|
||||
oc_pump_events() pumps system events into the event queue. A timeout of 0 polls for events,
|
||||
while a timeout of -1 blocks for events. A timeout > 0 blocks until new events are available
|
||||
or the timeout elapses.
|
||||
|
||||
oc_next_event() get the next event from the event queue, allocating from the passed arena
|
||||
*/
|
||||
ORCA_API void oc_pump_events(f64 timeout);
|
||||
ORCA_API oc_event* oc_next_event(oc_arena* arena);
|
||||
|
||||
typedef void(*oc_live_resize_callback)(oc_event event, void* data);
|
||||
ORCA_API void oc_set_live_resize_callback(oc_live_resize_callback callback, void* data);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// window management
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
ORCA_API bool oc_window_handle_is_null(oc_window window);
|
||||
ORCA_API oc_window oc_window_null_handle(void);
|
||||
|
||||
ORCA_API oc_window oc_window_create(oc_rect contentRect, oc_str8 title, oc_window_style style);
|
||||
ORCA_API void oc_window_destroy(oc_window window);
|
||||
ORCA_API void* oc_window_native_pointer(oc_window window);
|
||||
|
||||
ORCA_API bool oc_window_should_close(oc_window window);
|
||||
ORCA_API void oc_window_request_close(oc_window window);
|
||||
ORCA_API void oc_window_cancel_close(oc_window window);
|
||||
|
||||
ORCA_API bool oc_window_is_hidden(oc_window window);
|
||||
ORCA_API void oc_window_hide(oc_window window);
|
||||
ORCA_API void oc_window_show(oc_window window);
|
||||
|
||||
ORCA_API bool oc_window_is_minimized(oc_window window);
|
||||
ORCA_API bool oc_window_is_maximized(oc_window window);
|
||||
ORCA_API void oc_window_minimize(oc_window window);
|
||||
ORCA_API void oc_window_maximize(oc_window window);
|
||||
ORCA_API void oc_window_restore(oc_window window);
|
||||
|
||||
ORCA_API bool oc_window_has_focus(oc_window window);
|
||||
ORCA_API void oc_window_focus(oc_window window);
|
||||
ORCA_API void oc_window_unfocus(oc_window window);
|
||||
|
||||
ORCA_API void oc_window_send_to_back(oc_window window);
|
||||
ORCA_API void oc_window_bring_to_front(oc_window window);
|
||||
|
||||
ORCA_API oc_rect oc_window_get_frame_rect(oc_window window);
|
||||
ORCA_API void oc_window_set_frame_rect(oc_window window, oc_rect rect);
|
||||
ORCA_API void oc_window_set_frame_position(oc_window window, oc_vec2 position);
|
||||
ORCA_API void oc_window_set_frame_size(oc_window window, oc_vec2 size);
|
||||
|
||||
ORCA_API oc_rect oc_window_get_content_rect(oc_window window);
|
||||
ORCA_API void oc_window_set_content_rect(oc_window window, oc_rect rect);
|
||||
ORCA_API void oc_window_set_content_position(oc_window window, oc_vec2 position);
|
||||
ORCA_API void oc_window_set_content_size(oc_window window, oc_vec2 size);
|
||||
|
||||
ORCA_API void oc_window_center(oc_window window);
|
||||
|
||||
ORCA_API oc_rect oc_window_content_rect_for_frame_rect(oc_rect frameRect, oc_window_style style);
|
||||
ORCA_API oc_rect oc_window_frame_rect_for_content_rect(oc_rect contentRect, oc_window_style style);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Dispatching stuff to the main thread
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef i32 (*oc_dispatch_proc)(void* user);
|
||||
|
||||
ORCA_API i32 oc_dispatch_on_main_thread_sync(oc_window main_window, oc_dispatch_proc proc, void* user);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Clipboard
|
||||
//--------------------------------------------------------------------
|
||||
ORCA_API void oc_clipboard_clear(void);
|
||||
|
||||
ORCA_API void oc_clipboard_set_string(oc_str8 string);
|
||||
ORCA_API oc_str8 oc_clipboard_get_string(oc_arena* arena);
|
||||
ORCA_API oc_str8 oc_clipboard_copy_string(oc_str8 backing);
|
||||
|
||||
ORCA_API bool oc_clipboard_has_tag(const char* tag);
|
||||
ORCA_API void oc_clipboard_set_data_for_tag(const char* tag, oc_str8 data);
|
||||
ORCA_API oc_str8 oc_clipboard_get_data_for_tag(oc_arena* arena, const char* tag);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// native open/save/alert windows
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
ORCA_API oc_str8 oc_open_dialog(oc_arena* arena,
|
||||
oc_str8 title,
|
||||
oc_str8 defaultPath,
|
||||
oc_str8_list filters,
|
||||
bool directory);
|
||||
|
||||
ORCA_API oc_str8 oc_save_dialog(oc_arena* arena,
|
||||
oc_str8 title,
|
||||
oc_str8 defaultPath,
|
||||
oc_str8_list filters);
|
||||
|
||||
ORCA_API int oc_alert_popup(oc_str8 title,
|
||||
oc_str8 message,
|
||||
oc_str8_list options);
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// file system stuff... //TODO: move elsewhere
|
||||
//--------------------------------------------------------------------
|
||||
ORCA_API int oc_file_move(oc_str8 from, oc_str8 to);
|
||||
ORCA_API int oc_file_remove(oc_str8 path);
|
||||
|
||||
ORCA_API int oc_directory_create(oc_str8 path);
|
||||
|
||||
|
||||
#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif //__APP_H_
|
|
@ -1,22 +1,22 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: mp_app_internal.h
|
||||
* @file: app_internal.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 23/12/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __MP_APP_INTERNAL_H_
|
||||
#define __MP_APP_INTERNAL_H_
|
||||
#ifndef __APP_INTERNAL_H_
|
||||
#define __APP_INTERNAL_H_
|
||||
|
||||
#include"mp_app.h"
|
||||
#include"app.h"
|
||||
|
||||
#include"platform/platform.h"
|
||||
#include"util/ringbuffer.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#if OC_PLATFORM_WINDOWS
|
||||
#include"win32_app.h"
|
||||
#elif PLATFORM_MACOS
|
||||
#elif OC_PLATFORM_MACOS
|
||||
#include"osx_app.h"
|
||||
#else
|
||||
#error "platform not supported yet"
|
||||
|
@ -26,66 +26,66 @@
|
|||
// Window structure
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef struct mp_frame_stats
|
||||
typedef struct oc_frame_stats
|
||||
{
|
||||
f64 start;
|
||||
f64 workTime;
|
||||
f64 remainingTime;
|
||||
f64 targetFramePeriod;
|
||||
} mp_frame_stats;
|
||||
} oc_frame_stats;
|
||||
|
||||
typedef struct mp_window_data
|
||||
typedef struct oc_window_data
|
||||
{
|
||||
list_elt freeListElt;
|
||||
oc_list_elt freeListElt;
|
||||
u32 generation;
|
||||
|
||||
mp_window_style style;
|
||||
oc_window_style style;
|
||||
|
||||
bool shouldClose; //TODO could be in status flags
|
||||
bool hidden;
|
||||
bool minimized;
|
||||
|
||||
MP_PLATFORM_WINDOW_DATA
|
||||
} mp_window_data;
|
||||
OC_PLATFORM_WINDOW_DATA
|
||||
} oc_window_data;
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Global App State
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef struct mp_key_utf8
|
||||
typedef struct oc_key_utf8
|
||||
{
|
||||
u8 labelLen;
|
||||
char label[8];
|
||||
} mp_key_utf8;
|
||||
} oc_key_utf8;
|
||||
|
||||
|
||||
enum { MP_APP_MAX_WINDOWS = 128 };
|
||||
enum { OC_APP_MAX_WINDOWS = 128 };
|
||||
|
||||
typedef struct mp_app
|
||||
typedef struct oc_app
|
||||
{
|
||||
bool init;
|
||||
bool shouldQuit;
|
||||
bool minimized;
|
||||
|
||||
str8 pendingPathDrop;
|
||||
mem_arena eventArena;
|
||||
oc_str8 pendingPathDrop;
|
||||
oc_arena eventArena;
|
||||
|
||||
ringbuffer eventQueue;
|
||||
oc_ringbuffer eventQueue;
|
||||
|
||||
mp_frame_stats frameStats;
|
||||
oc_frame_stats frameStats;
|
||||
|
||||
mp_window_data windowPool[MP_APP_MAX_WINDOWS];
|
||||
list_info windowFreeList;
|
||||
oc_window_data windowPool[OC_APP_MAX_WINDOWS];
|
||||
oc_list windowFreeList;
|
||||
|
||||
mp_live_resize_callback liveResizeCallback;
|
||||
oc_live_resize_callback liveResizeCallback;
|
||||
void* liveResizeData;
|
||||
|
||||
mp_key_utf8 keyLabels[512];
|
||||
oc_key_utf8 keyLabels[512];
|
||||
int keyCodes[512];
|
||||
int nativeKeys[MP_KEY_COUNT];
|
||||
int nativeKeys[OC_KEY_COUNT];
|
||||
|
||||
MP_PLATFORM_APP_DATA
|
||||
} mp_app;
|
||||
OC_PLATFORM_APP_DATA
|
||||
} oc_app;
|
||||
|
||||
#endif // __MP_APP_INTERNAL_H_
|
||||
#endif // __APP_INTERNAL_H_
|
217
src/app/mp_app.c
217
src/app/mp_app.c
|
@ -1,217 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: mp_app_internal.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 23/12/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#include"platform/platform_debug.h"
|
||||
#include"mp_app_internal.h"
|
||||
|
||||
mp_app __mpApp = {0};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Window handles
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void mp_init_window_handles()
|
||||
{
|
||||
list_init(&__mpApp.windowFreeList);
|
||||
for(int i=0; i<MP_APP_MAX_WINDOWS; i++)
|
||||
{
|
||||
__mpApp.windowPool[i].generation = 1;
|
||||
list_append(&__mpApp.windowFreeList, &__mpApp.windowPool[i].freeListElt);
|
||||
}
|
||||
}
|
||||
|
||||
bool mp_window_handle_is_null(mp_window window)
|
||||
{
|
||||
return(window.h == 0);
|
||||
}
|
||||
|
||||
mp_window mp_window_null_handle()
|
||||
{
|
||||
return((mp_window){.h = 0});
|
||||
}
|
||||
|
||||
mp_window_data* mp_window_alloc()
|
||||
{
|
||||
return(list_pop_entry(&__mpApp.windowFreeList, mp_window_data, freeListElt));
|
||||
}
|
||||
|
||||
mp_window_data* mp_window_ptr_from_handle(mp_window handle)
|
||||
{
|
||||
u32 index = handle.h>>32;
|
||||
u32 generation = handle.h & 0xffffffff;
|
||||
if(index >= MP_APP_MAX_WINDOWS)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
mp_window_data* window = &__mpApp.windowPool[index];
|
||||
if(window->generation != generation)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(window);
|
||||
}
|
||||
}
|
||||
|
||||
mp_window mp_window_handle_from_ptr(mp_window_data* window)
|
||||
{
|
||||
DEBUG_ASSERT( (window - __mpApp.windowPool) >= 0
|
||||
&& (window - __mpApp.windowPool) < MP_APP_MAX_WINDOWS);
|
||||
|
||||
u64 h = ((u64)(window - __mpApp.windowPool))<<32
|
||||
| ((u64)window->generation);
|
||||
|
||||
return((mp_window){h});
|
||||
}
|
||||
|
||||
void mp_window_recycle_ptr(mp_window_data* window)
|
||||
{
|
||||
window->generation++;
|
||||
list_push(&__mpApp.windowFreeList, &window->freeListElt);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Init
|
||||
//---------------------------------------------------------------
|
||||
|
||||
static void mp_init_common()
|
||||
{
|
||||
mp_init_window_handles();
|
||||
ringbuffer_init(&__mpApp.eventQueue, 16);
|
||||
}
|
||||
|
||||
static void mp_terminate_common()
|
||||
{
|
||||
ringbuffer_cleanup(&__mpApp.eventQueue);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Event handling
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void mp_queue_event(mp_event* event)
|
||||
{
|
||||
ringbuffer* queue = &__mpApp.eventQueue;
|
||||
|
||||
if(ringbuffer_write_available(queue) < sizeof(mp_event))
|
||||
{
|
||||
log_error("event queue full\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool error = false;
|
||||
ringbuffer_reserve(queue, sizeof(mp_event), (u8*)event);
|
||||
|
||||
if(event->type == MP_EVENT_PATHDROP)
|
||||
{
|
||||
for_list(&event->paths.list, elt, str8_elt, listElt)
|
||||
{
|
||||
str8* path = &elt->string;
|
||||
if(ringbuffer_write_available(queue) < (sizeof(u64) + path->len))
|
||||
{
|
||||
log_error("event queue full\n");
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ringbuffer_reserve(queue, sizeof(u64), (u8*)&path->len);
|
||||
ringbuffer_reserve(queue, path->len, (u8*)path->ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(error)
|
||||
{
|
||||
ringbuffer_rewind(queue);
|
||||
}
|
||||
else
|
||||
{
|
||||
ringbuffer_commit(queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mp_event* mp_next_event(mem_arena* arena)
|
||||
{
|
||||
//NOTE: pop and return event from queue
|
||||
mp_event* event = 0;
|
||||
ringbuffer* queue = &__mpApp.eventQueue;
|
||||
|
||||
if(ringbuffer_read_available(queue) >= sizeof(mp_event))
|
||||
{
|
||||
event = mem_arena_alloc_type(arena, mp_event);
|
||||
u64 read = ringbuffer_read(queue, sizeof(mp_event), (u8*)event);
|
||||
DEBUG_ASSERT(read == sizeof(mp_event));
|
||||
|
||||
if(event->type == MP_EVENT_PATHDROP)
|
||||
{
|
||||
u64 pathCount = event->paths.eltCount;
|
||||
event->paths = (str8_list){0};
|
||||
|
||||
for(int i=0; i<pathCount; i++)
|
||||
{
|
||||
if(ringbuffer_read_available(queue) < sizeof(u64))
|
||||
{
|
||||
log_error("malformed path payload: no string size\n");
|
||||
break;
|
||||
}
|
||||
|
||||
u64 len = 0;
|
||||
ringbuffer_read(queue, sizeof(u64), (u8*)&len);
|
||||
if(ringbuffer_read_available(queue) < len)
|
||||
{
|
||||
log_error("malformed path payload: string shorter than expected\n");
|
||||
break;
|
||||
}
|
||||
|
||||
char* buffer = mem_arena_alloc_array(arena, char, len);
|
||||
ringbuffer_read(queue, len, (u8*)buffer);
|
||||
|
||||
str8_list_push(arena, &event->paths, str8_from_buffer(len, buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(event);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// window rects helpers
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void mp_window_set_content_position(mp_window window, vec2 position)
|
||||
{
|
||||
mp_rect rect = mp_window_get_content_rect(window);
|
||||
rect.x = position.x;
|
||||
rect.y = position.y;
|
||||
mp_window_set_content_rect(window, rect);
|
||||
}
|
||||
|
||||
void mp_window_set_content_size(mp_window window, vec2 size)
|
||||
{
|
||||
mp_rect rect = mp_window_get_content_rect(window);
|
||||
rect.w = size.x;
|
||||
rect.h = size.y;
|
||||
mp_window_set_content_rect(window, rect);
|
||||
}
|
||||
|
||||
void mp_window_set_frame_position(mp_window window, vec2 position)
|
||||
{
|
||||
mp_rect frame = mp_window_get_frame_rect(window);
|
||||
frame.x = position.x;
|
||||
frame.y = position.y;
|
||||
mp_window_set_frame_rect(window, frame);
|
||||
}
|
||||
|
||||
void mp_window_set_frame_size(mp_window window, vec2 size)
|
||||
{
|
||||
mp_rect frame = mp_window_get_frame_rect(window);
|
||||
frame.w = size.x;
|
||||
frame.h = size.y;
|
||||
mp_window_set_frame_rect(window, frame);
|
||||
}
|
395
src/app/mp_app.h
395
src/app/mp_app.h
|
@ -1,395 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: platform_app.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 16/05/2020
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __PLATFORM_APP_H_
|
||||
#define __PLATFORM_APP_H_
|
||||
|
||||
#include"util/typedefs.h"
|
||||
#include"util/utf8.h"
|
||||
#include"util/lists.h"
|
||||
#include"util/memory.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Typedefs, enums and constants
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
typedef struct mp_window { u64 h; } mp_window;
|
||||
|
||||
typedef enum { MP_MOUSE_CURSOR_ARROW,
|
||||
MP_MOUSE_CURSOR_RESIZE_0,
|
||||
MP_MOUSE_CURSOR_RESIZE_90,
|
||||
MP_MOUSE_CURSOR_RESIZE_45,
|
||||
MP_MOUSE_CURSOR_RESIZE_135,
|
||||
MP_MOUSE_CURSOR_TEXT } mp_mouse_cursor;
|
||||
|
||||
typedef i32 mp_window_style;
|
||||
static const mp_window_style MP_WINDOW_STYLE_NO_TITLE = 0x01<<0,
|
||||
MP_WINDOW_STYLE_FIXED_SIZE = 0x01<<1,
|
||||
MP_WINDOW_STYLE_NO_CLOSE = 0x01<<2,
|
||||
MP_WINDOW_STYLE_NO_MINIFY = 0x01<<3,
|
||||
MP_WINDOW_STYLE_NO_FOCUS = 0x01<<4,
|
||||
MP_WINDOW_STYLE_FLOAT = 0x01<<5,
|
||||
MP_WINDOW_STYLE_POPUPMENU = 0x01<<6,
|
||||
MP_WINDOW_STYLE_NO_BUTTONS = 0x01<<7;
|
||||
|
||||
typedef enum { MP_EVENT_NONE,
|
||||
MP_EVENT_KEYBOARD_MODS, //TODO: remove, keep only key?
|
||||
MP_EVENT_KEYBOARD_KEY,
|
||||
MP_EVENT_KEYBOARD_CHAR,
|
||||
MP_EVENT_MOUSE_BUTTON,
|
||||
MP_EVENT_MOUSE_MOVE,
|
||||
MP_EVENT_MOUSE_WHEEL,
|
||||
MP_EVENT_MOUSE_ENTER,
|
||||
MP_EVENT_MOUSE_LEAVE,
|
||||
MP_EVENT_WINDOW_RESIZE,
|
||||
MP_EVENT_WINDOW_MOVE,
|
||||
MP_EVENT_WINDOW_FOCUS,
|
||||
MP_EVENT_WINDOW_UNFOCUS,
|
||||
MP_EVENT_WINDOW_HIDE, // rename to minimize?
|
||||
MP_EVENT_WINDOW_SHOW, // rename to restore?
|
||||
MP_EVENT_WINDOW_CLOSE,
|
||||
MP_EVENT_PATHDROP,
|
||||
MP_EVENT_FRAME,
|
||||
MP_EVENT_QUIT } mp_event_type;
|
||||
|
||||
typedef enum { MP_KEY_NO_ACTION,
|
||||
MP_KEY_PRESS,
|
||||
MP_KEY_RELEASE,
|
||||
MP_KEY_REPEAT } mp_key_action;
|
||||
|
||||
typedef enum { MP_KEY_UNKNOWN = 0,
|
||||
MP_KEY_SPACE = 32,
|
||||
MP_KEY_APOSTROPHE = 39, /* ' */
|
||||
MP_KEY_COMMA = 44, /* , */
|
||||
MP_KEY_MINUS = 45, // -
|
||||
MP_KEY_PERIOD = 46, // .
|
||||
MP_KEY_SLASH = 47, // /
|
||||
MP_KEY_0 = 48,
|
||||
MP_KEY_1 = 49,
|
||||
MP_KEY_2 = 50,
|
||||
MP_KEY_3 = 51,
|
||||
MP_KEY_4 = 52,
|
||||
MP_KEY_5 = 53,
|
||||
MP_KEY_6 = 54,
|
||||
MP_KEY_7 = 55,
|
||||
MP_KEY_8 = 56,
|
||||
MP_KEY_9 = 57,
|
||||
MP_KEY_SEMICOLON = 59, // ;
|
||||
MP_KEY_EQUAL = 61, // =
|
||||
MP_KEY_A = 65,
|
||||
MP_KEY_B = 66,
|
||||
MP_KEY_C = 67,
|
||||
MP_KEY_D = 68,
|
||||
MP_KEY_E = 69,
|
||||
MP_KEY_F = 70,
|
||||
MP_KEY_G = 71,
|
||||
MP_KEY_H = 72,
|
||||
MP_KEY_I = 73,
|
||||
MP_KEY_J = 74,
|
||||
MP_KEY_K = 75,
|
||||
MP_KEY_L = 76,
|
||||
MP_KEY_M = 77,
|
||||
MP_KEY_N = 78,
|
||||
MP_KEY_O = 79,
|
||||
MP_KEY_P = 80,
|
||||
MP_KEY_Q = 81,
|
||||
MP_KEY_R = 82,
|
||||
MP_KEY_S = 83,
|
||||
MP_KEY_T = 84,
|
||||
MP_KEY_U = 85,
|
||||
MP_KEY_V = 86,
|
||||
MP_KEY_W = 87,
|
||||
MP_KEY_X = 88,
|
||||
MP_KEY_Y = 89,
|
||||
MP_KEY_Z = 90,
|
||||
MP_KEY_LEFT_BRACKET = 91, // [
|
||||
MP_KEY_BACKSLASH = 92, // \ */
|
||||
MP_KEY_RIGHT_BRACKET = 93, // ]
|
||||
MP_KEY_GRAVE_ACCENT = 96, // `
|
||||
MP_KEY_WORLD_1 = 161, // non-US #1
|
||||
MP_KEY_WORLD_2 = 162, // non-US #2
|
||||
MP_KEY_ESCAPE = 256,
|
||||
MP_KEY_ENTER = 257,
|
||||
MP_KEY_TAB = 258,
|
||||
MP_KEY_BACKSPACE = 259,
|
||||
MP_KEY_INSERT = 260,
|
||||
MP_KEY_DELETE = 261,
|
||||
MP_KEY_RIGHT = 262,
|
||||
MP_KEY_LEFT = 263,
|
||||
MP_KEY_DOWN = 264,
|
||||
MP_KEY_UP = 265,
|
||||
MP_KEY_PAGE_UP = 266,
|
||||
MP_KEY_PAGE_DOWN = 267,
|
||||
MP_KEY_HOME = 268,
|
||||
MP_KEY_END = 269,
|
||||
MP_KEY_CAPS_LOCK = 280,
|
||||
MP_KEY_SCROLL_LOCK = 281,
|
||||
MP_KEY_NUM_LOCK = 282,
|
||||
MP_KEY_PRINT_SCREEN = 283,
|
||||
MP_KEY_PAUSE = 284,
|
||||
MP_KEY_F1 = 290,
|
||||
MP_KEY_F2 = 291,
|
||||
MP_KEY_F3 = 292,
|
||||
MP_KEY_F4 = 293,
|
||||
MP_KEY_F5 = 294,
|
||||
MP_KEY_F6 = 295,
|
||||
MP_KEY_F7 = 296,
|
||||
MP_KEY_F8 = 297,
|
||||
MP_KEY_F9 = 298,
|
||||
MP_KEY_F10 = 299,
|
||||
MP_KEY_F11 = 300,
|
||||
MP_KEY_F12 = 301,
|
||||
MP_KEY_F13 = 302,
|
||||
MP_KEY_F14 = 303,
|
||||
MP_KEY_F15 = 304,
|
||||
MP_KEY_F16 = 305,
|
||||
MP_KEY_F17 = 306,
|
||||
MP_KEY_F18 = 307,
|
||||
MP_KEY_F19 = 308,
|
||||
MP_KEY_F20 = 309,
|
||||
MP_KEY_F21 = 310,
|
||||
MP_KEY_F22 = 311,
|
||||
MP_KEY_F23 = 312,
|
||||
MP_KEY_F24 = 313,
|
||||
MP_KEY_F25 = 314,
|
||||
MP_KEY_KP_0 = 320,
|
||||
MP_KEY_KP_1 = 321,
|
||||
MP_KEY_KP_2 = 322,
|
||||
MP_KEY_KP_3 = 323,
|
||||
MP_KEY_KP_4 = 324,
|
||||
MP_KEY_KP_5 = 325,
|
||||
MP_KEY_KP_6 = 326,
|
||||
MP_KEY_KP_7 = 327,
|
||||
MP_KEY_KP_8 = 328,
|
||||
MP_KEY_KP_9 = 329,
|
||||
MP_KEY_KP_DECIMAL = 330,
|
||||
MP_KEY_KP_DIVIDE = 331,
|
||||
MP_KEY_KP_MULTIPLY = 332,
|
||||
MP_KEY_KP_SUBTRACT = 333,
|
||||
MP_KEY_KP_ADD = 334,
|
||||
MP_KEY_KP_ENTER = 335,
|
||||
MP_KEY_KP_EQUAL = 336,
|
||||
MP_KEY_LEFT_SHIFT = 340,
|
||||
MP_KEY_LEFT_CONTROL = 341,
|
||||
MP_KEY_LEFT_ALT = 342,
|
||||
MP_KEY_LEFT_SUPER = 343,
|
||||
MP_KEY_RIGHT_SHIFT = 344,
|
||||
MP_KEY_RIGHT_CONTROL = 345,
|
||||
MP_KEY_RIGHT_ALT = 346,
|
||||
MP_KEY_RIGHT_SUPER = 347,
|
||||
MP_KEY_MENU = 348,
|
||||
MP_KEY_COUNT } mp_key_code;
|
||||
|
||||
typedef enum {
|
||||
MP_KEYMOD_NONE = 0x00,
|
||||
MP_KEYMOD_ALT = 0x01,
|
||||
MP_KEYMOD_SHIFT = 0x02,
|
||||
MP_KEYMOD_CTRL = 0x04,
|
||||
MP_KEYMOD_CMD = 0x08,
|
||||
MP_KEYMOD_MAIN_MODIFIER = 0x16 /* CMD on Mac, CTRL on Win32 */ } mp_keymod_flags;
|
||||
|
||||
typedef enum {
|
||||
MP_MOUSE_LEFT = 0x00,
|
||||
MP_MOUSE_RIGHT = 0x01,
|
||||
MP_MOUSE_MIDDLE = 0x02,
|
||||
MP_MOUSE_EXT1 = 0x03,
|
||||
MP_MOUSE_EXT2 = 0x04,
|
||||
MP_MOUSE_BUTTON_COUNT } mp_mouse_button;
|
||||
|
||||
typedef struct mp_key_event // keyboard and mouse buttons input
|
||||
{
|
||||
mp_key_action action;
|
||||
i32 code;
|
||||
mp_keymod_flags mods;
|
||||
char label[8];
|
||||
u8 labelLen;
|
||||
int clickCount;
|
||||
} mp_key_event;
|
||||
|
||||
typedef struct mp_char_event // character input
|
||||
{
|
||||
utf32 codepoint;
|
||||
char sequence[8];
|
||||
u8 seqLen;
|
||||
} mp_char_event;
|
||||
|
||||
typedef struct mp_mouse_event // mouse move/scroll
|
||||
{
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 deltaX;
|
||||
f32 deltaY;
|
||||
mp_keymod_flags mods;
|
||||
} mp_mouse_event;
|
||||
|
||||
typedef struct mp_move_event // window resize / move
|
||||
{
|
||||
mp_rect frame;
|
||||
mp_rect content;
|
||||
} mp_move_event;
|
||||
|
||||
typedef struct mp_event
|
||||
{
|
||||
//TODO clipboard and path drop
|
||||
mp_window window;
|
||||
mp_event_type type;
|
||||
|
||||
union
|
||||
{
|
||||
mp_key_event key;
|
||||
mp_char_event character;
|
||||
mp_mouse_event mouse;
|
||||
mp_move_event move;
|
||||
str8_list paths;
|
||||
};
|
||||
|
||||
} mp_event;
|
||||
|
||||
//NOTE: these APIs are not directly available to Orca apps
|
||||
#if !defined(PLATFORM_ORCA) || !(PLATFORM_ORCA)
|
||||
//--------------------------------------------------------------------
|
||||
// app management
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
MP_API void mp_init(void);
|
||||
MP_API void mp_terminate(void);
|
||||
|
||||
MP_API bool mp_should_quit(void);
|
||||
MP_API void mp_cancel_quit(void);
|
||||
MP_API void mp_request_quit(void);
|
||||
|
||||
MP_API void mp_set_cursor(mp_mouse_cursor cursor);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Main loop and events handling
|
||||
//--------------------------------------------------------------------
|
||||
/*NOTE:
|
||||
mp_pump_events() pumps system events into the event queue. A timeout of 0 polls for events,
|
||||
while a timeout of -1 blocks for events. A timeout > 0 blocks until new events are available
|
||||
or the timeout elapses.
|
||||
|
||||
mp_next_event() get the next event from the event queue, allocating from the passed arena
|
||||
*/
|
||||
MP_API void mp_pump_events(f64 timeout);
|
||||
MP_API mp_event* mp_next_event(mem_arena* arena);
|
||||
|
||||
typedef void(*mp_live_resize_callback)(mp_event event, void* data);
|
||||
MP_API void mp_set_live_resize_callback(mp_live_resize_callback callback, void* data);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// window management
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
MP_API bool mp_window_handle_is_null(mp_window window);
|
||||
MP_API mp_window mp_window_null_handle(void);
|
||||
|
||||
MP_API mp_window mp_window_create(mp_rect contentRect, const char* title, mp_window_style style);
|
||||
MP_API void mp_window_destroy(mp_window window);
|
||||
MP_API void* mp_window_native_pointer(mp_window window);
|
||||
|
||||
MP_API bool mp_window_should_close(mp_window window);
|
||||
MP_API void mp_window_request_close(mp_window window);
|
||||
MP_API void mp_window_cancel_close(mp_window window);
|
||||
|
||||
MP_API bool mp_window_is_hidden(mp_window window);
|
||||
MP_API void mp_window_hide(mp_window window);
|
||||
MP_API void mp_window_show(mp_window window);
|
||||
|
||||
MP_API bool mp_window_is_minimized(mp_window window);
|
||||
MP_API bool mp_window_is_maximized(mp_window window);
|
||||
MP_API void mp_window_minimize(mp_window window);
|
||||
MP_API void mp_window_maximize(mp_window window);
|
||||
MP_API void mp_window_restore(mp_window window);
|
||||
|
||||
MP_API bool mp_window_has_focus(mp_window window);
|
||||
MP_API void mp_window_focus(mp_window window);
|
||||
MP_API void mp_window_unfocus(mp_window window);
|
||||
|
||||
MP_API void mp_window_send_to_back(mp_window window);
|
||||
MP_API void mp_window_bring_to_front(mp_window window);
|
||||
|
||||
MP_API mp_rect mp_window_get_frame_rect(mp_window window);
|
||||
MP_API void mp_window_set_frame_rect(mp_window window, mp_rect rect);
|
||||
MP_API void mp_window_set_frame_position(mp_window window, vec2 position);
|
||||
MP_API void mp_window_set_frame_size(mp_window window, vec2 size);
|
||||
|
||||
MP_API mp_rect mp_window_get_content_rect(mp_window window);
|
||||
MP_API void mp_window_set_content_rect(mp_window window, mp_rect rect);
|
||||
MP_API void mp_window_set_content_position(mp_window window, vec2 position);
|
||||
MP_API void mp_window_set_content_size(mp_window window, vec2 size);
|
||||
|
||||
MP_API void mp_window_center(mp_window window);
|
||||
|
||||
MP_API mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style);
|
||||
MP_API mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Dispatching stuff to the main thread
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef i32 (*mp_dispatch_proc)(void* user);
|
||||
|
||||
MP_API i32 mp_dispatch_on_main_thread_sync(mp_window main_window, mp_dispatch_proc proc, void* user);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Clipboard
|
||||
//--------------------------------------------------------------------
|
||||
MP_API void mp_clipboard_clear(void);
|
||||
|
||||
MP_API void mp_clipboard_set_string(str8 string);
|
||||
MP_API str8 mp_clipboard_get_string(mem_arena* arena);
|
||||
MP_API str8 mp_clipboard_copy_string(str8 backing);
|
||||
|
||||
MP_API bool mp_clipboard_has_tag(const char* tag);
|
||||
MP_API void mp_clipboard_set_data_for_tag(const char* tag, str8 data);
|
||||
MP_API str8 mp_clipboard_get_data_for_tag(mem_arena* arena, const char* tag);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// native open/save/alert windows
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
MP_API str8 mp_open_dialog(mem_arena* arena,
|
||||
const char* title,
|
||||
const char* defaultPath,
|
||||
int filterCount,
|
||||
const char** filters,
|
||||
bool directory);
|
||||
|
||||
MP_API str8 mp_save_dialog(mem_arena* arena,
|
||||
const char* title,
|
||||
const char* defaultPath,
|
||||
int filterCount,
|
||||
const char** filters);
|
||||
|
||||
MP_API int mp_alert_popup(const char* title,
|
||||
const char* message,
|
||||
u32 count,
|
||||
const char** options);
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// file system stuff... //TODO: move elsewhere
|
||||
//--------------------------------------------------------------------
|
||||
MP_API int mp_file_move(str8 from, str8 to);
|
||||
MP_API int mp_file_remove(str8 path);
|
||||
|
||||
MP_API int mp_directory_create(str8 path);
|
||||
|
||||
|
||||
#endif // !defined(PLATFORM_ORCA) || !(PLATFORM_ORCA)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif //__PLATFORM_APP_H_
|
|
@ -1,4 +1,4 @@
|
|||
#include"orca.h"
|
||||
|
||||
//This is used to pass raw events from the runtime
|
||||
ORCA_EXPORT mp_event _OrcaRawEvent;
|
||||
ORCA_EXPORT oc_event oc_rawEvent;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef __OSX_APP_H_
|
||||
#define __OSX_APP_H_
|
||||
|
||||
#include"mp_app.h"
|
||||
#include"app.h"
|
||||
#include"graphics/graphics.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
@ -26,19 +26,19 @@
|
|||
|
||||
#include<Carbon/Carbon.h>
|
||||
|
||||
typedef struct osx_window_data
|
||||
typedef struct oc_osx_window_data
|
||||
{
|
||||
NSWindow* nsWindow;
|
||||
NSView* nsView;
|
||||
NSObject* nsWindowDelegate;
|
||||
|
||||
} osx_window_data;
|
||||
} oc_osx_window_data;
|
||||
|
||||
#define MP_PLATFORM_WINDOW_DATA osx_window_data osx;
|
||||
#define OC_PLATFORM_WINDOW_DATA oc_osx_window_data osx;
|
||||
|
||||
const u32 MP_APP_MAX_VIEWS = 128;
|
||||
const u32 OC_APP_MAX_VIEWS = 128;
|
||||
|
||||
typedef struct osx_app_data
|
||||
typedef struct oc_osx_app_data
|
||||
{
|
||||
NSTimer* frameTimer;
|
||||
NSCursor* cursor;
|
||||
|
@ -47,9 +47,9 @@ typedef struct osx_app_data
|
|||
void* kbLayoutUnicodeData;
|
||||
id kbLayoutListener;
|
||||
|
||||
} osx_app_data;
|
||||
} oc_osx_app_data;
|
||||
|
||||
#define MP_PLATFORM_APP_DATA osx_app_data osx;
|
||||
#define OC_PLATFORM_APP_DATA oc_osx_app_data osx;
|
||||
|
||||
//-----------------------------------------------
|
||||
// Surface layer
|
||||
|
@ -76,11 +76,11 @@ typedef struct osx_app_data
|
|||
@end
|
||||
#endif
|
||||
|
||||
typedef struct mp_layer
|
||||
typedef struct oc_layer
|
||||
{
|
||||
CALayer* caLayer;
|
||||
CAContext* caContext;
|
||||
} mp_layer;
|
||||
} oc_layer;
|
||||
|
||||
|
||||
|
||||
|
|
1131
src/app/osx_app.m
1131
src/app/osx_app.m
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -10,45 +10,45 @@
|
|||
#ifndef __WIN32_APP_H_
|
||||
#define __WIN32_APP_H_
|
||||
|
||||
#include"mp_app.h"
|
||||
#include"app.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define UNICODE
|
||||
#include<windows.h>
|
||||
|
||||
|
||||
typedef struct win32_window_data
|
||||
typedef struct oc_win32_window_data
|
||||
{
|
||||
HWND hWnd;
|
||||
list_info layers;
|
||||
} win32_window_data;
|
||||
oc_list layers;
|
||||
} oc_win32_window_data;
|
||||
|
||||
typedef struct mp_window_data mp_window_data;
|
||||
typedef struct mp_layer
|
||||
typedef struct oc_window_data oc_window_data;
|
||||
typedef struct oc_layer
|
||||
{
|
||||
mp_window_data* parent;
|
||||
list_elt listElt;
|
||||
oc_window_data* parent;
|
||||
oc_list_elt listElt;
|
||||
HWND hWnd;
|
||||
} mp_layer;
|
||||
} oc_layer;
|
||||
|
||||
#define MP_PLATFORM_WINDOW_DATA win32_window_data win32;
|
||||
#define OC_PLATFORM_WINDOW_DATA oc_win32_window_data win32;
|
||||
|
||||
typedef struct win32_app_data
|
||||
typedef struct oc_win32_app_data
|
||||
{
|
||||
u32 savedConsoleCodePage;
|
||||
|
||||
int mouseCaptureMask;
|
||||
bool mouseTracked;
|
||||
vec2 lastMousePos;
|
||||
oc_vec2 lastMousePos;
|
||||
u32 wheelScrollLines;
|
||||
|
||||
} win32_app_data;
|
||||
} oc_win32_app_data;
|
||||
|
||||
#define MP_PLATFORM_APP_DATA win32_app_data win32;
|
||||
#define OC_PLATFORM_APP_DATA oc_win32_app_data win32;
|
||||
|
||||
enum MP_WM_USER
|
||||
enum OC_WM_USER
|
||||
{
|
||||
MP_WM_USER_DISPATCH_PROC = 0x0400, // WM_USER messages are defined from 0x400 to 0x7FFF
|
||||
OC_WM_USER_DISPATCH_PROC = 0x0400, // WM_USER messages are defined from 0x400 to 0x7FFF
|
||||
};
|
||||
|
||||
#endif __WIN32_APP_H_
|
||||
|
|
|
@ -10,47 +10,47 @@
|
|||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#include<EGL/egl.h>
|
||||
#include<EGL/eglext.h>
|
||||
#include"app/mp_app_internal.h"
|
||||
#include"app/app_internal.h"
|
||||
#include"graphics_surface.h"
|
||||
#include"gl_loader.h"
|
||||
|
||||
#if PLATFORM_MACOS
|
||||
#if OC_PLATFORM_MACOS
|
||||
//NOTE: EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE on osx defaults to CGL backend, which doesn't handle SwapInterval correctly
|
||||
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE
|
||||
#define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE
|
||||
|
||||
//NOTE: hardcode GLES versions for now
|
||||
//TODO: use version hints, once we have all api versions correctly categorized by glapi.py
|
||||
#define MG_GLES_VERSION_MAJOR 3
|
||||
#define MG_GLES_VERSION_MINOR 0
|
||||
#define mg_gl_load_gles mg_gl_load_gles31
|
||||
#define OC_GLES_VERSION_MAJOR 3
|
||||
#define OC_GLES_VERSION_MINOR 0
|
||||
#define oc_gl_load_gles oc_gl_load_gles31
|
||||
#else
|
||||
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
||||
#define MG_GLES_VERSION_MAJOR 3
|
||||
#define MG_GLES_VERSION_MINOR 1
|
||||
#define mg_gl_load_gles mg_gl_load_gles32
|
||||
#define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
||||
#define OC_GLES_VERSION_MAJOR 3
|
||||
#define OC_GLES_VERSION_MINOR 1
|
||||
#define oc_gl_load_gles oc_gl_load_gles32
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct mg_egl_surface
|
||||
typedef struct oc_egl_surface
|
||||
{
|
||||
mg_surface_data interface;
|
||||
oc_surface_data interface;
|
||||
|
||||
EGLDisplay eglDisplay;
|
||||
EGLConfig eglConfig;
|
||||
EGLContext eglContext;
|
||||
EGLSurface eglSurface;
|
||||
|
||||
mg_gl_api api;
|
||||
oc_gl_api api;
|
||||
|
||||
} mg_egl_surface;
|
||||
} oc_egl_surface;
|
||||
|
||||
void mg_egl_surface_destroy(mg_surface_data* interface)
|
||||
void oc_egl_surface_destroy(oc_surface_data* interface)
|
||||
{
|
||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
||||
oc_egl_surface* surface = (oc_egl_surface*)interface;
|
||||
|
||||
if(&surface->api == mg_gl_get_api())
|
||||
if(&surface->api == oc_gl_get_api())
|
||||
{
|
||||
mg_gl_deselect_api();
|
||||
oc_gl_deselect_api();
|
||||
}
|
||||
if(eglGetCurrentContext() == surface->eglContext)
|
||||
{
|
||||
|
@ -59,50 +59,50 @@ void mg_egl_surface_destroy(mg_surface_data* interface)
|
|||
eglDestroyContext(surface->eglDisplay, surface->eglContext);
|
||||
eglDestroySurface(surface->eglDisplay, surface->eglSurface);
|
||||
|
||||
mg_surface_cleanup((mg_surface_data*)surface);
|
||||
oc_surface_cleanup((oc_surface_data*)surface);
|
||||
free(surface);
|
||||
}
|
||||
|
||||
void mg_egl_surface_prepare(mg_surface_data* interface)
|
||||
void oc_egl_surface_prepare(oc_surface_data* interface)
|
||||
{
|
||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
||||
oc_egl_surface* surface = (oc_egl_surface*)interface;
|
||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
||||
mg_gl_select_api(&surface->api);
|
||||
oc_gl_select_api(&surface->api);
|
||||
}
|
||||
|
||||
void mg_egl_surface_present(mg_surface_data* interface)
|
||||
void oc_egl_surface_present(oc_surface_data* interface)
|
||||
{
|
||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
||||
oc_egl_surface* surface = (oc_egl_surface*)interface;
|
||||
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
|
||||
}
|
||||
|
||||
void mg_egl_surface_deselect(mg_surface_data* interface)
|
||||
void oc_egl_surface_deselect(oc_surface_data* interface)
|
||||
{
|
||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
||||
oc_egl_surface* surface = (oc_egl_surface*)interface;
|
||||
eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
mg_gl_deselect_api();
|
||||
oc_gl_deselect_api();
|
||||
}
|
||||
|
||||
void mg_egl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
void oc_egl_surface_swap_interval(oc_surface_data* interface, int swap)
|
||||
{
|
||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
||||
oc_egl_surface* surface = (oc_egl_surface*)interface;
|
||||
eglSwapInterval(surface->eglDisplay, swap);
|
||||
}
|
||||
|
||||
void mg_egl_surface_init(mg_egl_surface* surface)
|
||||
void oc_egl_surface_init(oc_egl_surface* surface)
|
||||
{
|
||||
void* nativeLayer = surface->interface.nativeLayer((mg_surface_data*)surface);
|
||||
void* nativeLayer = surface->interface.nativeLayer((oc_surface_data*)surface);
|
||||
|
||||
surface->interface.api = MG_GLES;
|
||||
surface->interface.api = OC_GLES;
|
||||
|
||||
surface->interface.destroy = mg_egl_surface_destroy;
|
||||
surface->interface.prepare = mg_egl_surface_prepare;
|
||||
surface->interface.present = mg_egl_surface_present;
|
||||
surface->interface.deselect = mg_egl_surface_deselect;
|
||||
surface->interface.swapInterval = mg_egl_surface_swap_interval;
|
||||
surface->interface.destroy = oc_egl_surface_destroy;
|
||||
surface->interface.prepare = oc_egl_surface_prepare;
|
||||
surface->interface.present = oc_egl_surface_present;
|
||||
surface->interface.deselect = oc_egl_surface_deselect;
|
||||
surface->interface.swapInterval = oc_egl_surface_swap_interval;
|
||||
|
||||
EGLAttrib displayAttribs[] = {
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE, MG_EGL_PLATFORM_ANGLE_TYPE,
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE, OC_EGL_PLATFORM_ANGLE_TYPE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
|
||||
EGL_NONE};
|
||||
|
||||
|
@ -133,8 +133,8 @@ void mg_egl_surface_init(mg_egl_surface* surface)
|
|||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
EGLint contextAttributes[] = {
|
||||
EGL_CONTEXT_MAJOR_VERSION_KHR, MG_GLES_VERSION_MAJOR,
|
||||
EGL_CONTEXT_MINOR_VERSION_KHR, MG_GLES_VERSION_MINOR,
|
||||
EGL_CONTEXT_MAJOR_VERSION_KHR, OC_GLES_VERSION_MAJOR,
|
||||
EGL_CONTEXT_MINOR_VERSION_KHR, OC_GLES_VERSION_MINOR,
|
||||
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE,
|
||||
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE,
|
||||
EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE,
|
||||
|
@ -143,41 +143,41 @@ void mg_egl_surface_init(mg_egl_surface* surface)
|
|||
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
|
||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
||||
|
||||
mg_gl_load_gles(&surface->api, (mg_gl_load_proc)eglGetProcAddress);
|
||||
oc_gl_load_gles(&surface->api, (oc_gl_load_proc)eglGetProcAddress);
|
||||
|
||||
eglSwapInterval(surface->eglDisplay, 1);
|
||||
}
|
||||
|
||||
mg_surface_data* mg_egl_surface_create_remote(u32 width, u32 height)
|
||||
oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height)
|
||||
{
|
||||
mg_egl_surface* surface = 0;
|
||||
oc_egl_surface* surface = 0;
|
||||
|
||||
surface = malloc_type(mg_egl_surface);
|
||||
surface = oc_malloc_type(oc_egl_surface);
|
||||
if(surface)
|
||||
{
|
||||
memset(surface, 0, sizeof(mg_egl_surface));
|
||||
memset(surface, 0, sizeof(oc_egl_surface));
|
||||
|
||||
mg_surface_init_remote((mg_surface_data*)surface, width, height);
|
||||
mg_egl_surface_init(surface);
|
||||
oc_surface_init_remote((oc_surface_data*)surface, width, height);
|
||||
oc_egl_surface_init(surface);
|
||||
}
|
||||
|
||||
return((mg_surface_data*)surface);
|
||||
return((oc_surface_data*)surface);
|
||||
}
|
||||
|
||||
mg_surface_data* mg_egl_surface_create_for_window(mp_window window)
|
||||
oc_surface_data* oc_egl_surface_create_for_window(oc_window window)
|
||||
{
|
||||
mg_egl_surface* surface = 0;
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
oc_egl_surface* surface = 0;
|
||||
oc_window_data* windowData = oc_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
surface = malloc_type(mg_egl_surface);
|
||||
surface = oc_malloc_type(oc_egl_surface);
|
||||
if(surface)
|
||||
{
|
||||
memset(surface, 0, sizeof(mg_egl_surface));
|
||||
memset(surface, 0, sizeof(oc_egl_surface));
|
||||
|
||||
mg_surface_init_for_window((mg_surface_data*)surface, windowData);
|
||||
mg_egl_surface_init(surface);
|
||||
oc_surface_init_for_window((oc_surface_data*)surface, windowData);
|
||||
oc_egl_surface_init(surface);
|
||||
}
|
||||
}
|
||||
return((mg_surface_data*)surface);
|
||||
return((oc_surface_data*)surface);
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#define __EGL_SURFACE_H_
|
||||
|
||||
#include"graphics_surface.h"
|
||||
#include"app/mp_app.h"
|
||||
#include"app/app.h"
|
||||
|
||||
mg_surface_data* mg_egl_surface_create_for_window(mp_window window);
|
||||
mg_surface_data* mg_egl_surface_create_remote(u32 width, u32 height);
|
||||
oc_surface_data* oc_egl_surface_create_for_window(oc_window window);
|
||||
oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height);
|
||||
|
||||
#endif // __EGL_SURFACE_H_
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
18900
src/graphics/gl_loader.c
18900
src/graphics/gl_loader.c
File diff suppressed because it is too large
Load Diff
|
@ -1,23 +1,23 @@
|
|||
/********************************************************
|
||||
*
|
||||
* @file: gl_loader.h
|
||||
* @note: auto-generated by glapi.py from gl.xml
|
||||
* @date: 11/082023
|
||||
*
|
||||
*********************************************************/
|
||||
#ifndef __GL_LOADER_H__
|
||||
#define __GL_LOADER_H__
|
||||
|
||||
#include"gl_api.h"
|
||||
|
||||
typedef void*(*mg_gl_load_proc)(const char* name);
|
||||
|
||||
void mg_gl_load_gl41(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gl43(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gl44(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gles30(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
|
||||
void mg_gl_select_api(mg_gl_api* api);
|
||||
|
||||
#endif // __GL_LOADER_H__
|
||||
/********************************************************
|
||||
*
|
||||
* @file: gl_loader.h
|
||||
* @note: auto-generated by glapi.py from gl.xml
|
||||
* @date: 15/082023
|
||||
*
|
||||
*********************************************************/
|
||||
#ifndef __GL_LOADER_H__
|
||||
#define __GL_LOADER_H__
|
||||
|
||||
#include"gl_api.h"
|
||||
|
||||
typedef void*(*oc_gl_load_proc)(const char* name);
|
||||
|
||||
void oc_gl_load_gl41(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||
void oc_gl_load_gl43(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||
void oc_gl_load_gl44(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||
void oc_gl_load_gles30(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||
void oc_gl_load_gles31(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||
|
||||
void oc_gl_select_api(oc_gl_api* api);
|
||||
|
||||
#endif // __GL_LOADER_H__
|
||||
|
|
|
@ -6,12 +6,12 @@ layout(std430) buffer;
|
|||
|
||||
layout(binding = 0) restrict readonly buffer pathQueueBufferSSBO
|
||||
{
|
||||
mg_gl_path_queue elements[];
|
||||
oc_gl_path_queue elements[];
|
||||
} pathQueueBuffer;
|
||||
|
||||
layout(binding = 1) restrict buffer tileQueueBufferSSBO
|
||||
{
|
||||
mg_gl_tile_queue elements[];
|
||||
oc_gl_tile_queue elements[];
|
||||
} tileQueueBuffer;
|
||||
|
||||
layout(location = 0) uniform int pathQueueBufferStart;
|
||||
|
@ -30,7 +30,7 @@ void main()
|
|||
barrier();
|
||||
|
||||
int rowIndex = 0;
|
||||
mg_gl_path_queue pathQueue = pathQueueBuffer.elements[pathQueueBufferStart + pathIndex];
|
||||
oc_gl_path_queue pathQueue = pathQueueBuffer.elements[pathQueueBufferStart + pathIndex];
|
||||
int tileQueueBase = pathQueue.tileQueues;
|
||||
int rowSize = pathQueue.area.z;
|
||||
int rowCount = pathQueue.area.w;
|
||||
|
|
|
@ -11,7 +11,7 @@ layout(binding = 0) coherent restrict readonly buffer screenTilesCountBufferSSBO
|
|||
|
||||
layout(binding = 1) coherent restrict writeonly buffer dispatchBufferSSBO
|
||||
{
|
||||
mg_gl_dispatch_indirect_command elements[];
|
||||
oc_gl_dispatch_indirect_command elements[];
|
||||
} dispatchBuffer;
|
||||
|
||||
|
||||
|
|
|
@ -2,32 +2,32 @@
|
|||
layout(std430) buffer;
|
||||
|
||||
// command
|
||||
#define MG_GL_FILL 0
|
||||
#define MG_GL_STROKE 1
|
||||
#define OC_GL_FILL 0
|
||||
#define OC_GL_STROKE 1
|
||||
|
||||
// element kind
|
||||
#define MG_GL_LINE 1
|
||||
#define MG_GL_QUADRATIC 2
|
||||
#define MG_GL_CUBIC 3
|
||||
#define OC_GL_LINE 1
|
||||
#define OC_GL_QUADRATIC 2
|
||||
#define OC_GL_CUBIC 3
|
||||
|
||||
// curve config
|
||||
#define MG_GL_BL 1 /* curve on bottom left */
|
||||
#define MG_GL_BR 2 /* curve on bottom right */
|
||||
#define MG_GL_TL 3 /* curve on top left */
|
||||
#define MG_GL_TR 4 /* curve on top right */
|
||||
#define OC_GL_BL 1 /* curve on bottom left */
|
||||
#define OC_GL_BR 2 /* curve on bottom right */
|
||||
#define OC_GL_TL 3 /* curve on top left */
|
||||
#define OC_GL_TR 4 /* curve on top right */
|
||||
|
||||
// Operations
|
||||
#define MG_GL_OP_FILL 0
|
||||
#define MG_GL_OP_CLIP_FILL 1
|
||||
#define MG_GL_OP_START 2
|
||||
#define MG_GL_OP_END 3
|
||||
#define MG_GL_OP_SEGMENT 4
|
||||
#define OC_GL_OP_FILL 0
|
||||
#define OC_GL_OP_CLIP_FILL 1
|
||||
#define OC_GL_OP_START 2
|
||||
#define OC_GL_OP_END 3
|
||||
#define OC_GL_OP_SEGMENT 4
|
||||
|
||||
// MSAA
|
||||
#define MG_GL_MAX_SAMPLE_COUNT 8
|
||||
#define MG_GL_MAX_SRC_SAMPLE_COUNT 4
|
||||
#define OC_GL_MAX_SAMPLE_COUNT 8
|
||||
#define OC_GL_MAX_SRC_SAMPLE_COUNT 4
|
||||
|
||||
struct mg_gl_path
|
||||
struct oc_gl_path
|
||||
{
|
||||
mat3 uvTransform;
|
||||
vec4 color;
|
||||
|
@ -37,14 +37,14 @@ struct mg_gl_path
|
|||
int textureID;
|
||||
};
|
||||
|
||||
struct mg_gl_path_elt
|
||||
struct oc_gl_path_elt
|
||||
{
|
||||
vec2 p[4];
|
||||
int pathIndex;
|
||||
int kind;
|
||||
};
|
||||
|
||||
struct mg_gl_segment
|
||||
struct oc_gl_segment
|
||||
{
|
||||
int kind;
|
||||
int pathIndex;
|
||||
|
@ -56,13 +56,13 @@ struct mg_gl_segment
|
|||
float sign;
|
||||
};
|
||||
|
||||
struct mg_gl_path_queue
|
||||
struct oc_gl_path_queue
|
||||
{
|
||||
ivec4 area;
|
||||
int tileQueues;
|
||||
};
|
||||
|
||||
struct mg_gl_tile_op
|
||||
struct oc_gl_tile_op
|
||||
{
|
||||
int kind;
|
||||
int next;
|
||||
|
@ -70,20 +70,20 @@ struct mg_gl_tile_op
|
|||
int windingOffsetOrCrossRight;
|
||||
};
|
||||
|
||||
struct mg_gl_tile_queue
|
||||
struct oc_gl_tile_queue
|
||||
{
|
||||
int windingOffset;
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
struct mg_gl_screen_tile
|
||||
struct oc_gl_screen_tile
|
||||
{
|
||||
uvec2 tileCoord;
|
||||
int first;
|
||||
};
|
||||
|
||||
struct mg_gl_dispatch_indirect_command
|
||||
struct oc_gl_dispatch_indirect_command
|
||||
{
|
||||
uint num_groups_x;
|
||||
uint num_groups_y;
|
||||
|
@ -95,7 +95,7 @@ float ccw(vec2 a, vec2 b, vec2 c)
|
|||
return((b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x));
|
||||
}
|
||||
|
||||
int side_of_segment(vec2 p, mg_gl_segment seg)
|
||||
int side_of_segment(vec2 p, oc_gl_segment seg)
|
||||
{
|
||||
int side = 0;
|
||||
if(p.y > seg.box.w || p.y <= seg.box.y)
|
||||
|
@ -104,11 +104,11 @@ int side_of_segment(vec2 p, mg_gl_segment seg)
|
|||
{
|
||||
if(p.y > seg.box.w)
|
||||
{
|
||||
side = (seg.config == MG_GL_TL || seg.config == MG_GL_BR)? -1 : 1;
|
||||
side = (seg.config == OC_GL_TL || seg.config == OC_GL_BR)? -1 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
side = (seg.config == MG_GL_TL || seg.config == MG_GL_BR)? 1 : -1;
|
||||
side = (seg.config == OC_GL_TL || seg.config == OC_GL_BR)? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,22 +125,22 @@ int side_of_segment(vec2 p, mg_gl_segment seg)
|
|||
vec2 a, b, c;
|
||||
switch(seg.config)
|
||||
{
|
||||
case MG_GL_TL:
|
||||
case OC_GL_TL:
|
||||
a = seg.box.xy;
|
||||
b = seg.box.zw;
|
||||
break;
|
||||
|
||||
case MG_GL_BR:
|
||||
case OC_GL_BR:
|
||||
a = seg.box.zw;
|
||||
b = seg.box.xy;
|
||||
break;
|
||||
|
||||
case MG_GL_TR:
|
||||
case OC_GL_TR:
|
||||
a = seg.box.xw;
|
||||
b = seg.box.zy;
|
||||
break;
|
||||
|
||||
case MG_GL_BL:
|
||||
case OC_GL_BL:
|
||||
a = seg.box.zy;
|
||||
b = seg.box.xw;
|
||||
break;
|
||||
|
@ -150,30 +150,30 @@ int side_of_segment(vec2 p, mg_gl_segment seg)
|
|||
if(ccw(a, b, p) < 0)
|
||||
{
|
||||
// other side of the diagonal
|
||||
side = (seg.config == MG_GL_BR || seg.config == MG_GL_TR) ? -1 : 1;
|
||||
side = (seg.config == OC_GL_BR || seg.config == OC_GL_TR) ? -1 : 1;
|
||||
}
|
||||
else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0)
|
||||
{
|
||||
// same side of the diagonal, but outside curve hull
|
||||
side = (seg.config == MG_GL_BL || seg.config == MG_GL_TL) ? -1 : 1;
|
||||
side = (seg.config == OC_GL_BL || seg.config == OC_GL_TL) ? -1 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// inside curve hull
|
||||
switch(seg.kind)
|
||||
{
|
||||
case MG_GL_LINE:
|
||||
case OC_GL_LINE:
|
||||
side = 1;
|
||||
break;
|
||||
|
||||
case MG_GL_QUADRATIC:
|
||||
case OC_GL_QUADRATIC:
|
||||
{
|
||||
vec3 ph = {p.x, p.y, 1};
|
||||
vec3 klm = seg.implicitMatrix * ph;
|
||||
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
|
||||
} break;
|
||||
|
||||
case MG_GL_CUBIC:
|
||||
case OC_GL_CUBIC:
|
||||
{
|
||||
vec3 ph = {p.x, p.y, 1};
|
||||
vec3 klm = seg.implicitMatrix * ph;
|
||||
|
|
|
@ -6,17 +6,17 @@ layout(std430) buffer;
|
|||
|
||||
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
||||
{
|
||||
mg_gl_path elements[];
|
||||
oc_gl_path elements[];
|
||||
} pathBuffer;
|
||||
|
||||
layout(binding = 1) restrict readonly buffer pathQueueBufferSSBO
|
||||
{
|
||||
mg_gl_path_queue elements[];
|
||||
oc_gl_path_queue elements[];
|
||||
} pathQueueBuffer;
|
||||
|
||||
layout(binding = 2) restrict readonly buffer tileQueueBufferSSBO
|
||||
{
|
||||
mg_gl_tile_queue elements[];
|
||||
oc_gl_tile_queue elements[];
|
||||
} tileQueueBuffer;
|
||||
|
||||
layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO
|
||||
|
@ -26,12 +26,12 @@ layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO
|
|||
|
||||
layout(binding = 4) restrict buffer tileOpBufferSSBO
|
||||
{
|
||||
mg_gl_tile_op elements[];
|
||||
oc_gl_tile_op elements[];
|
||||
} tileOpBuffer;
|
||||
|
||||
layout(binding = 5) restrict writeonly buffer screenTilesBufferSSBO
|
||||
{
|
||||
mg_gl_screen_tile elements[];
|
||||
oc_gl_screen_tile elements[];
|
||||
} screenTilesBuffer;
|
||||
|
||||
layout(binding = 6) coherent restrict buffer screenTilesCountBufferSSBO
|
||||
|
@ -54,7 +54,7 @@ void main()
|
|||
|
||||
for(int pathIndex = 0; pathIndex < pathCount; pathIndex++)
|
||||
{
|
||||
mg_gl_path_queue pathQueue = pathQueueBuffer.elements[pathIndex];
|
||||
oc_gl_path_queue pathQueue = pathQueueBuffer.elements[pathIndex];
|
||||
ivec2 pathTileCoord = tileCoord - pathQueue.area.xy;
|
||||
|
||||
vec4 pathBox = pathBuffer.elements[pathBufferStart + pathIndex].box;
|
||||
|
@ -77,7 +77,7 @@ void main()
|
|||
}
|
||||
|
||||
int pathTileIndex = pathQueue.tileQueues + pathTileCoord.y * pathQueue.area.z + pathTileCoord.x;
|
||||
mg_gl_tile_queue tileQueue = tileQueueBuffer.elements[pathTileIndex];
|
||||
oc_gl_tile_queue tileQueue = tileQueueBuffer.elements[pathTileIndex];
|
||||
|
||||
int windingOffset = tileQueue.windingOffset;
|
||||
int firstOpIndex = tileQueue.first;
|
||||
|
@ -107,7 +107,7 @@ void main()
|
|||
return;
|
||||
}
|
||||
|
||||
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_CLIP_FILL;
|
||||
tileOpBuffer.elements[pathOpIndex].kind = OC_GL_OP_CLIP_FILL;
|
||||
tileOpBuffer.elements[pathOpIndex].next = -1;
|
||||
tileOpBuffer.elements[pathOpIndex].index = pathIndex;
|
||||
tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||
|
@ -126,7 +126,7 @@ void main()
|
|||
&& tileBox.y >= clip.y
|
||||
&& tileBox.w < clip.w)
|
||||
{
|
||||
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_FILL;
|
||||
tileOpBuffer.elements[pathOpIndex].kind = OC_GL_OP_FILL;
|
||||
|
||||
if( pathBuffer.elements[pathBufferStart + pathIndex].color.a == 1
|
||||
&& pathBuffer.elements[pathBufferStart + pathIndex].textureID < 0)
|
||||
|
@ -147,7 +147,7 @@ void main()
|
|||
return;
|
||||
}
|
||||
|
||||
tileOpBuffer.elements[startOpIndex].kind = MG_GL_OP_START;
|
||||
tileOpBuffer.elements[startOpIndex].kind = OC_GL_OP_START;
|
||||
tileOpBuffer.elements[startOpIndex].next = -1;
|
||||
tileOpBuffer.elements[startOpIndex].index = pathIndex;
|
||||
tileOpBuffer.elements[startOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||
|
@ -173,7 +173,7 @@ void main()
|
|||
return;
|
||||
}
|
||||
|
||||
tileOpBuffer.elements[endOpIndex].kind = MG_GL_OP_END;
|
||||
tileOpBuffer.elements[endOpIndex].kind = OC_GL_OP_END;
|
||||
tileOpBuffer.elements[endOpIndex].next = -1;
|
||||
tileOpBuffer.elements[endOpIndex].index = pathIndex;
|
||||
tileOpBuffer.elements[endOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||
|
|
|
@ -6,12 +6,12 @@ layout(std430) buffer;
|
|||
|
||||
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
||||
{
|
||||
mg_gl_path elements[];
|
||||
oc_gl_path elements[];
|
||||
} pathBuffer;
|
||||
|
||||
layout(binding = 1) restrict writeonly buffer pathQueueBufferSSBO
|
||||
{
|
||||
mg_gl_path_queue elements[];
|
||||
oc_gl_path_queue elements[];
|
||||
} pathQueueBuffer;
|
||||
|
||||
layout(binding = 2) coherent restrict buffer tileQueueCountBufferSSBO
|
||||
|
@ -21,7 +21,7 @@ layout(binding = 2) coherent restrict buffer tileQueueCountBufferSSBO
|
|||
|
||||
layout(binding = 3) restrict writeonly buffer tileQueueBufferSSBO
|
||||
{
|
||||
mg_gl_tile_queue elements[];
|
||||
oc_gl_tile_queue elements[];
|
||||
} tileQueueBuffer;
|
||||
|
||||
layout(location = 0) uniform int tileSize;
|
||||
|
@ -32,7 +32,7 @@ layout(location = 3) uniform int pathQueueBufferStart;
|
|||
void main()
|
||||
{
|
||||
uint pathIndex = gl_WorkGroupID.x;
|
||||
const mg_gl_path path = pathBuffer.elements[pathIndex + pathBufferStart];
|
||||
const oc_gl_path path = pathBuffer.elements[pathIndex + pathBufferStart];
|
||||
|
||||
//NOTE: we don't clip on the right, since we need those tiles to accurately compute
|
||||
// the prefix sum of winding increments in the backprop pass.
|
||||
|
|
|
@ -6,22 +6,22 @@ layout(std430) buffer;
|
|||
|
||||
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
||||
{
|
||||
mg_gl_path elements[];
|
||||
oc_gl_path elements[];
|
||||
} pathBuffer;
|
||||
|
||||
layout(binding = 1) restrict readonly buffer segmentBufferSSBO
|
||||
{
|
||||
mg_gl_segment elements[];
|
||||
oc_gl_segment elements[];
|
||||
} segmentBuffer;
|
||||
|
||||
layout(binding = 2) restrict readonly buffer tileOpBufferSSBO
|
||||
{
|
||||
mg_gl_tile_op elements[];
|
||||
oc_gl_tile_op elements[];
|
||||
} tileOpBuffer;
|
||||
|
||||
layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO
|
||||
{
|
||||
mg_gl_screen_tile elements[];
|
||||
oc_gl_screen_tile elements[];
|
||||
} screenTilesBuffer;
|
||||
|
||||
layout(binding = 4) restrict readonly buffer screenTilesCountBufferSSBO
|
||||
|
@ -67,7 +67,7 @@ void main()
|
|||
return;
|
||||
}
|
||||
*/
|
||||
vec2 sampleCoords[MG_GL_MAX_SAMPLE_COUNT] = {
|
||||
vec2 sampleCoords[OC_GL_MAX_SAMPLE_COUNT] = {
|
||||
centerCoord + vec2(1, 3)/16,
|
||||
centerCoord + vec2(-1, -3)/16,
|
||||
centerCoord + vec2(5, -1)/16,
|
||||
|
@ -87,14 +87,14 @@ void main()
|
|||
|
||||
const int srcSampleCount = 2;
|
||||
|
||||
vec2 imgSampleCoords[MG_GL_MAX_SRC_SAMPLE_COUNT] = {
|
||||
vec2 imgSampleCoords[OC_GL_MAX_SRC_SAMPLE_COUNT] = {
|
||||
centerCoord + vec2(-0.25, 0.25),
|
||||
centerCoord + vec2(+0.25, +0.25),
|
||||
centerCoord + vec2(+0.25, -0.25),
|
||||
centerCoord + vec2(-0.25, +0.25)};
|
||||
|
||||
vec4 color = vec4(0);
|
||||
int winding[MG_GL_MAX_SAMPLE_COUNT];
|
||||
int winding[OC_GL_MAX_SAMPLE_COUNT];
|
||||
|
||||
for(int i=0; i<sampleCount; i++)
|
||||
{
|
||||
|
@ -106,19 +106,19 @@ void main()
|
|||
|
||||
while(opIndex >= 0)
|
||||
{
|
||||
mg_gl_tile_op op = tileOpBuffer.elements[opIndex];
|
||||
oc_gl_tile_op op = tileOpBuffer.elements[opIndex];
|
||||
|
||||
if(op.kind == MG_GL_OP_START)
|
||||
if(op.kind == OC_GL_OP_START)
|
||||
{
|
||||
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++)
|
||||
{
|
||||
winding[sampleIndex] = op.windingOffsetOrCrossRight;
|
||||
}
|
||||
}
|
||||
else if(op.kind == MG_GL_OP_SEGMENT)
|
||||
else if(op.kind == OC_GL_OP_SEGMENT)
|
||||
{
|
||||
int segIndex = op.index;
|
||||
mg_gl_segment seg = segmentBuffer.elements[segIndex];
|
||||
oc_gl_segment seg = segmentBuffer.elements[segIndex];
|
||||
|
||||
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++)
|
||||
{
|
||||
|
@ -133,12 +133,12 @@ void main()
|
|||
|
||||
if(op.windingOffsetOrCrossRight != 0)
|
||||
{
|
||||
if( (seg.config == MG_GL_BR || seg.config == MG_GL_TL)
|
||||
if( (seg.config == OC_GL_BR || seg.config == OC_GL_TL)
|
||||
&&(sampleCoord.y > seg.box.w))
|
||||
{
|
||||
winding[sampleIndex] += seg.windingIncrement;
|
||||
}
|
||||
else if( (seg.config == MG_GL_BL || seg.config == MG_GL_TR)
|
||||
else if( (seg.config == OC_GL_BL || seg.config == OC_GL_TR)
|
||||
&&(sampleCoord.y > seg.box.y))
|
||||
{
|
||||
winding[sampleIndex] -= seg.windingIncrement;
|
||||
|
@ -202,7 +202,7 @@ void main()
|
|||
nextColor *= texColor;
|
||||
}
|
||||
|
||||
if(op.kind == MG_GL_OP_FILL)
|
||||
if(op.kind == OC_GL_OP_FILL)
|
||||
{
|
||||
color = color*(1-nextColor.a) + nextColor;
|
||||
}
|
||||
|
@ -220,10 +220,10 @@ void main()
|
|||
&& sampleCoord.y >= clip.y
|
||||
&& sampleCoord.y < clip.w)
|
||||
{
|
||||
bool filled = op.kind == MG_GL_OP_CLIP_FILL
|
||||
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == MG_GL_FILL
|
||||
bool filled = op.kind == OC_GL_OP_CLIP_FILL
|
||||
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_FILL
|
||||
&& ((winding[sampleIndex] & 1) != 0))
|
||||
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == MG_GL_STROKE
|
||||
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_STROKE
|
||||
&& (winding[sampleIndex] != 0));
|
||||
if(filled)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@ layout(std430) buffer;
|
|||
|
||||
layout(binding = 0) restrict readonly buffer elementBufferSSBO
|
||||
{
|
||||
mg_gl_path_elt elements[];
|
||||
oc_gl_path_elt elements[];
|
||||
} elementBuffer;
|
||||
|
||||
layout(binding = 1) coherent restrict buffer segmentCountBufferSSBO
|
||||
|
@ -16,17 +16,17 @@ layout(binding = 1) coherent restrict buffer segmentCountBufferSSBO
|
|||
|
||||
layout(binding = 2) restrict buffer segmentBufferSSBO
|
||||
{
|
||||
mg_gl_segment elements[];
|
||||
oc_gl_segment elements[];
|
||||
} segmentBuffer;
|
||||
|
||||
layout(binding = 3) restrict buffer pathQueueBufferSSBO
|
||||
{
|
||||
mg_gl_path_queue elements[];
|
||||
oc_gl_path_queue elements[];
|
||||
} pathQueueBuffer;
|
||||
|
||||
layout(binding = 4) coherent restrict buffer tileQueueBufferSSBO
|
||||
{
|
||||
mg_gl_tile_queue elements[];
|
||||
oc_gl_tile_queue elements[];
|
||||
} tileQueueBuffer;
|
||||
|
||||
layout(binding = 5) coherent restrict buffer tileOpCountBufferSSBO
|
||||
|
@ -36,7 +36,7 @@ layout(binding = 5) coherent restrict buffer tileOpCountBufferSSBO
|
|||
|
||||
layout(binding = 6) restrict buffer tileOpBufferSSBO
|
||||
{
|
||||
mg_gl_tile_op elements[];
|
||||
oc_gl_tile_op elements[];
|
||||
} tileOpBuffer;
|
||||
|
||||
layout(location = 0) uniform float scale;
|
||||
|
@ -46,8 +46,8 @@ layout(location = 2) uniform int elementBufferStart;
|
|||
void bin_to_tiles(int segIndex)
|
||||
{
|
||||
//NOTE: add segment index to the queues of tiles it overlaps with
|
||||
const mg_gl_segment seg = segmentBuffer.elements[segIndex];
|
||||
const mg_gl_path_queue pathQueue = pathQueueBuffer.elements[seg.pathIndex];
|
||||
const oc_gl_segment seg = segmentBuffer.elements[segIndex];
|
||||
const oc_gl_path_queue pathQueue = pathQueueBuffer.elements[seg.pathIndex];
|
||||
|
||||
ivec4 pathArea = pathQueue.area;
|
||||
ivec4 coveredTiles = ivec4(seg.box)/int(tileSize);
|
||||
|
@ -81,7 +81,7 @@ void bin_to_tiles(int segIndex)
|
|||
bool crossB = (sbl*sbr < 0);
|
||||
|
||||
vec2 s0, s1;
|
||||
if(seg.config == MG_GL_TL||seg.config == MG_GL_BR)
|
||||
if(seg.config == OC_GL_TL||seg.config == OC_GL_BR)
|
||||
{
|
||||
s0 = seg.box.xy;
|
||||
s1 = seg.box.zw;
|
||||
|
@ -107,7 +107,7 @@ void bin_to_tiles(int segIndex)
|
|||
|
||||
if(tileOpIndex < tileOpBuffer.elements.length())
|
||||
{
|
||||
tileOpBuffer.elements[tileOpIndex].kind = MG_GL_OP_SEGMENT;
|
||||
tileOpBuffer.elements[tileOpIndex].kind = OC_GL_OP_SEGMENT;
|
||||
tileOpBuffer.elements[tileOpIndex].index = segIndex;
|
||||
tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 0;
|
||||
tileOpBuffer.elements[tileOpIndex].next = -1;
|
||||
|
@ -148,19 +148,19 @@ int push_segment(in vec2 p[4], int kind, int pathIndex)
|
|||
|
||||
switch(kind)
|
||||
{
|
||||
case MG_GL_LINE:
|
||||
case OC_GL_LINE:
|
||||
s = p[0];
|
||||
c = p[0];
|
||||
e = p[1];
|
||||
break;
|
||||
|
||||
case MG_GL_QUADRATIC:
|
||||
case OC_GL_QUADRATIC:
|
||||
s = p[0];
|
||||
c = p[1];
|
||||
e = p[2];
|
||||
break;
|
||||
|
||||
case MG_GL_CUBIC:
|
||||
case OC_GL_CUBIC:
|
||||
{
|
||||
s = p[0];
|
||||
float sqrNorm0 = dot(p[1]-p[0], p[1]-p[0]);
|
||||
|
@ -197,32 +197,32 @@ int push_segment(in vec2 p[4], int kind, int pathIndex)
|
|||
|
||||
if(goingUp == goingRight)
|
||||
{
|
||||
if(kind == MG_GL_LINE)
|
||||
if(kind == OC_GL_LINE)
|
||||
{
|
||||
segmentBuffer.elements[segIndex].config = MG_GL_BR;
|
||||
segmentBuffer.elements[segIndex].config = OC_GL_BR;
|
||||
}
|
||||
else if(dy > alpha*dx)
|
||||
{
|
||||
segmentBuffer.elements[segIndex].config = MG_GL_TL;
|
||||
segmentBuffer.elements[segIndex].config = OC_GL_TL;
|
||||
}
|
||||
else
|
||||
{
|
||||
segmentBuffer.elements[segIndex].config = MG_GL_BR;
|
||||
segmentBuffer.elements[segIndex].config = OC_GL_BR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(kind == MG_GL_LINE)
|
||||
if(kind == OC_GL_LINE)
|
||||
{
|
||||
segmentBuffer.elements[segIndex].config = MG_GL_TR;
|
||||
segmentBuffer.elements[segIndex].config = OC_GL_TR;
|
||||
}
|
||||
else if(dy < ofs - alpha*dx)
|
||||
{
|
||||
segmentBuffer.elements[segIndex].config = MG_GL_BL;
|
||||
segmentBuffer.elements[segIndex].config = OC_GL_BL;
|
||||
}
|
||||
else
|
||||
{
|
||||
segmentBuffer.elements[segIndex].config = MG_GL_TR;
|
||||
segmentBuffer.elements[segIndex].config = OC_GL_TR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ int push_segment(in vec2 p[4], int kind, int pathIndex)
|
|||
|
||||
void line_setup(vec2 p[4], int pathIndex)
|
||||
{
|
||||
int segIndex = push_segment(p, MG_GL_LINE, pathIndex);
|
||||
int segIndex = push_segment(p, OC_GL_LINE, pathIndex);
|
||||
if(segIndex < segmentBuffer.elements.length())
|
||||
{
|
||||
segmentBuffer.elements[segIndex].hullVertex = p[0];
|
||||
|
@ -304,7 +304,7 @@ mat3 barycentric_matrix(vec2 v0, vec2 v1, vec2 v2)
|
|||
|
||||
void quadratic_emit(vec2 p[4], int pathIndex)
|
||||
{
|
||||
int segIndex = push_segment(p, MG_GL_QUADRATIC, pathIndex);
|
||||
int segIndex = push_segment(p, OC_GL_QUADRATIC, pathIndex);
|
||||
|
||||
if(segIndex < segmentBuffer.elements.length())
|
||||
{
|
||||
|
@ -318,8 +318,8 @@ void quadratic_emit(vec2 p[4], int pathIndex)
|
|||
float e = p[1].x - p[0].x;
|
||||
float f = p[0].x*p[1].y - p[1].x*p[0].y;
|
||||
|
||||
float flip = ( segmentBuffer.elements[segIndex].config == MG_GL_TL
|
||||
|| segmentBuffer.elements[segIndex].config == MG_GL_BL)? -1 : 1;
|
||||
float flip = ( segmentBuffer.elements[segIndex].config == OC_GL_TL
|
||||
|| segmentBuffer.elements[segIndex].config == OC_GL_BL)? -1 : 1;
|
||||
|
||||
float g = flip*(p[2].x*(p[0].y - p[1].y) + p[0].x*(p[1].y - p[2].y) + p[1].x*(p[2].y - p[0].y));
|
||||
|
||||
|
@ -663,7 +663,7 @@ vec2 select_hull_vertex(vec2 p0, vec2 p1, vec2 p2, vec2 p3)
|
|||
|
||||
void cubic_emit(cubic_info curve, vec2 p[4], float s0, float s1, vec2 sp[4], int pathIndex)
|
||||
{
|
||||
int segIndex = push_segment(sp, MG_GL_CUBIC, pathIndex);
|
||||
int segIndex = push_segment(sp, OC_GL_CUBIC, pathIndex);
|
||||
|
||||
if(segIndex < segmentBuffer.elements.length())
|
||||
{
|
||||
|
@ -839,23 +839,23 @@ void main()
|
|||
{
|
||||
int eltIndex = int(gl_WorkGroupID.x);
|
||||
|
||||
mg_gl_path_elt elt = elementBuffer.elements[elementBufferStart + eltIndex];
|
||||
oc_gl_path_elt elt = elementBuffer.elements[elementBufferStart + eltIndex];
|
||||
|
||||
switch(elt.kind)
|
||||
{
|
||||
case MG_GL_LINE:
|
||||
case OC_GL_LINE:
|
||||
{
|
||||
vec2 p[4] = {elt.p[0]*scale, elt.p[1]*scale, vec2(0), vec2(0)};
|
||||
line_setup(p, elt.pathIndex);
|
||||
} break;
|
||||
|
||||
case MG_GL_QUADRATIC:
|
||||
case OC_GL_QUADRATIC:
|
||||
{
|
||||
vec2 p[4] = {elt.p[0]*scale, elt.p[1]*scale, elt.p[2]*scale, vec2(0)};
|
||||
quadratic_setup(p, elt.pathIndex);
|
||||
} break;
|
||||
|
||||
case MG_GL_CUBIC:
|
||||
case OC_GL_CUBIC:
|
||||
{
|
||||
vec2 p[4] = {elt.p[0]*scale, elt.p[1]*scale, elt.p[2]*scale, elt.p[3]*scale};
|
||||
cubic_setup(p, elt.pathIndex);
|
||||
|
|
|
@ -11,126 +11,121 @@
|
|||
|
||||
#include"util/typedefs.h"
|
||||
#include"platform/platform.h"
|
||||
#include"app/mp_app.h"
|
||||
#include"app/app.h"
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): backends selection
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
typedef enum {
|
||||
MG_NONE,
|
||||
MG_METAL,
|
||||
MG_GL,
|
||||
MG_GLES,
|
||||
MG_CANVAS,
|
||||
MG_HOST } mg_surface_api;
|
||||
OC_NONE,
|
||||
OC_METAL,
|
||||
OC_GL,
|
||||
OC_GLES,
|
||||
OC_CANVAS,
|
||||
OC_HOST } oc_surface_api;
|
||||
|
||||
//NOTE: these macros are used to select which backend to include when building milepost
|
||||
// they can be overridden by passing them to the compiler command line
|
||||
#if PLATFORM_MACOS
|
||||
#ifndef MG_COMPILE_METAL
|
||||
#define MG_COMPILE_METAL 1
|
||||
#if OC_PLATFORM_MACOS
|
||||
#ifndef OC_COMPILE_METAL
|
||||
#define OC_COMPILE_METAL 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_COMPILE_GLES
|
||||
#define MG_COMPILE_GLES 1
|
||||
#ifndef OC_COMPILE_GLES
|
||||
#define OC_COMPILE_GLES 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_COMPILE_CANVAS
|
||||
#if !MG_COMPILE_METAL
|
||||
#error "Canvas surface requires a Metal backend on macOS. Make sure you define MG_COMPILE_METAL to 1."
|
||||
#ifndef OC_COMPILE_CANVAS
|
||||
#if !OC_COMPILE_METAL
|
||||
#error "Canvas surface requires a Metal backend on macOS. Make sure you define OC_COMPILE_METAL to 1."
|
||||
#endif
|
||||
#define MG_COMPILE_CANVAS 1
|
||||
#define OC_COMPILE_CANVAS 1
|
||||
#endif
|
||||
|
||||
#define MG_COMPILE_GL 0
|
||||
#define OC_COMPILE_GL 0
|
||||
|
||||
#elif PLATFORM_WINDOWS
|
||||
#ifndef MG_COMPILE_GL
|
||||
#define MG_COMPILE_GL 1
|
||||
#elif OC_PLATFORM_WINDOWS
|
||||
#ifndef OC_COMPILE_GL
|
||||
#define OC_COMPILE_GL 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_COMPILE_GLES
|
||||
#define MG_COMPILE_GLES 1
|
||||
#ifndef OC_COMPILE_GLES
|
||||
#define OC_COMPILE_GLES 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_COMPILE_CANVAS
|
||||
#if !MG_COMPILE_GL
|
||||
#error "Canvas surface requires an OpenGL backend on Windows. Make sure you define MG_COMPILE_GL to 1."
|
||||
#ifndef OC_COMPILE_CANVAS
|
||||
#if !OC_COMPILE_GL
|
||||
#error "Canvas surface requires an OpenGL backend on Windows. Make sure you define OC_COMPILE_GL to 1."
|
||||
#endif
|
||||
#define MG_COMPILE_CANVAS 1
|
||||
#define OC_COMPILE_CANVAS 1
|
||||
#endif
|
||||
|
||||
#elif PLATFORM_LINUX
|
||||
#ifndef MG_COMPILE_GL
|
||||
#define MG_COMPILE_GL 1
|
||||
#ifndef OC_COMPILE_GL
|
||||
#define OC_COMPILE_GL 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_COMPILE_CANVAS
|
||||
#if !MG_COMPILE_GL
|
||||
#error "Canvas surface requires an OpenGL backend on Linux. Make sure you define MG_COMPILE_GL to 1."
|
||||
#ifndef OC_COMPILE_CANVAS
|
||||
#if !OC_COMPILE_GL
|
||||
#error "Canvas surface requires an OpenGL backend on Linux. Make sure you define OC_COMPILE_GL to 1."
|
||||
#endif
|
||||
#define MG_COMPILE_CANVAS 1
|
||||
#define OC_COMPILE_CANVAS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//NOTE: these macros are used to select backend-specific APIs to include when using milepost
|
||||
#ifdef MG_EXPOSE_SURFACE_METAL
|
||||
#ifdef OC_EXPOSE_SURFACE_METAL
|
||||
#include"mtl_surface.h"
|
||||
#endif
|
||||
|
||||
#ifdef MG_EXPOSE_SURFACE_WGL
|
||||
#ifdef OC_EXPOSE_SURFACE_WGL
|
||||
#include"wgl_surface.h"
|
||||
#endif
|
||||
|
||||
//TODO: expose nsgl surface when supported, expose egl surface, etc...
|
||||
|
||||
//TODO: add MG_INCLUDE_OPENGL/GLES/etc, once we know how we make different gl versions co-exist
|
||||
//TODO: add OC_INCLUDE_OPENGL/GLES/etc, once we know how we make different gl versions co-exist
|
||||
|
||||
MP_API bool mg_is_surface_api_available(mg_surface_api api);
|
||||
ORCA_API bool oc_is_surface_api_available(oc_surface_api api);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): graphics surface
|
||||
//------------------------------------------------------------------------------------------
|
||||
typedef struct mg_surface { u64 h; } mg_surface;
|
||||
typedef struct oc_surface { u64 h; } oc_surface;
|
||||
|
||||
MP_API mg_surface mg_surface_nil(void);
|
||||
MP_API bool mg_surface_is_nil(mg_surface surface);
|
||||
ORCA_API oc_surface oc_surface_nil(void);
|
||||
ORCA_API bool oc_surface_is_nil(oc_surface surface);
|
||||
|
||||
MP_API mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api);
|
||||
MP_API void mg_surface_destroy(mg_surface surface);
|
||||
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);
|
||||
|
||||
MP_API void mg_surface_prepare(mg_surface surface);
|
||||
MP_API void mg_surface_present(mg_surface surface);
|
||||
MP_API void mg_surface_deselect(void);
|
||||
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);
|
||||
|
||||
MP_API void mg_surface_swap_interval(mg_surface surface, int swap);
|
||||
MP_API vec2 mg_surface_get_size(mg_surface surface);
|
||||
MP_API vec2 mg_surface_contents_scaling(mg_surface surface);
|
||||
MP_API bool mg_surface_get_hidden(mg_surface surface);
|
||||
MP_API void mg_surface_set_hidden(mg_surface surface, bool hidden);
|
||||
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);
|
||||
|
||||
//NOTE(martin): surface sharing
|
||||
typedef u64 mg_surface_id;
|
||||
typedef u64 oc_surface_id;
|
||||
|
||||
MP_API mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api);
|
||||
MP_API mg_surface mg_surface_create_host(mp_window window);
|
||||
MP_API mg_surface_id mg_surface_remote_id(mg_surface surface);
|
||||
MP_API void mg_surface_host_connect(mg_surface surface, mg_surface_id remoteId);
|
||||
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);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): graphics canvas structs
|
||||
//------------------------------------------------------------------------------------------
|
||||
typedef struct mg_canvas { u64 h; } mg_canvas;
|
||||
typedef struct mg_font { u64 h; } mg_font;
|
||||
typedef struct mg_image { u64 h; } mg_image;
|
||||
typedef struct oc_canvas { u64 h; } oc_canvas;
|
||||
typedef struct oc_font { u64 h; } oc_font;
|
||||
typedef struct oc_image { u64 h; } oc_image;
|
||||
|
||||
typedef struct mg_mat2x3
|
||||
{
|
||||
f32 m[6];
|
||||
} mg_mat2x3;
|
||||
|
||||
typedef struct mg_color
|
||||
typedef struct oc_color
|
||||
{
|
||||
union
|
||||
{
|
||||
|
@ -143,16 +138,16 @@ typedef struct mg_color
|
|||
};
|
||||
f32 c[4];
|
||||
};
|
||||
} mg_color;
|
||||
} oc_color;
|
||||
|
||||
typedef enum {MG_JOINT_MITER = 0,
|
||||
MG_JOINT_BEVEL,
|
||||
MG_JOINT_NONE } mg_joint_type;
|
||||
typedef enum {OC_JOINT_MITER = 0,
|
||||
OC_JOINT_BEVEL,
|
||||
OC_JOINT_NONE } oc_joint_type;
|
||||
|
||||
typedef enum {MG_CAP_NONE = 0,
|
||||
MG_CAP_SQUARE } mg_cap_type;
|
||||
typedef enum {OC_CAP_NONE = 0,
|
||||
OC_CAP_SQUARE } oc_cap_type;
|
||||
|
||||
typedef struct mg_font_extents
|
||||
typedef struct oc_font_extents
|
||||
{
|
||||
f32 ascent; // the extent above the baseline (by convention a positive value extends above the baseline)
|
||||
f32 descent; // the extent below the baseline (by convention, positive value extends below the baseline)
|
||||
|
@ -161,9 +156,9 @@ typedef struct mg_font_extents
|
|||
f32 capHeight; // height of the upper case letter 'M'
|
||||
f32 width; // maximum width of the font
|
||||
|
||||
} mg_font_extents;
|
||||
} oc_font_extents;
|
||||
|
||||
typedef struct mg_text_extents
|
||||
typedef struct oc_text_extents
|
||||
{
|
||||
f32 xBearing;
|
||||
f32 yBearing;
|
||||
|
@ -172,159 +167,159 @@ typedef struct mg_text_extents
|
|||
f32 xAdvance;
|
||||
f32 yAdvance;
|
||||
|
||||
} mg_text_extents;
|
||||
} oc_text_extents;
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): graphics canvas
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API mg_canvas mg_canvas_nil(void);
|
||||
MP_API bool mg_canvas_is_nil(mg_canvas canvas);
|
||||
ORCA_API oc_canvas oc_canvas_nil(void);
|
||||
ORCA_API bool oc_canvas_is_nil(oc_canvas canvas);
|
||||
|
||||
MP_API mg_canvas mg_canvas_create(void);
|
||||
MP_API void mg_canvas_destroy(mg_canvas canvas);
|
||||
MP_API mg_canvas mg_canvas_set_current(mg_canvas canvas);
|
||||
MP_API void mg_render(mg_surface surface, mg_canvas canvas);
|
||||
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);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): fonts
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API mg_font mg_font_nil(void);
|
||||
MP_API mg_font mg_font_create_from_memory(u32 size, byte* buffer, u32 rangeCount, unicode_range* ranges);
|
||||
MP_API void mg_font_destroy(mg_font font);
|
||||
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);
|
||||
ORCA_API void oc_font_destroy(oc_font font);
|
||||
|
||||
//NOTE(martin): the following int valued functions return -1 if font is invalid or codepoint is not present in font//
|
||||
//TODO(martin): add enum error codes
|
||||
|
||||
MP_API mg_font_extents mg_font_get_extents(mg_font font);
|
||||
MP_API mg_font_extents mg_font_get_scaled_extents(mg_font font, f32 emSize);
|
||||
MP_API f32 mg_font_get_scale_for_em_pixels(mg_font font, f32 emSize);
|
||||
ORCA_API oc_font_extents oc_font_get_extents(oc_font font);
|
||||
ORCA_API oc_font_extents oc_font_get_scaled_extents(oc_font font, f32 emSize);
|
||||
ORCA_API f32 oc_font_get_scale_for_em_pixels(oc_font font, f32 emSize);
|
||||
|
||||
//NOTE(martin): if you need to process more than one codepoint, first convert your codepoints to glyph indices, then use the
|
||||
// glyph index versions of the functions, which can take an array of glyph indices.
|
||||
|
||||
MP_API str32 mg_font_get_glyph_indices(mg_font font, str32 codePoints, str32 backing);
|
||||
MP_API str32 mg_font_push_glyph_indices(mg_font font, mem_arena* arena, str32 codePoints);
|
||||
MP_API u32 mg_font_get_glyph_index(mg_font font, utf32 codePoint);
|
||||
ORCA_API oc_str32 oc_font_get_glyph_indices(oc_font font, oc_str32 codePoints, oc_str32 backing);
|
||||
ORCA_API oc_str32 oc_font_push_glyph_indices(oc_font font, oc_arena* arena, oc_str32 codePoints);
|
||||
ORCA_API u32 oc_font_get_glyph_index(oc_font font, oc_utf32 codePoint);
|
||||
|
||||
MP_API int mg_font_get_codepoint_extents(mg_font font, utf32 codePoint, mg_text_extents* outExtents);
|
||||
ORCA_API int oc_font_get_codepoint_extents(oc_font font, oc_utf32 codePoint, oc_text_extents* outExtents);
|
||||
|
||||
MP_API int mg_font_get_glyph_extents(mg_font font, str32 glyphIndices, mg_text_extents* outExtents);
|
||||
ORCA_API int oc_font_get_glyph_extents(oc_font font, oc_str32 glyphIndices, oc_text_extents* outExtents);
|
||||
|
||||
MP_API mp_rect mg_text_bounding_box_utf32(mg_font font, f32 fontSize, str32 text);
|
||||
MP_API mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text);
|
||||
ORCA_API oc_rect oc_text_bounding_box_utf32(oc_font font, f32 fontSize, oc_str32 text);
|
||||
ORCA_API oc_rect oc_text_bounding_box(oc_font font, f32 fontSize, oc_str8 text);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): images
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API mg_image mg_image_nil(void);
|
||||
MP_API bool mg_image_is_nil(mg_image a);
|
||||
ORCA_API oc_image oc_image_nil(void);
|
||||
ORCA_API bool oc_image_is_nil(oc_image a);
|
||||
|
||||
MP_API mg_image mg_image_create(mg_surface surface, u32 width, u32 height);
|
||||
MP_API mg_image mg_image_create_from_rgba8(mg_surface surface, u32 width, u32 height, u8* pixels);
|
||||
MP_API mg_image mg_image_create_from_data(mg_surface surface, str8 data, bool flip);
|
||||
MP_API mg_image mg_image_create_from_file(mg_surface surface, str8 path, bool flip);
|
||||
ORCA_API oc_image oc_image_create(oc_surface surface, u32 width, u32 height);
|
||||
ORCA_API oc_image oc_image_create_from_rgba8(oc_surface surface, u32 width, u32 height, u8* pixels);
|
||||
ORCA_API oc_image oc_image_create_from_memory(oc_surface surface, oc_str8 mem, bool flip);
|
||||
ORCA_API oc_image oc_image_create_from_file(oc_surface surface, oc_str8 path, bool flip);
|
||||
|
||||
MP_API void mg_image_destroy(mg_image image);
|
||||
ORCA_API void oc_image_destroy(oc_image image);
|
||||
|
||||
MP_API void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels);
|
||||
MP_API vec2 mg_image_size(mg_image image);
|
||||
ORCA_API void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels);
|
||||
ORCA_API oc_vec2 oc_image_size(oc_image image);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): atlasing
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
//NOTE: rectangle allocator
|
||||
typedef struct mg_rect_atlas mg_rect_atlas;
|
||||
typedef struct oc_rect_atlas oc_rect_atlas;
|
||||
|
||||
MP_API mg_rect_atlas* mg_rect_atlas_create(mem_arena* arena, i32 width, i32 height);
|
||||
MP_API mp_rect mg_rect_atlas_alloc(mg_rect_atlas* atlas, i32 width, i32 height);
|
||||
MP_API void mg_rect_atlas_recycle(mg_rect_atlas* atlas, mp_rect rect);
|
||||
ORCA_API oc_rect_atlas* oc_rect_atlas_create(oc_arena* arena, i32 width, i32 height);
|
||||
ORCA_API oc_rect oc_rect_atlas_alloc(oc_rect_atlas* atlas, i32 width, i32 height);
|
||||
ORCA_API void oc_rect_atlas_recycle(oc_rect_atlas* atlas, oc_rect rect);
|
||||
|
||||
//NOTE: image atlas helpers
|
||||
typedef struct mg_image_region
|
||||
typedef struct oc_image_region
|
||||
{
|
||||
mg_image image;
|
||||
mp_rect rect;
|
||||
} mg_image_region;
|
||||
oc_image image;
|
||||
oc_rect rect;
|
||||
} oc_image_region;
|
||||
|
||||
MP_API mg_image_region mg_image_atlas_alloc_from_rgba8(mg_rect_atlas* atlas, mg_image backingImage, u32 width, u32 height, u8* pixels);
|
||||
MP_API mg_image_region mg_image_atlas_alloc_from_data(mg_rect_atlas* atlas, mg_image backingImage, str8 data, bool flip);
|
||||
MP_API mg_image_region mg_image_atlas_alloc_from_file(mg_rect_atlas* atlas, mg_image backingImage, str8 path, bool flip);
|
||||
MP_API void mg_image_atlas_recycle(mg_rect_atlas* atlas, mg_image_region imageRgn);
|
||||
ORCA_API oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_image backingImage, u32 width, u32 height, u8* pixels);
|
||||
ORCA_API oc_image_region oc_image_atlas_alloc_from_data(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 data, bool flip);
|
||||
ORCA_API oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 path, bool flip);
|
||||
ORCA_API void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): transform, viewport and clipping
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API void mg_viewport(mp_rect viewPort);
|
||||
ORCA_API void oc_viewport(oc_rect viewPort);
|
||||
|
||||
MP_API void mg_matrix_push(mg_mat2x3 matrix);
|
||||
MP_API void mg_matrix_pop(void);
|
||||
ORCA_API void oc_matrix_push(oc_mat2x3 matrix);
|
||||
ORCA_API void oc_matrix_pop(void);
|
||||
|
||||
MP_API void mg_clip_push(f32 x, f32 y, f32 w, f32 h);
|
||||
MP_API void mg_clip_pop(void);
|
||||
ORCA_API void oc_clip_push(f32 x, f32 y, f32 w, f32 h);
|
||||
ORCA_API void oc_clip_pop(void);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): graphics attributes setting/getting
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API void mg_set_color(mg_color color);
|
||||
MP_API void mg_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
|
||||
MP_API void mg_set_width(f32 width);
|
||||
MP_API void mg_set_tolerance(f32 tolerance);
|
||||
MP_API void mg_set_joint(mg_joint_type joint);
|
||||
MP_API void mg_set_max_joint_excursion(f32 maxJointExcursion);
|
||||
MP_API void mg_set_cap(mg_cap_type cap);
|
||||
MP_API void mg_set_font(mg_font font);
|
||||
MP_API void mg_set_font_size(f32 size);
|
||||
MP_API void mg_set_text_flip(bool flip);
|
||||
MP_API void mg_set_image(mg_image image);
|
||||
MP_API void mg_set_image_source_region(mp_rect region);
|
||||
ORCA_API void oc_set_color(oc_color color);
|
||||
ORCA_API void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
|
||||
ORCA_API void oc_set_width(f32 width);
|
||||
ORCA_API void oc_set_tolerance(f32 tolerance);
|
||||
ORCA_API void oc_set_joint(oc_joint_type joint);
|
||||
ORCA_API void oc_set_max_joint_excursion(f32 maxJointExcursion);
|
||||
ORCA_API void oc_set_cap(oc_cap_type cap);
|
||||
ORCA_API void oc_set_font(oc_font font);
|
||||
ORCA_API void oc_set_font_size(f32 size);
|
||||
ORCA_API void oc_set_text_flip(bool flip);
|
||||
ORCA_API void oc_set_image(oc_image image);
|
||||
ORCA_API void oc_set_image_source_region(oc_rect region);
|
||||
|
||||
MP_API mg_color mg_get_color(void);
|
||||
MP_API f32 mg_get_width(void);
|
||||
MP_API f32 mg_get_tolerance(void);
|
||||
MP_API mg_joint_type mg_get_joint(void);
|
||||
MP_API f32 mg_get_max_joint_excursion(void);
|
||||
MP_API mg_cap_type mg_get_cap(void);
|
||||
MP_API mg_font mg_get_font(void);
|
||||
MP_API f32 mg_get_font_size(void);
|
||||
MP_API bool mg_get_text_flip(void);
|
||||
ORCA_API oc_color oc_get_color(void);
|
||||
ORCA_API f32 oc_get_width(void);
|
||||
ORCA_API f32 oc_get_tolerance(void);
|
||||
ORCA_API oc_joint_type oc_get_joint(void);
|
||||
ORCA_API f32 oc_get_max_joint_excursion(void);
|
||||
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);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): path construction
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API vec2 mg_get_position(void);
|
||||
MP_API void mg_move_to(f32 x, f32 y);
|
||||
MP_API void mg_line_to(f32 x, f32 y);
|
||||
MP_API void mg_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
|
||||
MP_API void mg_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
|
||||
MP_API void mg_close_path(void);
|
||||
ORCA_API oc_vec2 oc_get_position(void);
|
||||
ORCA_API void oc_move_to(f32 x, f32 y);
|
||||
ORCA_API void oc_line_to(f32 x, f32 y);
|
||||
ORCA_API void oc_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
|
||||
ORCA_API void oc_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
|
||||
ORCA_API void oc_close_path(void);
|
||||
|
||||
MP_API mp_rect mg_glyph_outlines(str32 glyphIndices);
|
||||
MP_API void mg_codepoints_outlines(str32 string);
|
||||
MP_API void mg_text_outlines(str8 string);
|
||||
ORCA_API oc_rect oc_glyph_outlines(oc_str32 glyphIndices);
|
||||
ORCA_API void oc_codepoints_outlines(oc_str32 string);
|
||||
ORCA_API void oc_text_outlines(oc_str8 string);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): clear/fill/stroke
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API void mg_clear(void);
|
||||
MP_API void mg_fill(void);
|
||||
MP_API void mg_stroke(void);
|
||||
ORCA_API void oc_clear(void);
|
||||
ORCA_API void oc_fill(void);
|
||||
ORCA_API void oc_stroke(void);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): 'fast' shapes primitives
|
||||
//------------------------------------------------------------------------------------------
|
||||
MP_API void mg_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
|
||||
MP_API void mg_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
|
||||
MP_API void mg_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
|
||||
MP_API void mg_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
|
||||
MP_API void mg_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
|
||||
MP_API void mg_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
|
||||
MP_API void mg_circle_fill(f32 x, f32 y, f32 r);
|
||||
MP_API void mg_circle_stroke(f32 x, f32 y, f32 r);
|
||||
MP_API void mg_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
|
||||
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);
|
||||
ORCA_API void oc_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
|
||||
ORCA_API void oc_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
|
||||
ORCA_API void oc_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
|
||||
ORCA_API void oc_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
|
||||
ORCA_API void oc_circle_fill(f32 x, f32 y, f32 r);
|
||||
ORCA_API void oc_circle_stroke(f32 x, f32 y, f32 r);
|
||||
ORCA_API void oc_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
|
||||
|
||||
//NOTE: image helpers
|
||||
MP_API void mg_image_draw(mg_image image, mp_rect rect);
|
||||
MP_API void mg_image_draw_region(mg_image image, mp_rect srcRegion, mp_rect dstRegion);
|
||||
ORCA_API void oc_image_draw(oc_image image, oc_rect rect);
|
||||
ORCA_API void oc_image_draw_region(oc_image image, oc_rect srcRegion, oc_rect dstRegion);
|
||||
|
||||
#endif //__GRAPHICS_H_
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,70 +13,70 @@
|
|||
//------------------------------------------------------------------------
|
||||
// canvas structs
|
||||
//------------------------------------------------------------------------
|
||||
typedef enum { MG_PATH_MOVE,
|
||||
MG_PATH_LINE,
|
||||
MG_PATH_QUADRATIC,
|
||||
MG_PATH_CUBIC } mg_path_elt_type;
|
||||
typedef enum { OC_PATH_MOVE,
|
||||
OC_PATH_LINE,
|
||||
OC_PATH_QUADRATIC,
|
||||
OC_PATH_CUBIC } oc_path_elt_type;
|
||||
|
||||
typedef struct mg_path_elt
|
||||
typedef struct oc_path_elt
|
||||
{
|
||||
mg_path_elt_type type;
|
||||
vec2 p[3];
|
||||
oc_path_elt_type type;
|
||||
oc_vec2 p[3];
|
||||
|
||||
} mg_path_elt;
|
||||
} oc_path_elt;
|
||||
|
||||
typedef struct mg_path_descriptor
|
||||
typedef struct oc_path_descriptor
|
||||
{
|
||||
u32 startIndex;
|
||||
u32 count;
|
||||
vec2 startPoint;
|
||||
oc_vec2 startPoint;
|
||||
|
||||
} mg_path_descriptor;
|
||||
} oc_path_descriptor;
|
||||
|
||||
typedef struct mg_attributes
|
||||
typedef struct oc_attributes
|
||||
{
|
||||
f32 width;
|
||||
f32 tolerance;
|
||||
mg_color color;
|
||||
mg_joint_type joint;
|
||||
oc_color color;
|
||||
oc_joint_type joint;
|
||||
f32 maxJointExcursion;
|
||||
mg_cap_type cap;
|
||||
oc_cap_type cap;
|
||||
|
||||
mg_font font;
|
||||
oc_font font;
|
||||
f32 fontSize;
|
||||
|
||||
mg_image image;
|
||||
mp_rect srcRegion;
|
||||
oc_image image;
|
||||
oc_rect srcRegion;
|
||||
|
||||
mg_mat2x3 transform;
|
||||
mp_rect clip;
|
||||
oc_mat2x3 transform;
|
||||
oc_rect clip;
|
||||
|
||||
} mg_attributes;
|
||||
} oc_attributes;
|
||||
|
||||
typedef enum { MG_CMD_FILL,
|
||||
MG_CMD_STROKE,
|
||||
MG_CMD_JUMP
|
||||
} mg_primitive_cmd;
|
||||
typedef enum { OC_CMD_FILL,
|
||||
OC_CMD_STROKE,
|
||||
OC_CMD_JUMP
|
||||
} oc_primitive_cmd;
|
||||
|
||||
typedef struct mg_primitive
|
||||
typedef struct oc_primitive
|
||||
{
|
||||
mg_primitive_cmd cmd;
|
||||
mg_attributes attributes;
|
||||
oc_primitive_cmd cmd;
|
||||
oc_attributes attributes;
|
||||
|
||||
union
|
||||
{
|
||||
mg_path_descriptor path;
|
||||
mp_rect rect;
|
||||
oc_path_descriptor path;
|
||||
oc_rect rect;
|
||||
u32 jump;
|
||||
};
|
||||
|
||||
} mg_primitive;
|
||||
} oc_primitive;
|
||||
|
||||
MP_API void mg_surface_render_commands(mg_surface surface,
|
||||
mg_color clearColor,
|
||||
ORCA_API void oc_surface_render_commands(oc_surface surface,
|
||||
oc_color clearColor,
|
||||
u32 primitiveCount,
|
||||
mg_primitive* primitives,
|
||||
oc_primitive* primitives,
|
||||
u32 eltCount,
|
||||
mg_path_elt* elements);
|
||||
oc_path_elt* elements);
|
||||
|
||||
#endif //__GRAPHICS_COMMON_H_
|
||||
|
|
|
@ -12,33 +12,33 @@
|
|||
// per-thread selected surface
|
||||
//---------------------------------------------------------------
|
||||
|
||||
mp_thread_local mg_surface __mgSelectedSurface = {0};
|
||||
oc_thread_local oc_surface oc_selectedSurface = {0};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// typed handles functions
|
||||
//---------------------------------------------------------------
|
||||
|
||||
mg_surface mg_surface_handle_alloc(mg_surface_data* surface)
|
||||
oc_surface oc_surface_handle_alloc(oc_surface_data* surface)
|
||||
{
|
||||
mg_surface handle = {.h = mg_handle_alloc(MG_HANDLE_SURFACE, (void*)surface) };
|
||||
oc_surface handle = {.h = oc_graphics_handle_alloc(OC_GRAPHICS_HANDLE_SURFACE, (void*)surface) };
|
||||
return(handle);
|
||||
}
|
||||
|
||||
mg_surface_data* mg_surface_data_from_handle(mg_surface handle)
|
||||
oc_surface_data* oc_surface_data_from_handle(oc_surface handle)
|
||||
{
|
||||
mg_surface_data* data = mg_data_from_handle(MG_HANDLE_SURFACE, handle.h);
|
||||
oc_surface_data* data = oc_graphics_data_from_handle(OC_GRAPHICS_HANDLE_SURFACE, handle.h);
|
||||
return(data);
|
||||
}
|
||||
|
||||
mg_image mg_image_handle_alloc(mg_image_data* image)
|
||||
oc_image oc_image_handle_alloc(oc_image_data* image)
|
||||
{
|
||||
mg_image handle = {.h = mg_handle_alloc(MG_HANDLE_IMAGE, (void*)image) };
|
||||
oc_image handle = {.h = oc_graphics_handle_alloc(OC_GRAPHICS_HANDLE_IMAGE, (void*)image) };
|
||||
return(handle);
|
||||
}
|
||||
|
||||
mg_image_data* mg_image_data_from_handle(mg_image handle)
|
||||
oc_image_data* oc_image_data_from_handle(oc_image handle)
|
||||
{
|
||||
mg_image_data* data = mg_data_from_handle(MG_HANDLE_IMAGE, handle.h);
|
||||
oc_image_data* data = oc_graphics_data_from_handle(OC_GRAPHICS_HANDLE_IMAGE, handle.h);
|
||||
return(data);
|
||||
}
|
||||
|
||||
|
@ -46,48 +46,48 @@ mg_image_data* mg_image_data_from_handle(mg_image handle)
|
|||
// surface API
|
||||
//---------------------------------------------------------------
|
||||
|
||||
#if MG_COMPILE_GL
|
||||
#if PLATFORM_WINDOWS
|
||||
#if OC_COMPILE_GL
|
||||
#if OC_PLATFORM_WINDOWS
|
||||
#include"wgl_surface.h"
|
||||
#define gl_surface_create_for_window mg_wgl_surface_create_for_window
|
||||
#define oc_gl_surface_create_for_window oc_wgl_surface_create_for_window
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_GLES
|
||||
#if OC_COMPILE_GLES
|
||||
#include"egl_surface.h"
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_METAL
|
||||
#if OC_COMPILE_METAL
|
||||
#include"mtl_surface.h"
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_CANVAS
|
||||
#if PLATFORM_MACOS
|
||||
mg_surface_data* mtl_canvas_surface_create_for_window(mp_window window);
|
||||
#elif PLATFORM_WINDOWS
|
||||
mg_surface_data* gl_canvas_surface_create_for_window(mp_window window);
|
||||
#if OC_COMPILE_CANVAS
|
||||
#if OC_PLATFORM_MACOS
|
||||
oc_surface_data* oc_mtl_canvas_surface_create_for_window(oc_window window);
|
||||
#elif OC_PLATFORM_WINDOWS
|
||||
oc_surface_data* oc_gl_canvas_surface_create_for_window(oc_window window);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool mg_is_surface_backend_available(mg_surface_api api)
|
||||
bool oc_is_surface_backend_available(oc_surface_api api)
|
||||
{
|
||||
bool result = false;
|
||||
switch(api)
|
||||
{
|
||||
#if MG_COMPILE_METAL
|
||||
case MG_METAL:
|
||||
#if OC_COMPILE_METAL
|
||||
case OC_METAL:
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_GL
|
||||
case MG_GL:
|
||||
#if OC_COMPILE_GL
|
||||
case OC_GL:
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_GLES
|
||||
case MG_GLES:
|
||||
#if OC_COMPILE_GLES
|
||||
case OC_GLES:
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_CANVAS
|
||||
case MG_CANVAS:
|
||||
#if OC_COMPILE_CANVAS
|
||||
case OC_CANVAS:
|
||||
#endif
|
||||
result = true;
|
||||
break;
|
||||
|
@ -98,45 +98,45 @@ bool mg_is_surface_backend_available(mg_surface_api api)
|
|||
return(result);
|
||||
}
|
||||
|
||||
mg_surface mg_surface_nil() { return((mg_surface){.h = 0}); }
|
||||
bool mg_surface_is_nil(mg_surface surface) { return(surface.h == 0); }
|
||||
oc_surface oc_surface_nil() { return((oc_surface){.h = 0}); }
|
||||
bool oc_surface_is_nil(oc_surface surface) { return(surface.h == 0); }
|
||||
|
||||
mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api)
|
||||
oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api)
|
||||
{
|
||||
if(__mgData.init)
|
||||
if(oc_graphicsData.init)
|
||||
{
|
||||
mg_init();
|
||||
oc_graphics_init();
|
||||
}
|
||||
mg_surface surfaceHandle = mg_surface_nil();
|
||||
mg_surface_data* surface = 0;
|
||||
oc_surface surfaceHandle = oc_surface_nil();
|
||||
oc_surface_data* surface = 0;
|
||||
|
||||
switch(api)
|
||||
{
|
||||
#if MG_COMPILE_GL
|
||||
case MG_GL:
|
||||
surface = gl_surface_create_for_window(window);
|
||||
#if OC_COMPILE_GL
|
||||
case OC_GL:
|
||||
surface = oc_gl_surface_create_for_window(window);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_GLES
|
||||
case MG_GLES:
|
||||
surface = mg_egl_surface_create_for_window(window);
|
||||
#if OC_COMPILE_GLES
|
||||
case OC_GLES:
|
||||
surface = oc_egl_surface_create_for_window(window);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_METAL
|
||||
case MG_METAL:
|
||||
surface = mg_mtl_surface_create_for_window(window);
|
||||
#if OC_COMPILE_METAL
|
||||
case OC_METAL:
|
||||
surface = oc_mtl_surface_create_for_window(window);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_CANVAS
|
||||
case MG_CANVAS:
|
||||
#if OC_COMPILE_CANVAS
|
||||
case OC_CANVAS:
|
||||
|
||||
#if PLATFORM_MACOS
|
||||
surface = mtl_canvas_surface_create_for_window(window);
|
||||
#elif PLATFORM_WINDOWS
|
||||
surface = gl_canvas_surface_create_for_window(window);
|
||||
#if OC_PLATFORM_MACOS
|
||||
surface = oc_mtl_canvas_surface_create_for_window(window);
|
||||
#elif OC_PLATFORM_WINDOWS
|
||||
surface = oc_gl_canvas_surface_create_for_window(window);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
@ -146,26 +146,26 @@ mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api)
|
|||
}
|
||||
if(surface)
|
||||
{
|
||||
surfaceHandle = mg_surface_handle_alloc(surface);
|
||||
mg_surface_prepare(surfaceHandle);
|
||||
surfaceHandle = oc_surface_handle_alloc(surface);
|
||||
oc_surface_select(surfaceHandle);
|
||||
}
|
||||
return(surfaceHandle);
|
||||
}
|
||||
|
||||
mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api)
|
||||
oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api)
|
||||
{
|
||||
if(!__mgData.init)
|
||||
if(!oc_graphicsData.init)
|
||||
{
|
||||
mg_init();
|
||||
oc_graphics_init();
|
||||
}
|
||||
mg_surface surfaceHandle = mg_surface_nil();
|
||||
mg_surface_data* surface = 0;
|
||||
oc_surface surfaceHandle = oc_surface_nil();
|
||||
oc_surface_data* surface = 0;
|
||||
|
||||
switch(api)
|
||||
{
|
||||
#if MG_COMPILE_GLES
|
||||
case MG_GLES:
|
||||
surface = mg_egl_surface_create_remote(width, height);
|
||||
#if OC_COMPILE_GLES
|
||||
case OC_GLES:
|
||||
surface = oc_egl_surface_create_remote(width, height);
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -174,42 +174,42 @@ mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api)
|
|||
}
|
||||
if(surface)
|
||||
{
|
||||
surfaceHandle = mg_surface_handle_alloc(surface);
|
||||
mg_surface_prepare(surfaceHandle);
|
||||
surfaceHandle = oc_surface_handle_alloc(surface);
|
||||
oc_surface_select(surfaceHandle);
|
||||
}
|
||||
return(surfaceHandle);
|
||||
}
|
||||
|
||||
mg_surface mg_surface_create_host(mp_window window)
|
||||
oc_surface oc_surface_create_host(oc_window window)
|
||||
{
|
||||
if(!__mgData.init)
|
||||
if(!oc_graphicsData.init)
|
||||
{
|
||||
mg_init();
|
||||
oc_graphics_init();
|
||||
}
|
||||
mg_surface handle = mg_surface_nil();
|
||||
mg_surface_data* surface = 0;
|
||||
#if PLATFORM_MACOS
|
||||
surface = mg_osx_surface_create_host(window);
|
||||
#elif PLATFORM_WINDOWS
|
||||
surface = mg_win32_surface_create_host(window);
|
||||
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 = mg_surface_handle_alloc(surface);
|
||||
handle = oc_surface_handle_alloc(surface);
|
||||
}
|
||||
return(handle);
|
||||
}
|
||||
|
||||
void mg_surface_destroy(mg_surface handle)
|
||||
void oc_surface_destroy(oc_surface handle)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
oc_surface_data* surface = oc_surface_data_from_handle(handle);
|
||||
if(surface)
|
||||
{
|
||||
if(__mgSelectedSurface.h == handle.h)
|
||||
if(oc_selectedSurface.h == handle.h)
|
||||
{
|
||||
mg_surface_deselect();
|
||||
oc_surface_deselect();
|
||||
}
|
||||
|
||||
if(surface->backend && surface->backend->destroy)
|
||||
|
@ -217,64 +217,64 @@ void mg_surface_destroy(mg_surface handle)
|
|||
surface->backend->destroy(surface->backend);
|
||||
}
|
||||
surface->destroy(surface);
|
||||
mg_handle_recycle(handle.h);
|
||||
oc_graphics_handle_recycle(handle.h);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_surface_deselect()
|
||||
void oc_surface_deselect()
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
|
||||
mg_surface_data* prevSurface = mg_surface_data_from_handle(__mgSelectedSurface);
|
||||
oc_surface_data* prevSurface = oc_surface_data_from_handle(oc_selectedSurface);
|
||||
if(prevSurface && prevSurface->deselect)
|
||||
{
|
||||
prevSurface->deselect(prevSurface);
|
||||
}
|
||||
__mgSelectedSurface = mg_surface_nil();
|
||||
oc_selectedSurface = oc_surface_nil();
|
||||
}
|
||||
|
||||
void mg_surface_prepare(mg_surface surface)
|
||||
void oc_surface_select(oc_surface surface)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
|
||||
if(surface.h != __mgSelectedSurface.h)
|
||||
if(surface.h != oc_selectedSurface.h)
|
||||
{
|
||||
mg_surface_deselect();
|
||||
oc_surface_deselect();
|
||||
}
|
||||
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->prepare)
|
||||
{
|
||||
surfaceData->prepare(surfaceData);
|
||||
__mgSelectedSurface = surface;
|
||||
oc_selectedSurface = surface;
|
||||
}
|
||||
}
|
||||
|
||||
void mg_surface_present(mg_surface surface)
|
||||
void oc_surface_present(oc_surface surface)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->present)
|
||||
{
|
||||
surfaceData->present(surfaceData);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_surface_swap_interval(mg_surface surface, int swap)
|
||||
void oc_surface_swap_interval(oc_surface surface, int swap)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->swapInterval)
|
||||
{
|
||||
surfaceData->swapInterval(surfaceData, swap);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 mg_surface_get_size(mg_surface surface)
|
||||
oc_vec2 oc_surface_get_size(oc_surface surface)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
vec2 size = {0};
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
oc_vec2 size = {0};
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->getSize)
|
||||
{
|
||||
size = surfaceData->getSize(surfaceData);
|
||||
|
@ -282,11 +282,11 @@ vec2 mg_surface_get_size(mg_surface surface)
|
|||
return(size);
|
||||
}
|
||||
|
||||
vec2 mg_surface_contents_scaling(mg_surface surface)
|
||||
oc_vec2 oc_surface_contents_scaling(oc_surface surface)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
vec2 scaling = {1, 1};
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
oc_vec2 scaling = {1, 1};
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->contentsScaling)
|
||||
{
|
||||
scaling = surfaceData->contentsScaling(surfaceData);
|
||||
|
@ -294,21 +294,21 @@ vec2 mg_surface_contents_scaling(mg_surface surface)
|
|||
return(scaling);
|
||||
}
|
||||
|
||||
void mg_surface_set_hidden(mg_surface surface, bool hidden)
|
||||
void oc_surface_set_hidden(oc_surface surface, bool hidden)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->setHidden)
|
||||
{
|
||||
surfaceData->setHidden(surfaceData, hidden);
|
||||
}
|
||||
}
|
||||
|
||||
bool mg_surface_get_hidden(mg_surface surface)
|
||||
bool oc_surface_get_hidden(oc_surface surface)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||
bool res = false;
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->getHidden)
|
||||
{
|
||||
res = surfaceData->getHidden(surfaceData);
|
||||
|
@ -316,10 +316,10 @@ bool mg_surface_get_hidden(mg_surface surface)
|
|||
return(res);
|
||||
}
|
||||
|
||||
void* mg_surface_native_layer(mg_surface surface)
|
||||
void* oc_surface_native_layer(oc_surface surface)
|
||||
{
|
||||
void* res = 0;
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->nativeLayer)
|
||||
{
|
||||
res = surfaceData->nativeLayer(surfaceData);
|
||||
|
@ -327,10 +327,10 @@ void* mg_surface_native_layer(mg_surface surface)
|
|||
return(res);
|
||||
}
|
||||
|
||||
mg_surface_id mg_surface_remote_id(mg_surface handle)
|
||||
oc_surface_id oc_surface_remote_id(oc_surface handle)
|
||||
{
|
||||
mg_surface_id remoteId = 0;
|
||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||
oc_surface_id remoteId = 0;
|
||||
oc_surface_data* surface = oc_surface_data_from_handle(handle);
|
||||
if(surface && surface->remoteID)
|
||||
{
|
||||
remoteId = surface->remoteID(surface);
|
||||
|
@ -338,27 +338,27 @@ mg_surface_id mg_surface_remote_id(mg_surface handle)
|
|||
return(remoteId);
|
||||
}
|
||||
|
||||
void mg_surface_host_connect(mg_surface handle, mg_surface_id remoteID)
|
||||
void oc_surface_host_connect(oc_surface handle, oc_surface_id remoteID)
|
||||
{
|
||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||
oc_surface_data* surface = oc_surface_data_from_handle(handle);
|
||||
if(surface && surface->hostConnect)
|
||||
{
|
||||
surface->hostConnect(surface, remoteID);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_surface_render_commands(mg_surface surface,
|
||||
mg_color clearColor,
|
||||
void oc_surface_render_commands(oc_surface surface,
|
||||
oc_color clearColor,
|
||||
u32 primitiveCount,
|
||||
mg_primitive* primitives,
|
||||
oc_primitive* primitives,
|
||||
u32 eltCount,
|
||||
mg_path_elt* elements)
|
||||
oc_path_elt* elements)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
|
||||
if(surface.h != __mgSelectedSurface.h)
|
||||
if(surface.h != oc_selectedSurface.h)
|
||||
{
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before drawing onto a surface.\n");
|
||||
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before drawing onto a surface.\n");
|
||||
}
|
||||
else if(surfaceData && surfaceData->backend)
|
||||
{
|
||||
|
@ -375,10 +375,10 @@ void mg_surface_render_commands(mg_surface surface,
|
|||
//NOTE(martin): images
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
vec2 mg_image_size(mg_image image)
|
||||
oc_vec2 oc_image_size(oc_image image)
|
||||
{
|
||||
vec2 res = {0};
|
||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||
oc_vec2 res = {0};
|
||||
oc_image_data* imageData = oc_image_data_from_handle(image);
|
||||
if(imageData)
|
||||
{
|
||||
res = imageData->size;
|
||||
|
@ -386,67 +386,67 @@ vec2 mg_image_size(mg_image image)
|
|||
return(res);
|
||||
}
|
||||
|
||||
mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
|
||||
oc_image oc_image_create(oc_surface surface, u32 width, u32 height)
|
||||
{
|
||||
mg_image image = mg_image_nil();
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
oc_image image = oc_image_nil();
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
|
||||
if(surface.h != __mgSelectedSurface.h)
|
||||
if(surface.h != oc_selectedSurface.h)
|
||||
{
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before modifying graphics resources.\n");
|
||||
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n");
|
||||
}
|
||||
else if(surfaceData && surfaceData->backend)
|
||||
{
|
||||
DEBUG_ASSERT(surfaceData->api == MG_CANVAS);
|
||||
OC_DEBUG_ASSERT(surfaceData->api == OC_CANVAS);
|
||||
|
||||
mg_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (vec2){width, height});
|
||||
oc_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (oc_vec2){width, height});
|
||||
if(imageData)
|
||||
{
|
||||
imageData->surface = surface;
|
||||
image = mg_image_handle_alloc(imageData);
|
||||
image = oc_image_handle_alloc(imageData);
|
||||
}
|
||||
}
|
||||
return(image);
|
||||
}
|
||||
|
||||
void mg_image_destroy(mg_image image)
|
||||
void oc_image_destroy(oc_image image)
|
||||
{
|
||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||
oc_image_data* imageData = oc_image_data_from_handle(image);
|
||||
|
||||
if(imageData)
|
||||
{
|
||||
if(imageData->surface.h != __mgSelectedSurface.h)
|
||||
if(imageData->surface.h != oc_selectedSurface.h)
|
||||
{
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before modifying graphics resources.\n");
|
||||
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface);
|
||||
oc_surface_data* surface = oc_surface_data_from_handle(imageData->surface);
|
||||
if(surface && surface->backend)
|
||||
{
|
||||
surface->backend->imageDestroy(surface->backend, imageData);
|
||||
mg_handle_recycle(image.h);
|
||||
oc_graphics_handle_recycle(image.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
||||
void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels)
|
||||
{
|
||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||
oc_image_data* imageData = oc_image_data_from_handle(image);
|
||||
|
||||
if(imageData)
|
||||
{
|
||||
if(imageData->surface.h != __mgSelectedSurface.h)
|
||||
if(imageData->surface.h != oc_selectedSurface.h)
|
||||
{
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before modifying graphics resources.\n");
|
||||
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface);
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(imageData->surface);
|
||||
if(surfaceData)
|
||||
{
|
||||
DEBUG_ASSERT(surfaceData->backend);
|
||||
OC_DEBUG_ASSERT(surfaceData->backend);
|
||||
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#define __GRAPHICS_SURFACE_H_
|
||||
|
||||
#include"graphics_common.h"
|
||||
#include"app/mp_app_internal.h"
|
||||
#include"app/app_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -18,92 +18,92 @@ extern "C" {
|
|||
//---------------------------------------------------------------
|
||||
// surface interface
|
||||
//---------------------------------------------------------------
|
||||
typedef struct mg_surface_data mg_surface_data;
|
||||
typedef struct mg_canvas_backend mg_canvas_backend;
|
||||
typedef struct oc_surface_data oc_surface_data;
|
||||
typedef struct oc_canvas_backend oc_canvas_backend;
|
||||
|
||||
typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface);
|
||||
typedef void (*mg_surface_prepare_proc)(mg_surface_data* surface);
|
||||
typedef void (*mg_surface_deselect_proc)(mg_surface_data* surface);
|
||||
typedef void (*mg_surface_present_proc)(mg_surface_data* surface);
|
||||
typedef void (*mg_surface_swap_interval_proc)(mg_surface_data* surface, int swap);
|
||||
typedef vec2 (*mg_surface_get_size_proc)(mg_surface_data* surface);
|
||||
typedef vec2 (*mg_surface_contents_scaling_proc)(mg_surface_data* surface);
|
||||
typedef bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface);
|
||||
typedef void (*mg_surface_set_hidden_proc)(mg_surface_data* surface, bool hidden);
|
||||
typedef void* (*mg_surface_native_layer_proc)(mg_surface_data* surface);
|
||||
typedef mg_surface_id (*mg_surface_remote_id_proc)(mg_surface_data* surface);
|
||||
typedef void (*mg_surface_host_connect_proc)(mg_surface_data* surface, mg_surface_id remoteId);
|
||||
typedef void (*oc_surface_destroy_proc)(oc_surface_data* surface);
|
||||
typedef void (*oc_surface_select_proc)(oc_surface_data* surface);
|
||||
typedef void (*oc_surface_deselect_proc)(oc_surface_data* surface);
|
||||
typedef void (*oc_surface_present_proc)(oc_surface_data* surface);
|
||||
typedef void (*oc_surface_swap_interval_proc)(oc_surface_data* surface, int swap);
|
||||
typedef oc_vec2 (*oc_surface_get_size_proc)(oc_surface_data* surface);
|
||||
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 struct mg_surface_data
|
||||
typedef struct oc_surface_data
|
||||
{
|
||||
mg_surface_api api;
|
||||
mp_layer layer;
|
||||
oc_surface_api api;
|
||||
oc_layer layer;
|
||||
|
||||
mg_surface_destroy_proc destroy;
|
||||
mg_surface_prepare_proc prepare;
|
||||
mg_surface_present_proc present;
|
||||
mg_surface_deselect_proc deselect;
|
||||
mg_surface_swap_interval_proc swapInterval;
|
||||
mg_surface_get_size_proc getSize;
|
||||
mg_surface_contents_scaling_proc contentsScaling;
|
||||
mg_surface_get_hidden_proc getHidden;
|
||||
mg_surface_set_hidden_proc setHidden;
|
||||
mg_surface_native_layer_proc nativeLayer;
|
||||
mg_surface_remote_id_proc remoteID;
|
||||
mg_surface_host_connect_proc hostConnect;
|
||||
oc_surface_destroy_proc destroy;
|
||||
oc_surface_select_proc prepare;
|
||||
oc_surface_present_proc present;
|
||||
oc_surface_deselect_proc deselect;
|
||||
oc_surface_swap_interval_proc swapInterval;
|
||||
oc_surface_get_size_proc getSize;
|
||||
oc_surface_contents_scaling_proc contentsScaling;
|
||||
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;
|
||||
|
||||
mg_canvas_backend* backend;
|
||||
oc_canvas_backend* backend;
|
||||
|
||||
} mg_surface_data;
|
||||
} oc_surface_data;
|
||||
|
||||
mg_surface mg_surface_alloc_handle(mg_surface_data* surface);
|
||||
mg_surface_data* mg_surface_data_from_handle(mg_surface handle);
|
||||
oc_surface oc_surface_handle_alloc(oc_surface_data* surface);
|
||||
oc_surface_data* oc_surface_data_from_handle(oc_surface handle);
|
||||
|
||||
void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window);
|
||||
void mg_surface_init_remote(mg_surface_data* surface, u32 width, u32 height);
|
||||
void mg_surface_init_host(mg_surface_data* surface, mp_window_data* window);
|
||||
void mg_surface_cleanup(mg_surface_data* surface);
|
||||
void* mg_surface_native_layer(mg_surface surface);
|
||||
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);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// canvas backend interface
|
||||
//---------------------------------------------------------------
|
||||
typedef struct mg_image_data
|
||||
typedef struct oc_image_data
|
||||
{
|
||||
list_elt listElt;
|
||||
oc_list_elt listElt;
|
||||
u32 generation;
|
||||
mg_surface surface;
|
||||
vec2 size;
|
||||
oc_surface surface;
|
||||
oc_vec2 size;
|
||||
|
||||
} mg_image_data;
|
||||
} oc_image_data;
|
||||
|
||||
typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend);
|
||||
typedef void (*oc_canvas_backend_destroy_proc)(oc_canvas_backend* backend);
|
||||
|
||||
typedef mg_image_data* (*mg_canvas_backend_image_create_proc)(mg_canvas_backend* backend, vec2 size);
|
||||
typedef void (*mg_canvas_backend_image_destroy_proc)(mg_canvas_backend* backend, mg_image_data* image);
|
||||
typedef void (*mg_canvas_backend_image_upload_region_proc)(mg_canvas_backend* backend,
|
||||
mg_image_data* image,
|
||||
mp_rect region,
|
||||
typedef oc_image_data* (*oc_canvas_backend_image_create_proc)(oc_canvas_backend* backend, oc_vec2 size);
|
||||
typedef void (*oc_canvas_backend_image_destroy_proc)(oc_canvas_backend* backend, oc_image_data* image);
|
||||
typedef void (*oc_canvas_backend_image_upload_region_proc)(oc_canvas_backend* backend,
|
||||
oc_image_data* image,
|
||||
oc_rect region,
|
||||
u8* pixels);
|
||||
|
||||
typedef void (*mg_canvas_backend_render_proc)(mg_canvas_backend* backend,
|
||||
mg_color clearColor,
|
||||
typedef void (*oc_canvas_backend_render_proc)(oc_canvas_backend* backend,
|
||||
oc_color clearColor,
|
||||
u32 primitiveCount,
|
||||
mg_primitive* primitives,
|
||||
oc_primitive* primitives,
|
||||
u32 eltCount,
|
||||
mg_path_elt* pathElements);
|
||||
oc_path_elt* pathElements);
|
||||
|
||||
typedef struct mg_canvas_backend
|
||||
typedef struct oc_canvas_backend
|
||||
{
|
||||
mg_canvas_backend_destroy_proc destroy;
|
||||
oc_canvas_backend_destroy_proc destroy;
|
||||
|
||||
mg_canvas_backend_image_create_proc imageCreate;
|
||||
mg_canvas_backend_image_destroy_proc imageDestroy;
|
||||
mg_canvas_backend_image_upload_region_proc imageUploadRegion;
|
||||
oc_canvas_backend_image_create_proc imageCreate;
|
||||
oc_canvas_backend_image_destroy_proc imageDestroy;
|
||||
oc_canvas_backend_image_upload_region_proc imageUploadRegion;
|
||||
|
||||
mg_canvas_backend_render_proc render;
|
||||
oc_canvas_backend_render_proc render;
|
||||
|
||||
} mg_canvas_backend;
|
||||
} oc_canvas_backend;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -12,45 +12,45 @@
|
|||
#include<simd/simd.h>
|
||||
|
||||
typedef enum {
|
||||
MG_MTL_FILL,
|
||||
MG_MTL_STROKE,
|
||||
} mg_mtl_cmd;
|
||||
OC_MTL_FILL,
|
||||
OC_MTL_STROKE,
|
||||
} oc_mtl_cmd;
|
||||
|
||||
typedef struct mg_mtl_path
|
||||
typedef struct oc_mtl_path
|
||||
{
|
||||
mg_mtl_cmd cmd;
|
||||
oc_mtl_cmd cmd;
|
||||
matrix_float3x3 uvTransform;
|
||||
vector_float4 color;
|
||||
vector_float4 box;
|
||||
vector_float4 clip;
|
||||
int texture;
|
||||
} mg_mtl_path;
|
||||
} oc_mtl_path;
|
||||
|
||||
typedef enum {
|
||||
MG_MTL_LINE = 1,
|
||||
MG_MTL_QUADRATIC,
|
||||
MG_MTL_CUBIC,
|
||||
} mg_mtl_seg_kind;
|
||||
OC_MTL_LINE = 1,
|
||||
OC_MTL_QUADRATIC,
|
||||
OC_MTL_CUBIC,
|
||||
} oc_mtl_seg_kind;
|
||||
|
||||
typedef struct mg_mtl_path_elt
|
||||
typedef struct oc_mtl_path_elt
|
||||
{
|
||||
int pathIndex;
|
||||
mg_mtl_seg_kind kind;
|
||||
oc_mtl_seg_kind kind;
|
||||
vector_float2 p[4];
|
||||
} mg_mtl_path_elt;
|
||||
} oc_mtl_path_elt;
|
||||
|
||||
typedef enum {
|
||||
MG_MTL_BL, // curve on bottom left
|
||||
MG_MTL_BR, // curve on bottom right
|
||||
MG_MTL_TL, // curve on top left
|
||||
MG_MTL_TR // curve on top right
|
||||
} mg_mtl_seg_config;
|
||||
OC_MTL_BL, // curve on bottom left
|
||||
OC_MTL_BR, // curve on bottom right
|
||||
OC_MTL_TL, // curve on top left
|
||||
OC_MTL_TR // curve on top right
|
||||
} oc_mtl_seg_config;
|
||||
|
||||
typedef struct mg_mtl_segment
|
||||
typedef struct oc_mtl_segment
|
||||
{
|
||||
mg_mtl_seg_kind kind;
|
||||
oc_mtl_seg_kind kind;
|
||||
int pathIndex;
|
||||
mg_mtl_seg_config config; //TODO pack these
|
||||
oc_mtl_seg_config config; //TODO pack these
|
||||
int windingIncrement;
|
||||
vector_float4 box;
|
||||
matrix_float3x3 implicitMatrix;
|
||||
|
@ -58,27 +58,27 @@ typedef struct mg_mtl_segment
|
|||
vector_float2 hullVertex;
|
||||
int debugID;
|
||||
|
||||
} mg_mtl_segment;
|
||||
} oc_mtl_segment;
|
||||
|
||||
typedef struct mg_mtl_path_queue
|
||||
typedef struct oc_mtl_path_queue
|
||||
{
|
||||
vector_int4 area;
|
||||
int tileQueues;
|
||||
} mg_mtl_path_queue;
|
||||
} oc_mtl_path_queue;
|
||||
|
||||
#ifdef __METAL_VERSION__
|
||||
using namespace metal;
|
||||
#endif
|
||||
|
||||
typedef enum { MG_MTL_OP_FILL,
|
||||
MG_MTL_OP_CLIP_FILL,
|
||||
MG_MTL_OP_START,
|
||||
MG_MTL_OP_END,
|
||||
MG_MTL_OP_SEGMENT } mg_mtl_tile_op_kind;
|
||||
typedef enum { OC_MTL_OP_FILL,
|
||||
OC_MTL_OP_CLIP_FILL,
|
||||
OC_MTL_OP_START,
|
||||
OC_MTL_OP_END,
|
||||
OC_MTL_OP_SEGMENT } oc_mtl_tile_op_kind;
|
||||
|
||||
typedef struct mg_mtl_tile_op
|
||||
typedef struct oc_mtl_tile_op
|
||||
{
|
||||
mg_mtl_tile_op_kind kind;
|
||||
oc_mtl_tile_op_kind kind;
|
||||
int index;
|
||||
int next;
|
||||
union
|
||||
|
@ -87,25 +87,25 @@ typedef struct mg_mtl_tile_op
|
|||
int windingOffset;
|
||||
};
|
||||
|
||||
} mg_mtl_tile_op;
|
||||
} oc_mtl_tile_op;
|
||||
|
||||
typedef struct mg_mtl_tile_queue
|
||||
typedef struct oc_mtl_tile_queue
|
||||
{
|
||||
atomic_int windingOffset;
|
||||
atomic_int first;
|
||||
int last;
|
||||
|
||||
} mg_mtl_tile_queue;
|
||||
} oc_mtl_tile_queue;
|
||||
|
||||
typedef struct mg_mtl_screen_tile
|
||||
typedef struct oc_mtl_screen_tile
|
||||
{
|
||||
vector_uint2 tileCoord;
|
||||
int first;
|
||||
|
||||
} mg_mtl_screen_tile;
|
||||
} oc_mtl_screen_tile;
|
||||
|
||||
enum {
|
||||
MG_MTL_MAX_IMAGES_PER_BATCH = 30
|
||||
OC_MTL_MAX_IMAGES_PER_BATCH = 30
|
||||
};
|
||||
|
||||
#endif //__MTL_RENDERER_H_
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -227,16 +227,16 @@ void log_cubic_bezier(thread float2* p, mtl_log_context logCtx)
|
|||
}
|
||||
|
||||
kernel void mtl_path_setup(constant int* pathCount [[buffer(0)]],
|
||||
const device mg_mtl_path* pathBuffer [[buffer(1)]],
|
||||
device mg_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
||||
device mg_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
||||
const device oc_mtl_path* pathBuffer [[buffer(1)]],
|
||||
device oc_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
||||
device oc_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
||||
device atomic_int* tileQueueCount [[buffer(4)]],
|
||||
constant int* tileQueueMax [[buffer(5)]],
|
||||
constant int* tileSize [[buffer(6)]],
|
||||
constant float* scale [[buffer(7)]],
|
||||
uint pathIndex [[thread_position_in_grid]])
|
||||
{
|
||||
const device mg_mtl_path* path = &pathBuffer[pathIndex];
|
||||
const device oc_mtl_path* path = &pathBuffer[pathIndex];
|
||||
|
||||
|
||||
//NOTE: we don't clip on the right, since we need those tiles to accurately compute
|
||||
|
@ -265,7 +265,7 @@ kernel void mtl_path_setup(constant int* pathCount [[buffer(0)]],
|
|||
pathQueueBuffer[pathIndex].area = int4(firstTile.x, firstTile.y, nTilesX, nTilesY);
|
||||
pathQueueBuffer[pathIndex].tileQueues = tileQueuesIndex;
|
||||
|
||||
device mg_mtl_tile_queue* tileQueues = &tileQueueBuffer[tileQueuesIndex];
|
||||
device oc_mtl_tile_queue* tileQueues = &tileQueueBuffer[tileQueuesIndex];
|
||||
|
||||
for(int i=0; i<tileCount; i++)
|
||||
{
|
||||
|
@ -281,7 +281,7 @@ float ccw(float2 a, float2 b, float2 c)
|
|||
return((b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x));
|
||||
}
|
||||
|
||||
int mtl_side_of_segment(float2 p, const device mg_mtl_segment* seg, mtl_log_context log = {.enabled = false})
|
||||
int mtl_side_of_segment(float2 p, const device oc_mtl_segment* seg, mtl_log_context log = {.enabled = false})
|
||||
{
|
||||
int side = 0;
|
||||
if(p.y > seg->box.w || p.y <= seg->box.y)
|
||||
|
@ -290,11 +290,11 @@ int mtl_side_of_segment(float2 p, const device mg_mtl_segment* seg, mtl_log_cont
|
|||
{
|
||||
if(p.y > seg->box.w)
|
||||
{
|
||||
side = (seg->config == MG_MTL_TL || seg->config == MG_MTL_BR)? -1 : 1;
|
||||
side = (seg->config == OC_MTL_TL || seg->config == OC_MTL_BR)? -1 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
side = (seg->config == MG_MTL_TL || seg->config == MG_MTL_BR)? 1 : -1;
|
||||
side = (seg->config == OC_MTL_TL || seg->config == OC_MTL_BR)? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,22 +311,22 @@ int mtl_side_of_segment(float2 p, const device mg_mtl_segment* seg, mtl_log_cont
|
|||
float2 a, b, c;
|
||||
switch(seg->config)
|
||||
{
|
||||
case MG_MTL_TL:
|
||||
case OC_MTL_TL:
|
||||
a = seg->box.xy;
|
||||
b = seg->box.zw;
|
||||
break;
|
||||
|
||||
case MG_MTL_BR:
|
||||
case OC_MTL_BR:
|
||||
a = seg->box.zw;
|
||||
b = seg->box.xy;
|
||||
break;
|
||||
|
||||
case MG_MTL_TR:
|
||||
case OC_MTL_TR:
|
||||
a = seg->box.xw;
|
||||
b = seg->box.zy;
|
||||
break;
|
||||
|
||||
case MG_MTL_BL:
|
||||
case OC_MTL_BL:
|
||||
a = seg->box.zy;
|
||||
b = seg->box.xw;
|
||||
break;
|
||||
|
@ -336,30 +336,30 @@ int mtl_side_of_segment(float2 p, const device mg_mtl_segment* seg, mtl_log_cont
|
|||
if(ccw(a, b, p) < 0)
|
||||
{
|
||||
// other side of the diagonal
|
||||
side = (seg->config == MG_MTL_BR || seg->config == MG_MTL_TR) ? -1 : 1;
|
||||
side = (seg->config == OC_MTL_BR || seg->config == OC_MTL_TR) ? -1 : 1;
|
||||
}
|
||||
else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0)
|
||||
{
|
||||
// same side of the diagonal, but outside curve hull
|
||||
side = (seg->config == MG_MTL_BL || seg->config == MG_MTL_TL) ? -1 : 1;
|
||||
side = (seg->config == OC_MTL_BL || seg->config == OC_MTL_TL) ? -1 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// inside curve hull
|
||||
switch(seg->kind)
|
||||
{
|
||||
case MG_MTL_LINE:
|
||||
case OC_MTL_LINE:
|
||||
side = 1;
|
||||
break;
|
||||
|
||||
case MG_MTL_QUADRATIC:
|
||||
case OC_MTL_QUADRATIC:
|
||||
{
|
||||
float3 ph = {p.x, p.y, 1};
|
||||
float3 klm = seg->implicitMatrix * ph;
|
||||
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
|
||||
} break;
|
||||
|
||||
case MG_MTL_CUBIC:
|
||||
case OC_MTL_CUBIC:
|
||||
{
|
||||
float3 ph = {p.x, p.y, 1};
|
||||
float3 klm = seg->implicitMatrix * ph;
|
||||
|
@ -375,10 +375,10 @@ int mtl_side_of_segment(float2 p, const device mg_mtl_segment* seg, mtl_log_cont
|
|||
typedef struct mtl_segment_setup_context
|
||||
{
|
||||
device atomic_int* segmentCount;
|
||||
device mg_mtl_segment* segmentBuffer;
|
||||
const device mg_mtl_path_queue* pathQueue;
|
||||
device mg_mtl_tile_queue* tileQueues;
|
||||
device mg_mtl_tile_op* tileOpBuffer;
|
||||
device oc_mtl_segment* segmentBuffer;
|
||||
const device oc_mtl_path_queue* pathQueue;
|
||||
device oc_mtl_tile_queue* tileQueues;
|
||||
device oc_mtl_tile_op* tileOpBuffer;
|
||||
device atomic_int* tileOpCount;
|
||||
int tileSize;
|
||||
mtl_log_context log;
|
||||
|
@ -390,7 +390,7 @@ typedef struct mtl_segment_setup_context
|
|||
|
||||
} mtl_segment_setup_context;
|
||||
|
||||
void mtl_segment_bin_to_tiles(thread mtl_segment_setup_context* context, device mg_mtl_segment* seg)
|
||||
void mtl_segment_bin_to_tiles(thread mtl_segment_setup_context* context, device oc_mtl_segment* seg)
|
||||
{
|
||||
//NOTE: add segment index to the queues of tiles it overlaps with
|
||||
int segIndex = seg - context->segmentBuffer;
|
||||
|
@ -428,7 +428,7 @@ void mtl_segment_bin_to_tiles(thread mtl_segment_setup_context* context, device
|
|||
bool crossB = (sbl*sbr < 0);
|
||||
|
||||
float2 s0, s1;
|
||||
if(seg->config == MG_MTL_TL||seg->config == MG_MTL_BR)
|
||||
if(seg->config == OC_MTL_TL||seg->config == OC_MTL_BR)
|
||||
{
|
||||
s0 = seg->box.xy;
|
||||
s1 = seg->box.zw;
|
||||
|
@ -454,15 +454,15 @@ void mtl_segment_bin_to_tiles(thread mtl_segment_setup_context* context, device
|
|||
|
||||
if(tileOpIndex < context->tileOpMax)
|
||||
{
|
||||
device mg_mtl_tile_op* op = &context->tileOpBuffer[tileOpIndex];
|
||||
device oc_mtl_tile_op* op = &context->tileOpBuffer[tileOpIndex];
|
||||
|
||||
op->kind = MG_MTL_OP_SEGMENT;
|
||||
op->kind = OC_MTL_OP_SEGMENT;
|
||||
op->index = segIndex;
|
||||
op->crossRight = false;
|
||||
op->next = -1;
|
||||
|
||||
int tileIndex = y*pathArea.z + x;
|
||||
device mg_mtl_tile_queue* tile = &context->tileQueues[tileIndex];
|
||||
device oc_mtl_tile_queue* tile = &context->tileQueues[tileIndex];
|
||||
op->next = atomic_exchange_explicit(&tile->first, tileOpIndex, memory_order_relaxed);
|
||||
if(op->next == -1)
|
||||
{
|
||||
|
@ -489,25 +489,25 @@ void mtl_segment_bin_to_tiles(thread mtl_segment_setup_context* context, device
|
|||
}
|
||||
}
|
||||
|
||||
device mg_mtl_segment* mtl_segment_push(thread mtl_segment_setup_context* context, float2 p[4], mg_mtl_seg_kind kind)
|
||||
device oc_mtl_segment* mtl_segment_push(thread mtl_segment_setup_context* context, float2 p[4], oc_mtl_seg_kind kind)
|
||||
{
|
||||
float2 s, e, c;
|
||||
|
||||
switch(kind)
|
||||
{
|
||||
case MG_MTL_LINE:
|
||||
case OC_MTL_LINE:
|
||||
s = p[0];
|
||||
c = p[0];
|
||||
e = p[1];
|
||||
break;
|
||||
|
||||
case MG_MTL_QUADRATIC:
|
||||
case OC_MTL_QUADRATIC:
|
||||
s = p[0];
|
||||
c = p[1];
|
||||
e = p[2];
|
||||
break;
|
||||
|
||||
case MG_MTL_CUBIC:
|
||||
case OC_MTL_CUBIC:
|
||||
{
|
||||
s = p[0];
|
||||
float sqrNorm0 = length_squared(p[1]-p[0]);
|
||||
|
@ -524,7 +524,7 @@ device mg_mtl_segment* mtl_segment_push(thread mtl_segment_setup_context* contex
|
|||
} break;
|
||||
}
|
||||
|
||||
device mg_mtl_segment* seg = 0;
|
||||
device oc_mtl_segment* seg = 0;
|
||||
|
||||
int segIndex = atomic_fetch_add_explicit(context->segmentCount, 1, memory_order_relaxed);
|
||||
|
||||
|
@ -551,32 +551,32 @@ device mg_mtl_segment* mtl_segment_push(thread mtl_segment_setup_context* contex
|
|||
|
||||
if(goingUp == goingRight)
|
||||
{
|
||||
if(seg->kind == MG_MTL_LINE)
|
||||
if(seg->kind == OC_MTL_LINE)
|
||||
{
|
||||
seg->config = MG_MTL_BR;
|
||||
seg->config = OC_MTL_BR;
|
||||
}
|
||||
else if(dy > alpha*dx)
|
||||
{
|
||||
seg->config = MG_MTL_TL;
|
||||
seg->config = OC_MTL_TL;
|
||||
}
|
||||
else
|
||||
{
|
||||
seg->config = MG_MTL_BR;
|
||||
seg->config = OC_MTL_BR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(seg->kind == MG_MTL_LINE)
|
||||
if(seg->kind == OC_MTL_LINE)
|
||||
{
|
||||
seg->config = MG_MTL_TR;
|
||||
seg->config = OC_MTL_TR;
|
||||
}
|
||||
else if(dy < ofs - alpha*dx)
|
||||
{
|
||||
seg->config = MG_MTL_BL;
|
||||
seg->config = OC_MTL_BL;
|
||||
}
|
||||
else
|
||||
{
|
||||
seg->config = MG_MTL_TR;
|
||||
seg->config = OC_MTL_TR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ device mg_mtl_segment* mtl_segment_push(thread mtl_segment_setup_context* contex
|
|||
|
||||
void mtl_line_setup(thread mtl_segment_setup_context* context, float2 p[2])
|
||||
{
|
||||
device mg_mtl_segment* seg = mtl_segment_push(context, p, MG_MTL_LINE);
|
||||
device oc_mtl_segment* seg = mtl_segment_push(context, p, OC_MTL_LINE);
|
||||
if(seg)
|
||||
{
|
||||
seg->hullVertex = p[0];
|
||||
|
@ -659,7 +659,7 @@ matrix_float3x3 mtl_barycentric_matrix(float2 v0, float2 v1, float2 v2)
|
|||
void mtl_quadratic_emit(thread mtl_segment_setup_context* context,
|
||||
thread float2* p)
|
||||
{
|
||||
device mg_mtl_segment* seg = mtl_segment_push(context, p, MG_MTL_QUADRATIC);
|
||||
device oc_mtl_segment* seg = mtl_segment_push(context, p, OC_MTL_QUADRATIC);
|
||||
|
||||
if(seg)
|
||||
{
|
||||
|
@ -673,7 +673,7 @@ void mtl_quadratic_emit(thread mtl_segment_setup_context* context,
|
|||
float e = p[1].x - p[0].x;
|
||||
float f = p[0].x*p[1].y - p[1].x*p[0].y;
|
||||
|
||||
float flip = (seg->config == MG_MTL_TL || seg->config == MG_MTL_BL)? -1 : 1;
|
||||
float flip = (seg->config == OC_MTL_TL || seg->config == OC_MTL_BL)? -1 : 1;
|
||||
float g = flip*(p[2].x*(p[0].y - p[1].y) + p[0].x*(p[1].y - p[2].y) + p[1].x*(p[2].y - p[0].y));
|
||||
|
||||
seg->implicitMatrix = (1/det)*matrix_float3x3({a, d, 0.},
|
||||
|
@ -1070,7 +1070,7 @@ float2 mtl_select_hull_vertex(float2 p0, float2 p1, float2 p2, float2 p3, mtl_lo
|
|||
|
||||
void mtl_cubic_emit(thread mtl_segment_setup_context* context, mtl_cubic_info curve, float2 p[4], float s0, float s1, float2 sp[4])
|
||||
{
|
||||
device mg_mtl_segment* seg = mtl_segment_push(context, sp, MG_MTL_CUBIC);
|
||||
device oc_mtl_segment* seg = mtl_segment_push(context, sp, OC_MTL_CUBIC);
|
||||
|
||||
if(seg)
|
||||
{
|
||||
|
@ -1253,12 +1253,12 @@ void mtl_cubic_setup(thread mtl_segment_setup_context* context, float2 p[4])
|
|||
}
|
||||
|
||||
kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
||||
const device mg_mtl_path_elt* elementBuffer [[buffer(1)]],
|
||||
const device oc_mtl_path_elt* elementBuffer [[buffer(1)]],
|
||||
device atomic_int* segmentCount [[buffer(2)]],
|
||||
device mg_mtl_segment* segmentBuffer [[buffer(3)]],
|
||||
const device mg_mtl_path_queue* pathQueueBuffer [[buffer(4)]],
|
||||
device mg_mtl_tile_queue* tileQueueBuffer [[buffer(5)]],
|
||||
device mg_mtl_tile_op* tileOpBuffer [[buffer(6)]],
|
||||
device oc_mtl_segment* segmentBuffer [[buffer(3)]],
|
||||
const device oc_mtl_path_queue* pathQueueBuffer [[buffer(4)]],
|
||||
device oc_mtl_tile_queue* tileQueueBuffer [[buffer(5)]],
|
||||
device oc_mtl_tile_op* tileOpBuffer [[buffer(6)]],
|
||||
device atomic_int* tileOpCount [[buffer(7)]],
|
||||
constant int* segmentMax [[buffer(8)]],
|
||||
constant int* tileOpMax [[buffer(9)]],
|
||||
|
@ -1269,9 +1269,9 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
|||
device atomic_int* logOffsetBuffer [[buffer(13)]],
|
||||
uint eltIndex [[thread_position_in_grid]])
|
||||
{
|
||||
const device mg_mtl_path_elt* elt = &elementBuffer[eltIndex];
|
||||
const device mg_mtl_path_queue* pathQueue = &pathQueueBuffer[elt->pathIndex];
|
||||
device mg_mtl_tile_queue* tileQueues = &tileQueueBuffer[pathQueue->tileQueues];
|
||||
const device oc_mtl_path_elt* elt = &elementBuffer[eltIndex];
|
||||
const device oc_mtl_path_queue* pathQueue = &pathQueueBuffer[elt->pathIndex];
|
||||
device oc_mtl_tile_queue* tileQueues = &tileQueueBuffer[pathQueue->tileQueues];
|
||||
|
||||
mtl_segment_setup_context setupCtx = {.pathIndex = elt->pathIndex,
|
||||
.segmentCount = segmentCount,
|
||||
|
@ -1289,7 +1289,7 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
|||
|
||||
switch(elt->kind)
|
||||
{
|
||||
case MG_MTL_LINE:
|
||||
case OC_MTL_LINE:
|
||||
{
|
||||
float2 p[2] = {elt->p[0]*scale[0], elt->p[1]*scale[0]};
|
||||
mtl_log(setupCtx.log, "line: ");
|
||||
|
@ -1297,7 +1297,7 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
|||
mtl_line_setup(&setupCtx, p);
|
||||
} break;
|
||||
|
||||
case MG_MTL_QUADRATIC:
|
||||
case OC_MTL_QUADRATIC:
|
||||
{
|
||||
float2 p[3] = {elt->p[0]*scale[0], elt->p[1]*scale[0], elt->p[2]*scale[0]};
|
||||
mtl_log(setupCtx.log, "quadratic: ");
|
||||
|
@ -1305,7 +1305,7 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
|||
mtl_quadratic_setup(&setupCtx, p);
|
||||
} break;
|
||||
|
||||
case MG_MTL_CUBIC:
|
||||
case OC_MTL_CUBIC:
|
||||
{
|
||||
float2 p[4] = {elt->p[0]*scale[0], elt->p[1]*scale[0], elt->p[2]*scale[0], elt->p[3]*scale[0]};
|
||||
mtl_log(setupCtx.log, "cubic: ");
|
||||
|
@ -1316,8 +1316,8 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
|||
}
|
||||
}
|
||||
|
||||
kernel void mtl_backprop(const device mg_mtl_path_queue* pathQueueBuffer [[buffer(0)]],
|
||||
device mg_mtl_tile_queue* tileQueueBuffer [[buffer(1)]],
|
||||
kernel void mtl_backprop(const device oc_mtl_path_queue* pathQueueBuffer [[buffer(0)]],
|
||||
device oc_mtl_tile_queue* tileQueueBuffer [[buffer(1)]],
|
||||
device char* logBuffer [[buffer(2)]],
|
||||
device atomic_int* logOffsetBuffer [[buffer(3)]],
|
||||
uint pathIndex [[threadgroup_position_in_grid]],
|
||||
|
@ -1333,19 +1333,19 @@ kernel void mtl_backprop(const device mg_mtl_path_queue* pathQueueBuffer [[buffe
|
|||
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||
|
||||
int rowIndex = 0;
|
||||
const device mg_mtl_path_queue* pathQueue = &pathQueueBuffer[pathIndex];
|
||||
device mg_mtl_tile_queue* tiles = &tileQueueBuffer[pathQueue->tileQueues];
|
||||
const device oc_mtl_path_queue* pathQueue = &pathQueueBuffer[pathIndex];
|
||||
device oc_mtl_tile_queue* tiles = &tileQueueBuffer[pathQueue->tileQueues];
|
||||
int rowSize = pathQueue->area.z;
|
||||
int rowCount = pathQueue->area.w;
|
||||
|
||||
rowIndex = atomic_fetch_add_explicit(&nextRowIndex, 1, memory_order_relaxed);
|
||||
while(rowIndex < rowCount)
|
||||
{
|
||||
device mg_mtl_tile_queue* row = &tiles[rowIndex * rowSize];
|
||||
device oc_mtl_tile_queue* row = &tiles[rowIndex * rowSize];
|
||||
int sum = 0;
|
||||
for(int x = rowSize-1; x >= 0; x--)
|
||||
{
|
||||
device mg_mtl_tile_queue* tile = &row[x];
|
||||
device oc_mtl_tile_queue* tile = &row[x];
|
||||
int offset = *(device int*)&tile->windingOffset;
|
||||
*(device int*)(&tile->windingOffset) = sum;
|
||||
sum += offset;
|
||||
|
@ -1355,13 +1355,13 @@ kernel void mtl_backprop(const device mg_mtl_path_queue* pathQueueBuffer [[buffe
|
|||
}
|
||||
|
||||
kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
||||
const device mg_mtl_path* pathBuffer [[buffer(1)]],
|
||||
const device mg_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
||||
const device mg_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
||||
device mg_mtl_tile_op* tileOpBuffer [[buffer(4)]],
|
||||
const device oc_mtl_path* pathBuffer [[buffer(1)]],
|
||||
const device oc_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
||||
const device oc_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
||||
device oc_mtl_tile_op* tileOpBuffer [[buffer(4)]],
|
||||
device atomic_int* tileOpCount [[buffer(5)]],
|
||||
device MTLDispatchThreadgroupsIndirectArguments* dispatchBuffer [[buffer(6)]],
|
||||
device mg_mtl_screen_tile* screenTilesBuffer [[buffer(7)]],
|
||||
device oc_mtl_screen_tile* screenTilesBuffer [[buffer(7)]],
|
||||
constant int* tileOpMax [[buffer(8)]],
|
||||
constant int* tileSize [[buffer(9)]],
|
||||
constant float* scale [[buffer(10)]],
|
||||
|
@ -1384,10 +1384,10 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
|
||||
for(int pathIndex = 0; pathIndex < pathCount[0]; pathIndex++)
|
||||
{
|
||||
const device mg_mtl_path_queue* pathQueue = &pathQueueBuffer[pathIndex];
|
||||
const device oc_mtl_path_queue* pathQueue = &pathQueueBuffer[pathIndex];
|
||||
int2 pathTileCoord = tileCoord - pathQueue->area.xy;
|
||||
|
||||
const device mg_mtl_path* path = &pathBuffer[pathIndex];
|
||||
const device oc_mtl_path* path = &pathBuffer[pathIndex];
|
||||
float xMax = min(path->box.z, path->clip.z);
|
||||
int tileMaxX = xMax * scale[0] / tileSize[0];
|
||||
int pathTileMaxX = tileMaxX - pathQueue->area.x;
|
||||
|
@ -1406,7 +1406,7 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
}
|
||||
|
||||
int pathTileIndex = pathTileCoord.y * pathQueue->area.z + pathTileCoord.x;
|
||||
const device mg_mtl_tile_queue* tileQueue = &tileQueueBuffer[pathQueue->tileQueues + pathTileIndex];
|
||||
const device oc_mtl_tile_queue* tileQueue = &tileQueueBuffer[pathQueue->tileQueues + pathTileIndex];
|
||||
|
||||
int windingOffset = atomic_load_explicit(&tileQueue->windingOffset, memory_order_relaxed);
|
||||
int firstOpIndex = atomic_load_explicit(&tileQueue->first, memory_order_relaxed);
|
||||
|
@ -1435,8 +1435,8 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
return;
|
||||
}
|
||||
|
||||
device mg_mtl_tile_op* pathOp = &tileOpBuffer[pathOpIndex];
|
||||
pathOp->kind = MG_MTL_OP_CLIP_FILL;
|
||||
device oc_mtl_tile_op* pathOp = &tileOpBuffer[pathOpIndex];
|
||||
pathOp->kind = OC_MTL_OP_CLIP_FILL;
|
||||
pathOp->next = -1;
|
||||
pathOp->index = pathIndex;
|
||||
pathOp->windingOffset = windingOffset;
|
||||
|
@ -1448,7 +1448,7 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
&& tileBox.y >= clip.y
|
||||
&& tileBox.w < clip.w)
|
||||
{
|
||||
pathOp->kind = MG_MTL_OP_FILL;
|
||||
pathOp->kind = OC_MTL_OP_FILL;
|
||||
|
||||
if(pathBuffer[pathIndex].color.a == 1 && pathBuffer[pathIndex].texture < 0)
|
||||
{
|
||||
|
@ -1468,8 +1468,8 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
return;
|
||||
}
|
||||
|
||||
device mg_mtl_tile_op* startOp = &tileOpBuffer[startOpIndex];
|
||||
startOp->kind = MG_MTL_OP_START;
|
||||
device oc_mtl_tile_op* startOp = &tileOpBuffer[startOpIndex];
|
||||
startOp->kind = OC_MTL_OP_START;
|
||||
startOp->next = -1;
|
||||
startOp->index = pathIndex;
|
||||
startOp->windingOffset = windingOffset;
|
||||
|
@ -1479,7 +1479,7 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
|
||||
//NOTE: chain remaining path ops to end of tile list
|
||||
int lastOpIndex = tileQueue->last;
|
||||
device mg_mtl_tile_op* lastOp = &tileOpBuffer[lastOpIndex];
|
||||
device oc_mtl_tile_op* lastOp = &tileOpBuffer[lastOpIndex];
|
||||
*nextLink = firstOpIndex;
|
||||
nextLink = &lastOp->next;
|
||||
|
||||
|
@ -1491,8 +1491,8 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
return;
|
||||
}
|
||||
|
||||
device mg_mtl_tile_op* endOp = &tileOpBuffer[endOpIndex];
|
||||
endOp->kind = MG_MTL_OP_END;
|
||||
device oc_mtl_tile_op* endOp = &tileOpBuffer[endOpIndex];
|
||||
endOp->kind = OC_MTL_OP_END;
|
||||
endOp->next = -1;
|
||||
endOp->index = pathIndex;
|
||||
|
||||
|
@ -1503,17 +1503,17 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
|||
}
|
||||
}
|
||||
|
||||
kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buffer(0)]],
|
||||
const device mg_mtl_tile_op* tileOpBuffer [[buffer(1)]],
|
||||
const device mg_mtl_path* pathBuffer [[buffer(2)]],
|
||||
const device mg_mtl_segment* segmentBuffer [[buffer(3)]],
|
||||
kernel void mtl_raster(const device oc_mtl_screen_tile* screenTilesBuffer [[buffer(0)]],
|
||||
const device oc_mtl_tile_op* tileOpBuffer [[buffer(1)]],
|
||||
const device oc_mtl_path* pathBuffer [[buffer(2)]],
|
||||
const device oc_mtl_segment* segmentBuffer [[buffer(3)]],
|
||||
constant int* tileSize [[buffer(4)]],
|
||||
constant float* scale [[buffer(5)]],
|
||||
constant int* sampleCountBuffer [[buffer(6)]],
|
||||
device char* logBuffer [[buffer(7)]],
|
||||
device atomic_int* logOffsetBuffer [[buffer(8)]],
|
||||
texture2d<float, access::write> outTexture [[texture(0)]],
|
||||
array<texture2d<float>, MG_MTL_MAX_IMAGES_PER_BATCH> srcTextures [[texture(1)]],
|
||||
array<texture2d<float>, OC_MTL_MAX_IMAGES_PER_BATCH> srcTextures [[texture(1)]],
|
||||
uint2 threadGroupCoord [[threadgroup_position_in_grid]],
|
||||
uint2 localCoord [[thread_position_in_threadgroup]])
|
||||
{
|
||||
|
@ -1528,8 +1528,8 @@ kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buff
|
|||
|
||||
int opIndex = screenTilesBuffer[tileIndex].first;
|
||||
|
||||
const int MG_MTL_MAX_SAMPLE_COUNT = 8;
|
||||
float2 sampleCoords[MG_MTL_MAX_SAMPLE_COUNT];
|
||||
const int OC_MTL_MAX_SAMPLE_COUNT = 8;
|
||||
float2 sampleCoords[OC_MTL_MAX_SAMPLE_COUNT];
|
||||
int sampleCount = sampleCountBuffer[0];
|
||||
float2 centerCoord = float2(pixelCoord) + float2(0.5, 0.5);
|
||||
|
||||
|
@ -1551,33 +1551,33 @@ kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buff
|
|||
sampleCoords[0] = centerCoord;
|
||||
}
|
||||
|
||||
const int MG_MTL_MAX_SRC_SAMPLE_COUNT = 4;
|
||||
const int OC_MTL_MAX_SRC_SAMPLE_COUNT = 4;
|
||||
const int srcSampleCount = 2;
|
||||
|
||||
const float2 imgSampleCoords[MG_MTL_MAX_SRC_SAMPLE_COUNT] = {
|
||||
const float2 imgSampleCoords[OC_MTL_MAX_SRC_SAMPLE_COUNT] = {
|
||||
centerCoord + float2(-0.25, 0.25),
|
||||
centerCoord + float2(+0.25, +0.25),
|
||||
centerCoord + float2(+0.25, -0.25),
|
||||
centerCoord + float2(-0.25, +0.25)};
|
||||
|
||||
float4 color = {0};
|
||||
int winding[MG_MTL_MAX_SAMPLE_COUNT] = {0};
|
||||
int winding[OC_MTL_MAX_SAMPLE_COUNT] = {0};
|
||||
|
||||
while(opIndex != -1)
|
||||
{
|
||||
const device mg_mtl_tile_op* op = &tileOpBuffer[opIndex];
|
||||
const device oc_mtl_tile_op* op = &tileOpBuffer[opIndex];
|
||||
int pathIndex = op->index;
|
||||
|
||||
if(op->kind == MG_MTL_OP_START)
|
||||
if(op->kind == OC_MTL_OP_START)
|
||||
{
|
||||
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++)
|
||||
{
|
||||
winding[sampleIndex] = op->windingOffset;
|
||||
}
|
||||
}
|
||||
else if(op->kind == MG_MTL_OP_SEGMENT)
|
||||
else if(op->kind == OC_MTL_OP_SEGMENT)
|
||||
{
|
||||
const device mg_mtl_segment* seg = &segmentBuffer[op->index];
|
||||
const device oc_mtl_segment* seg = &segmentBuffer[op->index];
|
||||
|
||||
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++)
|
||||
{
|
||||
|
@ -1592,12 +1592,12 @@ kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buff
|
|||
|
||||
if(op->crossRight)
|
||||
{
|
||||
if( (seg->config == MG_MTL_BR || seg->config == MG_MTL_TL)
|
||||
if( (seg->config == OC_MTL_BR || seg->config == OC_MTL_TL)
|
||||
&&(sampleCoord.y > seg->box.w))
|
||||
{
|
||||
winding[sampleIndex] += seg->windingIncrement;
|
||||
}
|
||||
else if( (seg->config == MG_MTL_BL || seg->config == MG_MTL_TR)
|
||||
else if( (seg->config == OC_MTL_BL || seg->config == OC_MTL_TR)
|
||||
&&(sampleCoord.y > seg->box.y))
|
||||
{
|
||||
winding[sampleIndex] -= seg->windingIncrement;
|
||||
|
@ -1611,7 +1611,7 @@ kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buff
|
|||
nextColor.rgb *= nextColor.a;
|
||||
|
||||
int textureIndex = pathBuffer[pathIndex].texture;
|
||||
if(textureIndex >= 0 && textureIndex < MG_MTL_MAX_IMAGES_PER_BATCH)
|
||||
if(textureIndex >= 0 && textureIndex < OC_MTL_MAX_IMAGES_PER_BATCH)
|
||||
{
|
||||
constexpr sampler smp(mip_filter::nearest, mag_filter::linear, min_filter::linear);
|
||||
|
||||
|
@ -1629,7 +1629,7 @@ kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buff
|
|||
nextColor *= texColor;
|
||||
}
|
||||
|
||||
if(op->kind == MG_MTL_OP_FILL)
|
||||
if(op->kind == OC_MTL_OP_FILL)
|
||||
{
|
||||
color = color*(1-nextColor.a) + nextColor;
|
||||
}
|
||||
|
@ -1647,9 +1647,9 @@ kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buff
|
|||
&& sampleCoord.y >= clip.y
|
||||
&& sampleCoord.y < clip.w)
|
||||
{
|
||||
bool filled = op->kind == MG_MTL_OP_CLIP_FILL
|
||||
||(pathBuffer[pathIndex].cmd == MG_MTL_FILL && (winding[sampleIndex] & 1))
|
||||
||(pathBuffer[pathIndex].cmd == MG_MTL_STROKE && (winding[sampleIndex] != 0));
|
||||
bool filled = op->kind == OC_MTL_OP_CLIP_FILL
|
||||
||(pathBuffer[pathIndex].cmd == OC_MTL_FILL && (winding[sampleIndex] & 1))
|
||||
||(pathBuffer[pathIndex].cmd == OC_MTL_STROKE && (winding[sampleIndex] != 0));
|
||||
if(filled)
|
||||
{
|
||||
coverage++;
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#import<Metal/Metal.h>
|
||||
#endif
|
||||
|
||||
mg_surface_data* mg_mtl_surface_create_for_window(mp_window window);
|
||||
oc_surface_data* oc_mtl_surface_create_for_window(oc_window window);
|
||||
|
||||
void* mg_mtl_surface_render_encoder(mg_surface surface);
|
||||
void* mg_mtl_surface_compute_encoder(mg_surface surface);
|
||||
void* mg_mtl_surface_layer(mg_surface surface);
|
||||
void* mg_mtl_surface_drawable(mg_surface surface);
|
||||
void* mg_mtl_surface_command_buffer(mg_surface surface);
|
||||
void* oc_mtl_surface_render_encoder(oc_surface surface);
|
||||
void* oc_mtl_surface_compute_encoder(oc_surface surface);
|
||||
void* oc_mtl_surface_layer(oc_surface surface);
|
||||
void* oc_mtl_surface_drawable(oc_surface surface);
|
||||
void* oc_mtl_surface_command_buffer(oc_surface surface);
|
||||
|
||||
#endif //__MTL_SURFACE_H_
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
#include<simd/simd.h>
|
||||
|
||||
#include"graphics_surface.h"
|
||||
#include"util/macro_helpers.h"
|
||||
#include"util/macros.h"
|
||||
#include"app/osx_app.h"
|
||||
|
||||
typedef struct mg_mtl_surface
|
||||
typedef struct oc_mtl_surface
|
||||
{
|
||||
mg_surface_data interface;
|
||||
oc_surface_data interface;
|
||||
|
||||
// permanent mtl resources
|
||||
id<MTLDevice> device;
|
||||
|
@ -28,11 +28,11 @@ typedef struct mg_mtl_surface
|
|||
id<CAMetalDrawable> drawable;
|
||||
id<MTLCommandBuffer> commandBuffer;
|
||||
|
||||
} mg_mtl_surface;
|
||||
} oc_mtl_surface;
|
||||
|
||||
void mg_mtl_surface_destroy(mg_surface_data* interface)
|
||||
void oc_mtl_surface_destroy(oc_surface_data* interface)
|
||||
{
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
oc_mtl_surface* surface = (oc_mtl_surface*)interface;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -48,10 +48,10 @@ void mg_mtl_surface_destroy(mg_surface_data* interface)
|
|||
[surface->mtlLayer release];
|
||||
[surface->device release];
|
||||
}
|
||||
//NOTE: we don't use mp_layer_cleanup here, because the CAMetalLayer is taken care off by the surface itself
|
||||
//NOTE: we don't use oc_layer_cleanup here, because the CAMetalLayer is taken care off by the surface itself
|
||||
}
|
||||
|
||||
void mg_mtl_surface_acquire_command_buffer(mg_mtl_surface* surface)
|
||||
void oc_mtl_surface_acquire_command_buffer(oc_mtl_surface* surface)
|
||||
{
|
||||
if(surface->commandBuffer == nil)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ void mg_mtl_surface_acquire_command_buffer(mg_mtl_surface* surface)
|
|||
}
|
||||
}
|
||||
|
||||
void mg_mtl_surface_acquire_drawable(mg_mtl_surface* surface)
|
||||
void oc_mtl_surface_acquire_drawable(oc_mtl_surface* surface)
|
||||
{@autoreleasepool{
|
||||
/*WARN(martin):
|
||||
//TODO: we should stop trying to render if we detect that the app is in the background
|
||||
|
@ -81,15 +81,15 @@ void mg_mtl_surface_acquire_drawable(mg_mtl_surface* surface)
|
|||
}
|
||||
}}
|
||||
|
||||
void mg_mtl_surface_prepare(mg_surface_data* interface)
|
||||
void oc_mtl_surface_prepare(oc_surface_data* interface)
|
||||
{
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
mg_mtl_surface_acquire_command_buffer(surface);
|
||||
oc_mtl_surface* surface = (oc_mtl_surface*)interface;
|
||||
oc_mtl_surface_acquire_command_buffer(surface);
|
||||
}
|
||||
|
||||
void mg_mtl_surface_present(mg_surface_data* interface)
|
||||
void oc_mtl_surface_present(oc_surface_data* interface)
|
||||
{
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
oc_mtl_surface* surface = (oc_mtl_surface*)interface;
|
||||
@autoreleasepool
|
||||
{
|
||||
if(surface->commandBuffer != nil)
|
||||
|
@ -107,9 +107,9 @@ void mg_mtl_surface_present(mg_surface_data* interface)
|
|||
}
|
||||
}
|
||||
|
||||
void mg_mtl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
void oc_mtl_surface_swap_interval(oc_surface_data* interface, int swap)
|
||||
{
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
oc_mtl_surface* surface = (oc_mtl_surface*)interface;
|
||||
@autoreleasepool
|
||||
{
|
||||
[surface->mtlLayer setDisplaySyncEnabled: (swap ? YES : NO)];
|
||||
|
@ -117,11 +117,11 @@ void mg_mtl_surface_swap_interval(mg_surface_data* interface, int swap)
|
|||
}
|
||||
|
||||
/*
|
||||
void mg_mtl_surface_set_frame(mg_surface_data* interface, mp_rect frame)
|
||||
void oc_mtl_surface_set_frame(oc_surface_data* interface, oc_rect frame)
|
||||
{
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
mg_osx_surface_set_frame(interface, frame);
|
||||
vec2 scale = mg_osx_surface_contents_scaling(interface);
|
||||
oc_mtl_surface* surface = (oc_mtl_surface*)interface;
|
||||
oc_osx_surface_set_frame(interface, frame);
|
||||
oc_vec2 scale = oc_osx_surface_contents_scaling(interface);
|
||||
|
||||
CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}};
|
||||
|
||||
|
@ -140,29 +140,29 @@ void mg_mtl_surface_set_frame(mg_surface_data* interface, mp_rect frame)
|
|||
|
||||
|
||||
//TODO fix that according to real scaling, depending on the monitor settings
|
||||
static const f32 MG_MTL_SURFACE_CONTENTS_SCALING = 2;
|
||||
static const f32 OC_MTL_SURFACE_CONTENTS_SCALING = 2;
|
||||
|
||||
//NOTE: max frames in flight (n frames being queued on the GPU while we're working on the n+1 frame).
|
||||
// for triple buffering, there's 2 frames being queued on the GPU while we're working on the 3rd frame
|
||||
static const int MG_MTL_MAX_FRAMES_IN_FLIGHT = 2;
|
||||
static const int OC_MTL_MAX_FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
mg_surface_data* mg_mtl_surface_create_for_window(mp_window window)
|
||||
oc_surface_data* oc_mtl_surface_create_for_window(oc_window window)
|
||||
{
|
||||
mg_mtl_surface* surface = 0;
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
oc_mtl_surface* surface = 0;
|
||||
oc_window_data* windowData = oc_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
surface = (mg_mtl_surface*)malloc(sizeof(mg_mtl_surface));
|
||||
surface = (oc_mtl_surface*)malloc(sizeof(oc_mtl_surface));
|
||||
|
||||
mg_surface_init_for_window((mg_surface_data*)surface, windowData);
|
||||
oc_surface_init_for_window((oc_surface_data*)surface, windowData);
|
||||
|
||||
//NOTE(martin): setup interface functions
|
||||
surface->interface.api = MG_METAL;
|
||||
surface->interface.destroy = mg_mtl_surface_destroy;
|
||||
surface->interface.prepare = mg_mtl_surface_prepare;
|
||||
surface->interface.api = OC_METAL;
|
||||
surface->interface.destroy = oc_mtl_surface_destroy;
|
||||
surface->interface.prepare = oc_mtl_surface_prepare;
|
||||
surface->interface.deselect = 0;
|
||||
surface->interface.present = mg_mtl_surface_present;
|
||||
surface->interface.swapInterval = mg_mtl_surface_swap_interval;
|
||||
surface->interface.present = oc_mtl_surface_present;
|
||||
surface->interface.swapInterval = oc_mtl_surface_swap_interval;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -191,7 +191,7 @@ mg_surface_data* mg_mtl_surface_create_for_window(mp_window window)
|
|||
}
|
||||
if(surface->device == nil)
|
||||
{
|
||||
log_warning("Couldn't select a discrete GPU, using first available device\n");
|
||||
oc_log_warning("Couldn't select a discrete GPU, using first available device\n");
|
||||
surface->device = devices[0];
|
||||
}
|
||||
|
||||
|
@ -212,10 +212,10 @@ mg_surface_data* mg_mtl_surface_create_for_window(mp_window window)
|
|||
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
|
||||
CGSize size = frame.size;
|
||||
surface->mtlLayer.frame = (CGRect){{0, 0}, size};
|
||||
size.width *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||
size.height *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||
size.width *= OC_MTL_SURFACE_CONTENTS_SCALING;
|
||||
size.height *= OC_MTL_SURFACE_CONTENTS_SCALING;
|
||||
surface->mtlLayer.drawableSize = size;
|
||||
surface->mtlLayer.contentsScale = MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||
surface->mtlLayer.contentsScale = OC_MTL_SURFACE_CONTENTS_SCALING;
|
||||
|
||||
surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
|
||||
|
@ -234,15 +234,15 @@ mg_surface_data* mg_mtl_surface_create_for_window(mp_window window)
|
|||
surface->commandBuffer = nil;
|
||||
}
|
||||
}
|
||||
return((mg_surface_data*)surface);
|
||||
return((oc_surface_data*)surface);
|
||||
}
|
||||
|
||||
void* mg_mtl_surface_layer(mg_surface surface)
|
||||
void* oc_mtl_surface_layer(oc_surface surface)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->api == MG_METAL)
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->api == OC_METAL)
|
||||
{
|
||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
||||
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
|
||||
return(mtlSurface->mtlLayer);
|
||||
}
|
||||
else
|
||||
|
@ -251,13 +251,13 @@ void* mg_mtl_surface_layer(mg_surface surface)
|
|||
}
|
||||
}
|
||||
|
||||
void* mg_mtl_surface_drawable(mg_surface surface)
|
||||
void* oc_mtl_surface_drawable(oc_surface surface)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->api == MG_METAL)
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->api == OC_METAL)
|
||||
{
|
||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
||||
mg_mtl_surface_acquire_drawable(mtlSurface);
|
||||
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
|
||||
oc_mtl_surface_acquire_drawable(mtlSurface);
|
||||
return(mtlSurface->drawable);
|
||||
}
|
||||
else
|
||||
|
@ -266,13 +266,13 @@ void* mg_mtl_surface_drawable(mg_surface surface)
|
|||
}
|
||||
}
|
||||
|
||||
void* mg_mtl_surface_command_buffer(mg_surface surface)
|
||||
void* oc_mtl_surface_command_buffer(oc_surface surface)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->api == MG_METAL)
|
||||
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->api == OC_METAL)
|
||||
{
|
||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
||||
mg_mtl_surface_acquire_command_buffer(mtlSurface);
|
||||
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
|
||||
oc_mtl_surface_acquire_command_buffer(mtlSurface);
|
||||
return(mtlSurface->commandBuffer);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -11,42 +11,42 @@
|
|||
#include"gl_loader.h"
|
||||
|
||||
#include<GL/wglext.h>
|
||||
#include"util/macro_helpers.h"
|
||||
#include"util/macros.h"
|
||||
|
||||
#define WGL_PROC_LIST \
|
||||
WGL_PROC(WGLCHOOSEPIXELFORMATARB, wglChoosePixelFormatARB) \
|
||||
WGL_PROC(WGLCREATECONTEXTATTRIBSARB, wglCreateContextAttribsARB) \
|
||||
WGL_PROC(WGLMAKECONTEXTCURRENTARB, wglMakeContextCurrentARB) \
|
||||
WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT) \
|
||||
#define OC_WGL_PROC_LIST \
|
||||
OC_WGL_PROC(WGLCHOOSEPIXELFORMATARB, wglChoosePixelFormatARB) \
|
||||
OC_WGL_PROC(WGLCREATECONTEXTATTRIBSARB, wglCreateContextAttribsARB) \
|
||||
OC_WGL_PROC(WGLMAKECONTEXTCURRENTARB, wglMakeContextCurrentARB) \
|
||||
OC_WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT) \
|
||||
|
||||
//NOTE: wgl function pointers declarations
|
||||
|
||||
#define WGL_PROC(type, name) _cat3_(PFN, type, PROC) name = 0;
|
||||
WGL_PROC_LIST
|
||||
#undef WGL_PROC
|
||||
#define OC_WGL_PROC(type, name) OC_CAT3(PFN, type, PROC) name = 0;
|
||||
OC_WGL_PROC_LIST
|
||||
#undef OC_WGL_PROC
|
||||
|
||||
//NOTE: wgl loader
|
||||
|
||||
typedef struct wgl_dummy_context
|
||||
typedef struct oc_wgl_dummy_context
|
||||
{
|
||||
bool init;
|
||||
HWND hWnd;
|
||||
HDC hDC;
|
||||
HGLRC glContext;
|
||||
|
||||
} wgl_dummy_context;
|
||||
} oc_wgl_dummy_context;
|
||||
|
||||
static wgl_dummy_context __mgWGLDummyContext = {0};
|
||||
static oc_wgl_dummy_context oc_wglDummyContext = {0};
|
||||
|
||||
static void wgl_init()
|
||||
static void oc_wgl_init()
|
||||
{
|
||||
if(!__mgWGLDummyContext.init)
|
||||
if(!oc_wglDummyContext.init)
|
||||
{
|
||||
//NOTE: create a dummy window
|
||||
WNDCLASS windowClass = {.style = CS_OWNDC,
|
||||
.lpfnWndProc = DefWindowProc,
|
||||
.hInstance = GetModuleHandleW(NULL),
|
||||
.lpszClassName = "wgl_helper_window_class",
|
||||
.lpszClassName = "oc_wgl_helper_window_class",
|
||||
.hCursor = LoadCursor(0, IDC_ARROW)};
|
||||
|
||||
if(!RegisterClass(&windowClass))
|
||||
|
@ -55,18 +55,18 @@ static void wgl_init()
|
|||
goto quit;
|
||||
}
|
||||
|
||||
__mgWGLDummyContext.hWnd = CreateWindow("wgl_helper_window_class",
|
||||
oc_wglDummyContext.hWnd = CreateWindow("oc_wgl_helper_window_class",
|
||||
"dummy",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
0, 0, 100, 100,
|
||||
0, 0, windowClass.hInstance, 0);
|
||||
|
||||
if(!__mgWGLDummyContext.hWnd)
|
||||
if(!oc_wglDummyContext.hWnd)
|
||||
{
|
||||
//TODO: error
|
||||
goto quit;
|
||||
}
|
||||
__mgWGLDummyContext.hDC = GetDC(__mgWGLDummyContext.hWnd);
|
||||
oc_wglDummyContext.hDC = GetDC(oc_wglDummyContext.hWnd);
|
||||
|
||||
PIXELFORMATDESCRIPTOR pixelFormatDesc =
|
||||
{
|
||||
|
@ -88,44 +88,44 @@ static void wgl_init()
|
|||
0, 0, 0
|
||||
};
|
||||
|
||||
int pixelFormat = ChoosePixelFormat(__mgWGLDummyContext.hDC, &pixelFormatDesc);
|
||||
SetPixelFormat(__mgWGLDummyContext.hDC, pixelFormat, &pixelFormatDesc);
|
||||
int pixelFormat = ChoosePixelFormat(oc_wglDummyContext.hDC, &pixelFormatDesc);
|
||||
SetPixelFormat(oc_wglDummyContext.hDC, pixelFormat, &pixelFormatDesc);
|
||||
|
||||
__mgWGLDummyContext.glContext = wglCreateContext(__mgWGLDummyContext.hDC);
|
||||
wglMakeCurrent(__mgWGLDummyContext.hDC, __mgWGLDummyContext.glContext);
|
||||
oc_wglDummyContext.glContext = wglCreateContext(oc_wglDummyContext.hDC);
|
||||
wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext);
|
||||
|
||||
//NOTE(martin): now load WGL extension functions
|
||||
#define WGL_PROC(type, name) name = (_cat3_(PFN, type, PROC))wglGetProcAddress( #name );
|
||||
WGL_PROC_LIST
|
||||
#undef WGL_PROC
|
||||
#define OC_WGL_PROC(type, name) name = (OC_CAT3(PFN, type, PROC))wglGetProcAddress( #name );
|
||||
OC_WGL_PROC_LIST
|
||||
#undef OC_WGL_PROC
|
||||
|
||||
__mgWGLDummyContext.init = true;
|
||||
oc_wglDummyContext.init = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wglMakeCurrent(__mgWGLDummyContext.hDC, __mgWGLDummyContext.glContext);
|
||||
wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext);
|
||||
}
|
||||
quit:;
|
||||
}
|
||||
|
||||
#undef WGL_PROC_LIST
|
||||
#undef OC_WGL_PROC_LIST
|
||||
|
||||
|
||||
typedef struct mg_wgl_surface
|
||||
typedef struct oc_wgl_surface
|
||||
{
|
||||
mg_surface_data interface;
|
||||
oc_surface_data interface;
|
||||
|
||||
HDC hDC;
|
||||
HGLRC glContext;
|
||||
|
||||
//NOTE: this may be a bit wasteful to have one api struct per surface, but win32 docs says that loading procs
|
||||
// from different contexts might select different implementations (eg. depending on context version/pixel format)
|
||||
mg_gl_api api;
|
||||
} mg_wgl_surface;
|
||||
oc_gl_api api;
|
||||
} oc_wgl_surface;
|
||||
|
||||
void mg_wgl_surface_destroy(mg_surface_data* interface)
|
||||
void oc_wgl_surface_destroy(oc_surface_data* interface)
|
||||
{
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
oc_wgl_surface* surface = (oc_wgl_surface*)interface;
|
||||
|
||||
if(surface->glContext == wglGetCurrentContext())
|
||||
{
|
||||
|
@ -133,39 +133,39 @@ void mg_wgl_surface_destroy(mg_surface_data* interface)
|
|||
}
|
||||
wglDeleteContext(surface->glContext);
|
||||
|
||||
mg_surface_cleanup(interface);
|
||||
oc_surface_cleanup(interface);
|
||||
|
||||
free(surface);
|
||||
}
|
||||
|
||||
void mg_wgl_surface_prepare(mg_surface_data* interface)
|
||||
void oc_wgl_surface_prepare(oc_surface_data* interface)
|
||||
{
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
oc_wgl_surface* surface = (oc_wgl_surface*)interface;
|
||||
|
||||
wglMakeCurrent(surface->hDC, surface->glContext);
|
||||
mg_gl_select_api(&surface->api);
|
||||
oc_gl_select_api(&surface->api);
|
||||
}
|
||||
|
||||
void mg_wgl_surface_present(mg_surface_data* interface)
|
||||
void oc_wgl_surface_present(oc_surface_data* interface)
|
||||
{
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
oc_wgl_surface* surface = (oc_wgl_surface*)interface;
|
||||
|
||||
SwapBuffers(surface->hDC);
|
||||
}
|
||||
|
||||
void mg_wgl_surface_deselect(mg_surface_data* interface)
|
||||
void oc_wgl_surface_deselect(oc_surface_data* interface)
|
||||
{
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
mg_gl_deselect_api();
|
||||
oc_gl_deselect_api();
|
||||
}
|
||||
|
||||
void mg_wgl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
void oc_wgl_surface_swap_interval(oc_surface_data* interface, int swap)
|
||||
{
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
oc_wgl_surface* surface = (oc_wgl_surface*)interface;
|
||||
wglSwapIntervalEXT(swap);
|
||||
}
|
||||
|
||||
void* mg_wgl_get_proc(const char* name)
|
||||
void* oc_wgl_get_proc(const char* name)
|
||||
{
|
||||
void* p = wglGetProcAddress(name);
|
||||
if( p == 0
|
||||
|
@ -181,28 +181,28 @@ void* mg_wgl_get_proc(const char* name)
|
|||
return(p);
|
||||
}
|
||||
|
||||
mg_surface_data* mg_wgl_surface_create_for_window(mp_window window)
|
||||
oc_surface_data* oc_wgl_surface_create_for_window(oc_window window)
|
||||
{
|
||||
mg_wgl_surface* surface = 0;
|
||||
oc_wgl_surface* surface = 0;
|
||||
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
oc_window_data* windowData = oc_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
wgl_init();
|
||||
oc_wgl_init();
|
||||
|
||||
//NOTE: fill surface data and load api
|
||||
surface = malloc_type(mg_wgl_surface);
|
||||
surface = oc_malloc_type(oc_wgl_surface);
|
||||
if(surface)
|
||||
{
|
||||
memset(surface, 0, sizeof(mg_wgl_surface));
|
||||
mg_surface_init_for_window((mg_surface_data*)surface, windowData);
|
||||
memset(surface, 0, sizeof(oc_wgl_surface));
|
||||
oc_surface_init_for_window((oc_surface_data*)surface, windowData);
|
||||
|
||||
surface->interface.api = MG_GL;
|
||||
surface->interface.destroy = mg_wgl_surface_destroy;
|
||||
surface->interface.prepare = mg_wgl_surface_prepare;
|
||||
surface->interface.present = mg_wgl_surface_present;
|
||||
surface->interface.swapInterval = mg_wgl_surface_swap_interval;
|
||||
surface->interface.deselect = mg_wgl_surface_deselect;
|
||||
surface->interface.api = OC_GL;
|
||||
surface->interface.destroy = oc_wgl_surface_destroy;
|
||||
surface->interface.prepare = oc_wgl_surface_prepare;
|
||||
surface->interface.present = oc_wgl_surface_present;
|
||||
surface->interface.swapInterval = oc_wgl_surface_swap_interval;
|
||||
surface->interface.deselect = oc_wgl_surface_deselect;
|
||||
|
||||
surface->hDC = GetDC(surface->interface.layer.hWnd);
|
||||
|
||||
|
@ -259,7 +259,7 @@ mg_surface_data* mg_wgl_surface_create_for_window(mp_window window)
|
|||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
0};
|
||||
|
||||
surface->glContext = wglCreateContextAttribsARB(surface->hDC, __mgWGLDummyContext.glContext, contextAttrs);
|
||||
surface->glContext = wglCreateContextAttribsARB(surface->hDC, oc_wglDummyContext.glContext, contextAttrs);
|
||||
|
||||
if(!surface->glContext)
|
||||
{
|
||||
|
@ -271,8 +271,8 @@ mg_surface_data* mg_wgl_surface_create_for_window(mp_window window)
|
|||
//NOTE: make gl context current and load api
|
||||
wglMakeCurrent(surface->hDC, surface->glContext);
|
||||
wglSwapIntervalEXT(1);
|
||||
mg_gl_load_gl44(&surface->api, mg_wgl_get_proc);
|
||||
oc_gl_load_gl44(&surface->api, oc_wgl_get_proc);
|
||||
}
|
||||
}
|
||||
return((mg_surface_data*)surface);
|
||||
return((oc_surface_data*)surface);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
|
||||
#include"graphics_surface.h"
|
||||
|
||||
mg_surface_data* mg_wgl_surface_create_for_window(mp_window window);
|
||||
oc_surface_data* oc_wgl_surface_create_for_window(oc_window window);
|
||||
|
||||
#endif // __WIN32_GL_SURFACE_H_
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifdef NDEBUG
|
||||
#define assert(x) (void)0
|
||||
#else
|
||||
#define assert(x) ASSERT(x)
|
||||
#define assert(x) OC_ASSERT(x)
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define abort(...) ORCA_ABORT(__VA_ARGS__)
|
||||
#define abort(...) OC_ABORT(__VA_ARGS__)
|
||||
|
||||
int abs (int);
|
||||
|
||||
|
|
21
src/orca.c
21
src/orca.c
|
@ -12,7 +12,7 @@
|
|||
//---------------------------------------------------------------
|
||||
#include"platform/platform.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#if OC_PLATFORM_WINDOWS
|
||||
#include"platform/native_debug.c"
|
||||
#include"platform/win32_memory.c"
|
||||
#include"platform/win32_clock.c"
|
||||
|
@ -21,7 +21,7 @@
|
|||
#include"platform/win32_io.c"
|
||||
#include"platform/win32_thread.c"
|
||||
//TODO
|
||||
#elif PLATFORM_MACOS
|
||||
#elif OC_PLATFORM_MACOS
|
||||
#include"platform/native_debug.c"
|
||||
#include"platform/unix_memory.c"
|
||||
#include"platform/osx_clock.c"
|
||||
|
@ -43,7 +43,7 @@
|
|||
#include"platform/unix_rng.c"
|
||||
#include"platform/posix_socket.c"
|
||||
*/
|
||||
#elif PLATFORM_ORCA
|
||||
#elif OC_PLATFORM_ORCA
|
||||
#include"platform/orca_debug.c"
|
||||
#include"platform/orca_clock.c"
|
||||
#include"platform/orca_memory.c"
|
||||
|
@ -62,35 +62,36 @@
|
|||
#include"util/utf8.c"
|
||||
#include"util/hash.c"
|
||||
#include"util/ringbuffer.c"
|
||||
#include"util/algebra.c"
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// app/graphics layer
|
||||
//---------------------------------------------------------------
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#if OC_PLATFORM_WINDOWS
|
||||
#include"app/win32_app.c"
|
||||
#include"graphics/graphics_common.c"
|
||||
#include"graphics/graphics_surface.c"
|
||||
|
||||
#if MG_COMPILE_GL || MG_COMPILE_GLES
|
||||
#if OC_COMPILE_GL || OC_COMPILE_GLES
|
||||
#include"graphics/gl_loader.c"
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_GL
|
||||
#if OC_COMPILE_GL
|
||||
#include"graphics/wgl_surface.c"
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_CANVAS
|
||||
#if OC_COMPILE_CANVAS
|
||||
#include"graphics/gl_canvas.c"
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_GLES
|
||||
#if OC_COMPILE_GLES
|
||||
#include"graphics/egl_surface.c"
|
||||
#endif
|
||||
|
||||
#elif PLATFORM_MACOS
|
||||
#elif OC_PLATFORM_MACOS
|
||||
//NOTE: macos application layer and graphics backends are defined in orca.m
|
||||
#elif PLATFORM_ORCA
|
||||
#elif OC_PLATFORM_ORCA
|
||||
#include"app/orca_app.c"
|
||||
#include"graphics/graphics_common.c"
|
||||
#include"graphics/orca_surface_stubs.c"
|
||||
|
|
15
src/orca.h
15
src/orca.h
|
@ -10,39 +10,40 @@
|
|||
#define __ORCA_H_
|
||||
|
||||
#include"util/typedefs.h"
|
||||
#include"util/macro_helpers.h"
|
||||
#include"util/macros.h"
|
||||
#include"util/debug.h"
|
||||
#include"util/lists.h"
|
||||
#include"util/memory.h"
|
||||
#include"util/strings.h"
|
||||
#include"util/utf8.h"
|
||||
#include"util/hash.h"
|
||||
#include"util/algebra.h"
|
||||
|
||||
#include"platform/platform.h"
|
||||
#include"platform/platform_clock.h"
|
||||
#include"platform/platform_path.h"
|
||||
#include"platform/platform_io.h"
|
||||
|
||||
#if !defined(PLATFORM_ORCA) || !(PLATFORM_ORCA)
|
||||
#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
|
||||
#include"platform/platform_thread.h"
|
||||
#endif
|
||||
|
||||
#include"app/mp_app.h"
|
||||
#include"app/app.h"
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// graphics
|
||||
//----------------------------------------------------------------
|
||||
#include"graphics/graphics.h"
|
||||
|
||||
#if PLATFORM_ORCA
|
||||
#if OC_PLATFORM_ORCA
|
||||
//TODO: maybe make this conditional
|
||||
#include"graphics/orca_gl31.h"
|
||||
|
||||
mg_surface mg_surface_canvas();
|
||||
mg_surface mg_surface_gles();
|
||||
oc_surface oc_surface_canvas();
|
||||
oc_surface oc_surface_gles();
|
||||
|
||||
#else
|
||||
#ifdef MG_INCLUDE_GL_API
|
||||
#ifdef OC_INCLUDE_GL_API
|
||||
#include"graphics/gl_api.h"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
#include"graphics/graphics_common.c"
|
||||
#include"graphics/graphics_surface.c"
|
||||
|
||||
#if MG_COMPILE_METAL
|
||||
#if OC_COMPILE_METAL
|
||||
#include"graphics/mtl_surface.m"
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_CANVAS
|
||||
#if OC_COMPILE_CANVAS
|
||||
#include"graphics/mtl_renderer.m"
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_GLES
|
||||
#if OC_COMPILE_GLES
|
||||
#include"graphics/gl_loader.c"
|
||||
#include"graphics/egl_surface.c"
|
||||
#endif
|
||||
|
|
|
@ -1,193 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: linux_clock.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 20/04/2020
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include<math.h> //fabs()
|
||||
#include<time.h>
|
||||
#include<sys/time.h> // gettimeofday()
|
||||
|
||||
#include<sys/types.h>
|
||||
#include<sys/sysctl.h>
|
||||
|
||||
#include<unistd.h> // nanosleep()
|
||||
|
||||
#include"platform_rng.h"
|
||||
#include"platform_clock.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
//TODO(martin): measure the actual values of these constants
|
||||
const f64 SYSTEM_FUZZ = 25e-9, // minimum time to read the clock (s)
|
||||
SYSTEM_TICK = 25e-9; // minimum step between two clock readings (s)
|
||||
|
||||
static u64 __initialTimestamp__ = 0;
|
||||
static u64 __initialMonotonicNanoseconds__ = 0;
|
||||
|
||||
static inline u64 LinuxGetMonotonicNanoseconds()
|
||||
{
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
//WARN(martin): do not multiply ts.tv_sec directly (implicit conversion will overflow)
|
||||
u64 r = ts.tv_sec;
|
||||
r *= 1000000000;
|
||||
r += ts.tv_nsec;
|
||||
return(r);
|
||||
}
|
||||
|
||||
static inline u64 LinuxGetUptimeNanoseconds()
|
||||
{
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
//WARN(martin): do not multiply ts.tv_sec directly (implicit conversion will overflow)
|
||||
u64 r = ts.tv_sec;
|
||||
r *= 1000000000;
|
||||
r += ts.tv_nsec;
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
void ClockSystemInit()
|
||||
{
|
||||
//NOTE(martin): we don't know of a widely supported way of getting the boot time on linux, so
|
||||
// we fallback to our second best choice, which is taking an initial timestamp and
|
||||
// the initial monotonic time now
|
||||
|
||||
timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
__initialMonotonicNanoseconds__ = LinuxGetMonotonicNanoseconds();
|
||||
|
||||
//NOTE(martin): convert boot date to timestamp
|
||||
__initialTimestamp__ = (((u64)tv.tv_sec + JAN_1970) << 32)
|
||||
+ (u64)(tv.tv_usec * 1e-6 * TIMESTAMPS_PER_SECOND);
|
||||
|
||||
//TODO(martin): maybe get a state vector for exclusive clock usage ?
|
||||
RandomSeedFromDevice();
|
||||
}
|
||||
|
||||
fx_timestamp ClockGetTimestamp(clock_kind clock)
|
||||
{
|
||||
fx_timestamp ts = {0};
|
||||
switch(clock)
|
||||
{
|
||||
case SYS_CLOCK_MONOTONIC:
|
||||
{
|
||||
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
||||
u64 noff = LinuxGetMonotonicNanoseconds() - __initialMonotonicNanoseconds__;
|
||||
u64 foff = (u64)(noff * 1e-9 * TIMESTAMPS_PER_SECOND);
|
||||
ts.ts = __initialTimestamp__ + foff;
|
||||
} break;
|
||||
|
||||
case SYS_CLOCK_UPTIME:
|
||||
{
|
||||
//TODO(martin): maybe we should warn that this date is inconsistent after a sleep ?
|
||||
//NOTE(martin): compute uptime offset and add it to bootup timestamp
|
||||
u64 noff = LinuxGetUptimeNanoseconds() - __initialMonotonicNanoseconds__ ;
|
||||
u64 foff = (u64)(noff * 1e-9 * TIMESTAMPS_PER_SECOND);
|
||||
ts.ts = __initialTimestamp__ + foff;
|
||||
} break;
|
||||
|
||||
case SYS_CLOCK_DATE:
|
||||
{
|
||||
//NOTE(martin): get system date and convert it to a fixed-point timestamp
|
||||
timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
ts.ts = (((u64)tv.tv_sec + JAN_1970) << 32)
|
||||
+ (u64)(tv.tv_usec * 1e-6 * TIMESTAMPS_PER_SECOND);
|
||||
} break;
|
||||
}
|
||||
|
||||
//NOTE(martin): add a random fuzz between 0 and 1 times the system fuzz
|
||||
f64 fuzz = RandomU32()/(f64)(~(0UL)) * SYSTEM_FUZZ;
|
||||
fx_timediff tdfuzz = TimediffFromSeconds(fuzz);
|
||||
ts = TimestampAdd(ts, tdfuzz);
|
||||
//TODO(martin): ensure that we always return a value greater than the last value
|
||||
|
||||
return(ts);
|
||||
}
|
||||
|
||||
|
||||
f64 ClockGetTime(clock_kind clock)
|
||||
{
|
||||
switch(clock)
|
||||
{
|
||||
case SYS_CLOCK_MONOTONIC:
|
||||
{
|
||||
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
||||
u64 noff = LinuxGetMonotonicNanoseconds();
|
||||
return((f64)noff * 1e-9);
|
||||
} break;
|
||||
|
||||
case SYS_CLOCK_UPTIME:
|
||||
{
|
||||
//TODO(martin): maybe we should warn that this date is inconsistent after a sleep ?
|
||||
//NOTE(martin): compute uptime offset and add it to bootup timestamp
|
||||
u64 noff = LinuxGetUptimeNanoseconds();
|
||||
return((f64)noff * 1e-9);
|
||||
} break;
|
||||
|
||||
case SYS_CLOCK_DATE:
|
||||
{
|
||||
//TODO(martin): maybe warn about precision loss ?
|
||||
// could also change the epoch since we only promise to return a relative time
|
||||
//NOTE(martin): get system date and convert it to seconds
|
||||
timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
return(((f64)tv.tv_sec + JAN_1970) + ((f64)tv.tv_usec * 1e-6));
|
||||
} break;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void ClockSleepNanoseconds(u64 nanoseconds)
|
||||
{
|
||||
timespec rqtp;
|
||||
rqtp.tv_sec = nanoseconds / 1000000000;
|
||||
rqtp.tv_nsec = nanoseconds - rqtp.tv_sec * 1000000000;
|
||||
nanosleep(&rqtp, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//TODO: update these functions for various clocks besides monotonic
|
||||
////////////////////////////////////////////////////////////////////
|
||||
f64 ClockGetGranularity(clock_kind clock)
|
||||
{
|
||||
u64 minDiff = ~(0ULL);
|
||||
|
||||
const int GRANULARITY_NUM_ITERATION = 100000;
|
||||
for(int i=0; i<GRANULARITY_NUM_ITERATION; i++)
|
||||
{
|
||||
u64 a = LinuxGetMonotonicNanoseconds();
|
||||
u64 b = LinuxGetMonotonicNanoseconds();
|
||||
u64 diff = b - a;
|
||||
if(diff != 0 && diff < minDiff)
|
||||
{
|
||||
minDiff = diff;
|
||||
}
|
||||
}
|
||||
return(minDiff * 1e-9);
|
||||
}
|
||||
|
||||
f64 ClockGetMeanReadTime(clock_kind clock)
|
||||
{
|
||||
u64 start = LinuxGetMonotonicNanoseconds();
|
||||
fx_timestamp time;
|
||||
const int READ_NUM_ITERATION = 1000000;
|
||||
for(int i=0; i<READ_NUM_ITERATION; i++)
|
||||
{
|
||||
time = ClockGetTimestamp(SYS_CLOCK_MONOTONIC);
|
||||
}
|
||||
volatile u64 ts = time.ts;
|
||||
u64 end = LinuxGetMonotonicNanoseconds();
|
||||
f64 mean = (end - start)/(f64)READ_NUM_ITERATION;
|
||||
|
||||
return(mean * 1e-9);
|
||||
}
|
||||
|
||||
} // extern "C"
|
|
@ -7,49 +7,49 @@
|
|||
*****************************************************************/
|
||||
#include<stdio.h>
|
||||
|
||||
#include"app/mp_app.h"
|
||||
#include"app/app.h"
|
||||
#include"platform_debug.c"
|
||||
//----------------------------------------------------------------
|
||||
// Logging
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#if OC_PLATFORM_WINDOWS
|
||||
#include<io.h>
|
||||
#define isatty _isatty
|
||||
#define fileno _fileno
|
||||
#elif PLATFORM_MACOS || PLATFORM_LINUX
|
||||
#elif OC_PLATFORM_MACOS || PLATFORM_LINUX
|
||||
#include<unistd.h>
|
||||
#endif
|
||||
|
||||
static const char* LOG_HEADINGS[LOG_LEVEL_COUNT] = {
|
||||
static const char* OC_LOG_HEADINGS[OC_LOG_LEVEL_COUNT] = {
|
||||
"Error",
|
||||
"Warning",
|
||||
"Info"};
|
||||
|
||||
static const char* LOG_FORMATS[LOG_LEVEL_COUNT] = {
|
||||
static const char* OC_LOG_FORMATS[OC_LOG_LEVEL_COUNT] = {
|
||||
"\033[38;5;9m\033[1m",
|
||||
"\033[38;5;13m\033[1m",
|
||||
"\033[38;5;10m\033[1m"};
|
||||
|
||||
static const char* LOG_FORMAT_STOP = "\033[m";
|
||||
static const char* OC_LOG_FORMAT_STOP = "\033[m";
|
||||
|
||||
typedef struct log_output
|
||||
typedef struct oc_log_output
|
||||
{
|
||||
FILE* f;
|
||||
} log_output;
|
||||
} oc_log_output;
|
||||
|
||||
static log_output _logDefaultOutput = {0};
|
||||
log_output* LOG_DEFAULT_OUTPUT = &_logDefaultOutput;
|
||||
static oc_log_output oc_logDefaultOutput = {0};
|
||||
oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput;
|
||||
|
||||
void platform_log_push(log_output* output,
|
||||
log_level level,
|
||||
void platform_log_push(oc_log_output* output,
|
||||
oc_log_level level,
|
||||
const char* file,
|
||||
const char* function,
|
||||
int line,
|
||||
const char* fmt,
|
||||
va_list ap)
|
||||
{
|
||||
if(output == LOG_DEFAULT_OUTPUT && output->f == 0)
|
||||
if(output == OC_LOG_DEFAULT_OUTPUT && output->f == 0)
|
||||
{
|
||||
output->f = stdout;
|
||||
}
|
||||
|
@ -59,9 +59,9 @@ void platform_log_push(log_output* output,
|
|||
{
|
||||
fprintf(output->f,
|
||||
"%s%s:%s %s() in %s:%i: ",
|
||||
LOG_FORMATS[level],
|
||||
LOG_HEADINGS[level],
|
||||
LOG_FORMAT_STOP,
|
||||
OC_LOG_FORMATS[level],
|
||||
OC_LOG_HEADINGS[level],
|
||||
OC_LOG_FORMAT_STOP,
|
||||
function,
|
||||
file,
|
||||
line);
|
||||
|
@ -70,7 +70,7 @@ void platform_log_push(log_output* output,
|
|||
{
|
||||
fprintf(output->f,
|
||||
"%s: %s() in %s:%i: ",
|
||||
LOG_HEADINGS[level],
|
||||
OC_LOG_HEADINGS[level],
|
||||
function,
|
||||
file,
|
||||
line);
|
||||
|
@ -82,16 +82,16 @@ void platform_log_push(log_output* output,
|
|||
// Assert/Abort
|
||||
//----------------------------------------------------------------
|
||||
|
||||
_Noreturn void orca_abort(const char* file, const char* function, int line, const char* fmt, ...)
|
||||
_Noreturn void oc_abort_ext(const char* file, const char* function, int line, const char* fmt, ...)
|
||||
{
|
||||
mem_arena* scratch = mem_scratch();
|
||||
oc_arena* scratch = oc_scratch();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str8 note = str8_pushfv(scratch, fmt, ap);
|
||||
oc_str8 note = oc_str8_pushfv(scratch, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
str8 msg = str8_pushf(scratch,
|
||||
oc_str8 msg = oc_str8_pushf(scratch,
|
||||
"Fatal error in function %s() in file \"%s\", line %i:\n%.*s\n",
|
||||
function,
|
||||
file,
|
||||
|
@ -99,38 +99,40 @@ _Noreturn void orca_abort(const char* file, const char* function, int line, cons
|
|||
(int)note.len,
|
||||
note.ptr);
|
||||
|
||||
const char* msgCStr = str8_to_cstring(scratch, msg);
|
||||
log_error(msgCStr);
|
||||
oc_log_error(msg.ptr);
|
||||
|
||||
const char* options[] = {"OK"};
|
||||
mp_alert_popup("Fatal Error", msgCStr, 1, options);
|
||||
oc_str8_list options = {0};
|
||||
oc_str8_list_push(scratch, &options, OC_STR8("OK"));
|
||||
|
||||
oc_alert_popup(OC_STR8("Fatal Error"), msg, options);
|
||||
|
||||
//TODO: could terminate more gracefully?
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
_Noreturn void orca_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...)
|
||||
_Noreturn void oc_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...)
|
||||
{
|
||||
mem_arena* scratch = mem_scratch();
|
||||
oc_arena* scratch = oc_scratch();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str8 note = str8_pushfv(scratch, fmt, ap);
|
||||
oc_str8 note = oc_str8_pushfv(scratch, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
str8 msg = str8_pushf(scratch,
|
||||
oc_str8 msg = oc_str8_pushf(scratch,
|
||||
"Assertion failed in function %s() in file \"%s\", line %i:\n%s\nNote: %.*s\n",
|
||||
function,
|
||||
file,
|
||||
line,
|
||||
src,
|
||||
str8_ip(note));
|
||||
oc_str8_ip(note));
|
||||
|
||||
const char* msgCStr = str8_to_cstring(scratch, msg);
|
||||
log_error(msgCStr);
|
||||
oc_log_error(msg.ptr);
|
||||
|
||||
const char* options[] = {"OK"};
|
||||
mp_alert_popup("Assertion Failed", msgCStr, 1, options);
|
||||
oc_str8_list options = {0};
|
||||
oc_str8_list_push(scratch, &options, OC_STR8("OK"));
|
||||
|
||||
oc_alert_popup(OC_STR8("Assertion Failed"), msg, options);
|
||||
|
||||
//TODO: could terminate more gracefully?
|
||||
exit(-1);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include"util/typedefs.h"
|
||||
#include"platform_clock.h"
|
||||
|
||||
f64 ORCA_IMPORT(mp_get_time)(mp_clock_kind clock);
|
||||
f64 ORCA_IMPORT(oc_clock_time)(oc_clock_kind clock);
|
||||
|
|
|
@ -15,18 +15,18 @@
|
|||
// stb sprintf callback and user struct
|
||||
//----------------------------------------------------------------
|
||||
|
||||
typedef struct orca_stbsp_context
|
||||
typedef struct oc_stbsp_context
|
||||
{
|
||||
mem_arena* arena;
|
||||
str8_list list;
|
||||
} orca_stbsp_context;
|
||||
oc_arena* arena;
|
||||
oc_str8_list list;
|
||||
} oc_stbsp_context;
|
||||
|
||||
char* orca_stbsp_callback(char const* buf, void* user, int len)
|
||||
char* oc_stbsp_callback(char const* buf, void* user, int len)
|
||||
{
|
||||
orca_stbsp_context* ctx = (orca_stbsp_context*)user;
|
||||
oc_stbsp_context* ctx = (oc_stbsp_context*)user;
|
||||
|
||||
str8 string = str8_push_buffer(ctx->arena, len, (char*)buf);
|
||||
str8_list_push(ctx->arena, &ctx->list, string);
|
||||
oc_str8 string = oc_str8_push_buffer(ctx->arena, len, (char*)buf);
|
||||
oc_str8_list_push(ctx->arena, &ctx->list, string);
|
||||
|
||||
return((char*)buf);
|
||||
}
|
||||
|
@ -39,18 +39,18 @@ typedef enum
|
|||
{
|
||||
ORCA_LOG_OUTPUT_CONSOLE,
|
||||
ORCA_LOG_OUTPUT_FILE
|
||||
} orca_log_output_kind;
|
||||
} oc_log_output_kind;
|
||||
|
||||
typedef struct log_output
|
||||
typedef struct oc_log_output
|
||||
{
|
||||
orca_log_output_kind kind;
|
||||
oc_log_output_kind kind;
|
||||
//TODO: file output
|
||||
} log_output;
|
||||
} oc_log_output;
|
||||
|
||||
static log_output _logDefaultOutput = {.kind = ORCA_LOG_OUTPUT_CONSOLE};
|
||||
log_output* LOG_DEFAULT_OUTPUT = &_logDefaultOutput;
|
||||
static oc_log_output oc_logDefaultOutput = {.kind = ORCA_LOG_OUTPUT_CONSOLE};
|
||||
oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput;
|
||||
|
||||
void ORCA_IMPORT(orca_log)(log_level level,
|
||||
void ORCA_IMPORT(oc_runtime_log)(oc_log_level level,
|
||||
int fileLen,
|
||||
const char* file,
|
||||
int functionLen,
|
||||
|
@ -59,42 +59,42 @@ void ORCA_IMPORT(orca_log)(log_level level,
|
|||
int msgLen,
|
||||
const char* msg);
|
||||
|
||||
void platform_log_push(log_output* output,
|
||||
log_level level,
|
||||
void platform_log_push(oc_log_output* output,
|
||||
oc_log_level level,
|
||||
const char* file,
|
||||
const char* function,
|
||||
int line,
|
||||
const char* fmt,
|
||||
va_list ap)
|
||||
{
|
||||
mem_arena* scratch = mem_scratch();
|
||||
mem_arena_scope tmp = mem_arena_scope_begin(scratch);
|
||||
oc_arena* scratch = oc_scratch();
|
||||
oc_arena_scope tmp = oc_arena_scope_begin(scratch);
|
||||
|
||||
orca_stbsp_context ctx = {.arena = scratch,
|
||||
oc_stbsp_context ctx = {.arena = scratch,
|
||||
.list = {0}};
|
||||
|
||||
char buf[STB_SPRINTF_MIN];
|
||||
stbsp_vsprintfcb(orca_stbsp_callback, &ctx, buf, fmt, ap);
|
||||
stbsp_vsprintfcb(oc_stbsp_callback, &ctx, buf, fmt, ap);
|
||||
|
||||
str8 string = str8_list_join(scratch, ctx.list);
|
||||
oc_str8 string = oc_str8_list_join(scratch, ctx.list);
|
||||
|
||||
orca_log(level, strlen(file), file, strlen(function), function, line, str8_ip(string));
|
||||
oc_runtime_log(level, strlen(file), file, strlen(function), function, line, oc_str8_ip(string));
|
||||
|
||||
mem_arena_scope_end(tmp);
|
||||
oc_arena_scope_end(tmp);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Assert/Abort
|
||||
//----------------------------------------------------------------
|
||||
|
||||
_Noreturn void ORCA_IMPORT(orca_runtime_abort)(const char* file, const char* function, int line, const char* msg);
|
||||
_Noreturn void ORCA_IMPORT(orca_runtime_assert_fail)(const char* file, const char* function, int line, const char* src, const char* msg);
|
||||
_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_abort(const char* file, const char* function, int line, const char* fmt, ...)
|
||||
_Noreturn void oc_abort_ext(const char* file, const char* function, int line, const char* fmt, ...)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
|
||||
orca_stbsp_context ctx = {
|
||||
oc_stbsp_context ctx = {
|
||||
.arena = scratch.arena,
|
||||
.list = {0}
|
||||
};
|
||||
|
@ -103,22 +103,22 @@ _Noreturn void orca_abort(const char* file, const char* function, int line, cons
|
|||
va_start(ap, fmt);
|
||||
|
||||
char buf[STB_SPRINTF_MIN];
|
||||
stbsp_vsprintfcb(orca_stbsp_callback, &ctx, buf, fmt, ap);
|
||||
stbsp_vsprintfcb(oc_stbsp_callback, &ctx, buf, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
str8 msg = str8_list_join(scratch.arena, ctx.list);
|
||||
oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list);
|
||||
|
||||
orca_runtime_abort(file, function, line, msg.ptr);
|
||||
oc_runtime_abort_ext(file, function, line, msg.ptr);
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
}
|
||||
|
||||
_Noreturn void orca_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...)
|
||||
_Noreturn void oc_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
|
||||
orca_stbsp_context ctx = {
|
||||
oc_stbsp_context ctx = {
|
||||
.arena = scratch.arena,
|
||||
.list = {0}
|
||||
};
|
||||
|
@ -127,13 +127,13 @@ _Noreturn void orca_assert_fail(const char* file, const char* function, int line
|
|||
va_start(ap, fmt);
|
||||
|
||||
char buf[STB_SPRINTF_MIN];
|
||||
stbsp_vsprintfcb(orca_stbsp_callback, &ctx, buf, fmt, ap);
|
||||
stbsp_vsprintfcb(oc_stbsp_callback, &ctx, buf, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
str8 msg = str8_list_join(scratch.arena, ctx.list);
|
||||
oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list);
|
||||
|
||||
orca_runtime_assert_fail(file, function, line, src, msg.ptr);
|
||||
oc_runtime_assert_fail(file, function, line, src, msg.ptr);
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#define LACKS_UNISTD_H
|
||||
#define LACKS_SYS_PARAM_H
|
||||
|
||||
extern void* orca_mem_grow(u64 size);
|
||||
#define MORECORE orca_mem_grow
|
||||
extern void* oc_mem_grow(u64 size);
|
||||
#define MORECORE oc_mem_grow
|
||||
#define MORECORE_CONTIGUOUS 0
|
||||
/*
|
||||
This is a version (aka dlmalloc) of malloc/free/realloc written by
|
||||
|
@ -5485,7 +5485,7 @@ History:
|
|||
* Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
|
||||
memory allocation routines
|
||||
* Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
|
||||
* Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
|
||||
* Use 'assert' rather than 'OC_ASSERT' in WIN32 code to conform to
|
||||
usage of 'assert' in non-WIN32 code
|
||||
* Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
|
||||
avoid infinite loop
|
||||
|
|
|
@ -8,24 +8,24 @@
|
|||
|
||||
#include"platform_memory.h"
|
||||
|
||||
void* ORCA_IMPORT(orca_mem_grow)(u64 size);
|
||||
void* ORCA_IMPORT(oc_mem_grow)(u64 size);
|
||||
|
||||
void* orca_mem_base_reserve(mem_base_allocator* context, u64 size)
|
||||
void* orca_oc_base_reserve(oc_base_allocator* context, u64 size)
|
||||
{
|
||||
return(orca_mem_grow(size));
|
||||
return(oc_mem_grow(size));
|
||||
}
|
||||
|
||||
void orca_mem_base_nop(mem_base_allocator* context, void* ptr, u64 size) {}
|
||||
void orca_oc_base_nop(oc_base_allocator* context, void* ptr, u64 size) {}
|
||||
|
||||
mem_base_allocator* mem_base_allocator_default()
|
||||
oc_base_allocator* oc_base_allocator_default()
|
||||
{
|
||||
static mem_base_allocator base = {0};
|
||||
static oc_base_allocator base = {0};
|
||||
if(base.reserve == 0)
|
||||
{
|
||||
base.reserve = orca_mem_base_reserve;
|
||||
base.commit = orca_mem_base_nop;
|
||||
base.decommit = orca_mem_base_nop;
|
||||
base.release = orca_mem_base_nop;
|
||||
base.reserve = orca_oc_base_reserve;
|
||||
base.commit = orca_oc_base_nop;
|
||||
base.decommit = orca_oc_base_nop;
|
||||
base.release = orca_oc_base_nop;
|
||||
}
|
||||
return(&base);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#include<sys/types.h>
|
||||
#include<sys/sysctl.h>
|
||||
|
||||
#include<unistd.h> // nanosleep()
|
||||
|
||||
#include"platform_clock.h"
|
||||
|
||||
|
||||
|
@ -27,8 +25,8 @@ typedef struct timeval timeval;
|
|||
typedef struct timespec timespec;
|
||||
|
||||
//TODO(martin): measure the actual values of these constants
|
||||
const f64 SYSTEM_FUZZ = 25e-9, // minimum time to read the clock (s)
|
||||
SYSTEM_TICK = 25e-9; // minimum step between two clock readings (s)
|
||||
const f64 OC_CLOCK_FUZZ = 25e-9, // minimum time to read the clock (s)
|
||||
OC_CLOCK_TICK = 25e-9; // minimum step between two clock readings (s)
|
||||
|
||||
static mach_timebase_info_data_t __machTimeBase__ = {1,1};
|
||||
static u64 __initialTimestamp__ = 0;
|
||||
|
@ -45,9 +43,9 @@ static inline u64 OSXGetUptimeNanoseconds()
|
|||
|
||||
static inline u64 OSXGetMonotonicNanoseconds()
|
||||
{
|
||||
//NOTE(martin): according to the documentation, MP_CLOCK_MONOTONIC increment monotonically
|
||||
// on systems where MP_CLOCK_MONOTONIC_RAW is present, we may want to use that instead,
|
||||
// because MP_CLOCK_MONOTONIC seems to be subject to frequency changes ?
|
||||
//NOTE(martin): according to the documentation, OC_CLOCK_MONOTONIC increment monotonically
|
||||
// on systems where OC_CLOCK_MONOTONIC_RAW is present, we may want to use that instead,
|
||||
// because OC_CLOCK_MONOTONIC seems to be subject to frequency changes ?
|
||||
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
||||
#ifndef CLOCK_MONOTONIC_RAW
|
||||
|
@ -65,7 +63,7 @@ static inline u64 OSXGetMonotonicNanoseconds()
|
|||
static const f64 CLK_TIMESTAMPS_PER_SECOND = 4294967296.; // 2^32 as a double
|
||||
static const u64 CLK_JAN_1970 = 2208988800ULL; // seconds from january 1900 to january 1970
|
||||
|
||||
void mp_clock_init()
|
||||
void oc_clock_init()
|
||||
{
|
||||
mach_timebase_info(&__machTimeBase__);
|
||||
|
||||
|
@ -78,7 +76,7 @@ void mp_clock_init()
|
|||
|
||||
if(sysctl(mib, 2, &tv, &size, 0, 0) == -1)
|
||||
{
|
||||
log_error("can't read boot time\n");
|
||||
oc_log_error("can't read boot time\n");
|
||||
}
|
||||
//NOTE(martin): convert boot date to timestamp
|
||||
__initialTimestamp__ = (((u64)tv.tv_sec + CLK_JAN_1970) << 32)
|
||||
|
@ -88,12 +86,12 @@ void mp_clock_init()
|
|||
//RandomSeedFromDevice();
|
||||
}
|
||||
|
||||
u64 mp_get_timestamp(mp_clock_kind clock)
|
||||
u64 oc_clock_timestamp(oc_clock_kind clock)
|
||||
{
|
||||
u64 ts = 0;
|
||||
switch(clock)
|
||||
{
|
||||
case MP_CLOCK_MONOTONIC:
|
||||
case OC_CLOCK_MONOTONIC:
|
||||
{
|
||||
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
||||
u64 noff = OSXGetMonotonicNanoseconds() ;
|
||||
|
@ -101,7 +99,7 @@ u64 mp_get_timestamp(mp_clock_kind clock)
|
|||
ts = __initialTimestamp__ + foff;
|
||||
} break;
|
||||
|
||||
case MP_CLOCK_UPTIME:
|
||||
case OC_CLOCK_UPTIME:
|
||||
{
|
||||
//TODO(martin): maybe we should warn that this date is inconsistent after a sleep ?
|
||||
//NOTE(martin): compute uptime offset and add it to bootup timestamp
|
||||
|
@ -110,7 +108,7 @@ u64 mp_get_timestamp(mp_clock_kind clock)
|
|||
ts = __initialTimestamp__ + foff;
|
||||
} break;
|
||||
|
||||
case MP_CLOCK_DATE:
|
||||
case OC_CLOCK_DATE:
|
||||
{
|
||||
//NOTE(martin): get system date and convert it to a fixed-point timestamp
|
||||
timeval tv;
|
||||
|
@ -123,7 +121,7 @@ u64 mp_get_timestamp(mp_clock_kind clock)
|
|||
/*
|
||||
//NOTE(martin): add a random fuzz between 0 and 1 times the system fuzz
|
||||
//TODO(martin): ensure that we always return a value greater than the last value
|
||||
f64 fuzz = RandomU32()/(f64)(~(0UL)) * SYSTEM_FUZZ;
|
||||
f64 fuzz = RandomU32()/(f64)(~(0UL)) * OC_CLOCK_FUZZ;
|
||||
ts_timediff tdfuzz = TimediffFromSeconds(fuzz);
|
||||
ts = TimestampAdd(ts, tdfuzz);
|
||||
*/
|
||||
|
@ -132,18 +130,18 @@ u64 mp_get_timestamp(mp_clock_kind clock)
|
|||
}
|
||||
|
||||
|
||||
f64 mp_get_time(mp_clock_kind clock)
|
||||
f64 oc_clock_time(oc_clock_kind clock)
|
||||
{
|
||||
switch(clock)
|
||||
{
|
||||
case MP_CLOCK_MONOTONIC:
|
||||
case OC_CLOCK_MONOTONIC:
|
||||
{
|
||||
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
||||
u64 noff = OSXGetMonotonicNanoseconds();
|
||||
return((f64)noff * 1e-9);
|
||||
} break;
|
||||
|
||||
case MP_CLOCK_UPTIME:
|
||||
case OC_CLOCK_UPTIME:
|
||||
{
|
||||
//TODO(martin): maybe we should warn that this date is inconsistent after a sleep ?
|
||||
//NOTE(martin): compute uptime offset and add it to bootup timestamp
|
||||
|
@ -151,7 +149,7 @@ f64 mp_get_time(mp_clock_kind clock)
|
|||
return((f64)noff * 1e-9);
|
||||
} break;
|
||||
|
||||
case MP_CLOCK_DATE:
|
||||
case OC_CLOCK_DATE:
|
||||
{
|
||||
//TODO(martin): maybe warn about precision loss ?
|
||||
// could also change the epoch since we only promise to return a relative time
|
||||
|
@ -162,11 +160,3 @@ f64 mp_get_time(mp_clock_kind clock)
|
|||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void mp_sleep_nanoseconds(u64 nanoseconds)
|
||||
{
|
||||
timespec rqtp;
|
||||
rqtp.tv_sec = nanoseconds / 1000000000;
|
||||
rqtp.tv_nsec = nanoseconds - rqtp.tv_sec * 1000000000;
|
||||
nanosleep(&rqtp, 0);
|
||||
}
|
||||
|
|
|
@ -12,33 +12,33 @@
|
|||
|
||||
#include"platform_path.c"
|
||||
|
||||
bool path_is_absolute(str8 path)
|
||||
bool oc_path_is_absolute(oc_str8 path)
|
||||
{
|
||||
return(path.len && (path.ptr[0] == '/'));
|
||||
}
|
||||
|
||||
str8 path_executable(mem_arena* arena)
|
||||
oc_str8 oc_path_executable(oc_arena* arena)
|
||||
{@autoreleasepool{
|
||||
str8 result = {};
|
||||
oc_str8 result = {};
|
||||
u32 size = 0;
|
||||
_NSGetExecutablePath(0, &size);
|
||||
result.len = size;
|
||||
result.ptr = mem_arena_alloc_array(arena, char, result.len+1);
|
||||
result.ptr = oc_arena_push_array(arena, char, result.len+1);
|
||||
_NSGetExecutablePath(result.ptr, &size);
|
||||
result.ptr[result.len] = '\0';
|
||||
return(result);
|
||||
}}
|
||||
|
||||
str8 path_canonical(mem_arena* arena, str8 path)
|
||||
oc_str8 oc_path_canonical(oc_arena* arena, oc_str8 path)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin_next(arena);
|
||||
char* pathCString = str8_to_cstring(scratch.arena, path);
|
||||
oc_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||
char* pathCString = oc_str8_to_cstring(scratch.arena, path);
|
||||
|
||||
char* real = realpath(pathCString, 0);
|
||||
str8 result = str8_push_cstring(arena, real);
|
||||
oc_str8 result = oc_str8_push_cstring(arena, real);
|
||||
|
||||
free(real);
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
|
|
@ -14,17 +14,17 @@
|
|||
// Compiler identification
|
||||
//-----------------------------------------------------------------
|
||||
#if defined(__clang__)
|
||||
#define COMPILER_CLANG 1
|
||||
#define OC_COMPILER_CLANG 1
|
||||
#if defined(__apple_build_version__)
|
||||
#define COMPILER_CLANG_APPLE 1
|
||||
#define OC_COMPILER_CLANG_APPLE 1
|
||||
#elif defined(_MSC_VER)
|
||||
#define COMPILER_CLANG_CL 1
|
||||
#define OC_COMPILER_CLANG_CL 1
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
#define COMPILER_CL 1
|
||||
#define OC_COMPILER_CL 1
|
||||
#elif defined(__GNUC__)
|
||||
#define COMPILER_GCC 1
|
||||
#define OC_COMPILER_GCC 1
|
||||
#else
|
||||
#error "Can't identify compiler"
|
||||
#endif
|
||||
|
@ -33,15 +33,15 @@
|
|||
// OS identification
|
||||
//-----------------------------------------------------------------
|
||||
#if defined(_WIN64)
|
||||
#define PLATFORM_WINDOWS 1
|
||||
#define OC_PLATFORM_WINDOWS 1
|
||||
#elif defined(_WIN32)
|
||||
#error "Unsupported OS (32bit only version of Windows)"
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#define PLATFORM_MACOS 1
|
||||
#define OC_PLATFORM_MACOS 1
|
||||
#elif defined(__gnu_linux__)
|
||||
#define PLATFORM_LINUX 1
|
||||
#elif defined(__ORCA__)
|
||||
#define PLATFORM_ORCA 1
|
||||
#define OC_PLATFORM_ORCA 1
|
||||
#else
|
||||
#error "Can't identify platform"
|
||||
#endif
|
||||
|
@ -49,29 +49,29 @@
|
|||
//-----------------------------------------------------------------
|
||||
// Architecture identification
|
||||
//-----------------------------------------------------------------
|
||||
#if defined(COMPILER_CL)
|
||||
#if defined(OC_COMPILER_CL)
|
||||
#if defined(_M_AMD64)
|
||||
#define ARCH_X64 1
|
||||
#define OC_ARCH_X64 1
|
||||
#elif defined(_M_I86)
|
||||
#define ARCH_X86 1
|
||||
#define OC_ARCH_X86 1
|
||||
#elif defined(_M_ARM64)
|
||||
#define ARCH_ARM64 1
|
||||
#define OC_ARCH_ARM64 1
|
||||
#elif defined(_M_ARM)
|
||||
#define ARCH_ARM32 1
|
||||
#define OC_ARCH_ARM32 1
|
||||
#else
|
||||
#error "Can't identify architecture"
|
||||
#endif
|
||||
#else
|
||||
#if defined(__x86_64__)
|
||||
#define ARCH_X64 1
|
||||
#define OC_ARCH_X64 1
|
||||
#elif defined(__i386__)
|
||||
#define ARCH_X86 1
|
||||
#define OC_ARCH_X86 1
|
||||
#elif defined(__arm__)
|
||||
#define ARCH_ARM32 1
|
||||
#define OC_ARCH_ARM32 1
|
||||
#elif defined(__aarch64__)
|
||||
#define ARCH_ARM64 1
|
||||
#define OC_ARCH_ARM64 1
|
||||
#elif defined(__ORCA__)
|
||||
#define ARCH_WASM 1
|
||||
#define OC_ARCH_WASM32 1
|
||||
#else
|
||||
#error "Can't identify architecture"
|
||||
#endif
|
||||
|
@ -80,28 +80,28 @@
|
|||
//-----------------------------------------------------------------
|
||||
// platform helper macros
|
||||
//-----------------------------------------------------------------
|
||||
#if defined(COMPILER_CL)
|
||||
#if defined(MP_BUILD_DLL)
|
||||
#define MP_API __declspec(dllexport)
|
||||
#if defined(OC_COMPILER_CL)
|
||||
#if defined(OC_BUILD_DLL)
|
||||
#define ORCA_API __declspec(dllexport)
|
||||
#else
|
||||
#define MP_API __declspec(dllimport)
|
||||
#define ORCA_API __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
|
||||
#define MP_API
|
||||
#elif defined(OC_COMPILER_GCC) || defined(OC_COMPILER_CLANG)
|
||||
#define ORCA_API
|
||||
#endif
|
||||
|
||||
#if PLATFORM_ORCA
|
||||
#define mp_thread_local // no tls (or threads) for now on wasm orca
|
||||
#elif defined(COMPILER_CL)
|
||||
#define mp_thread_local __declspec(thread)
|
||||
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
|
||||
#define mp_thread_local __thread
|
||||
#if OC_PLATFORM_ORCA
|
||||
#define oc_thread_local // no tls (or threads) for now on wasm orca
|
||||
#elif defined(OC_COMPILER_CL)
|
||||
#define oc_thread_local __declspec(thread)
|
||||
#elif defined(OC_COMPILER_GCC) || defined(OC_COMPILER_CLANG)
|
||||
#define oc_thread_local __thread
|
||||
#endif
|
||||
|
||||
#if PLATFORM_ORCA
|
||||
#if OC_PLATFORM_ORCA
|
||||
#define ORCA_IMPORT(f) __attribute__((import_name(#f))) f
|
||||
|
||||
#if COMPILER_CLANG
|
||||
#if OC_COMPILER_CLANG
|
||||
#define ORCA_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#error "Orca apps can only be compiled with clang for now"
|
||||
|
|
|
@ -17,15 +17,14 @@ extern "C" {
|
|||
#endif // __cplusplus
|
||||
|
||||
typedef enum {
|
||||
MP_CLOCK_MONOTONIC, // clock that increment monotonically
|
||||
MP_CLOCK_UPTIME, // clock that increment monotonically during uptime
|
||||
MP_CLOCK_DATE // clock that is driven by the platform time
|
||||
} mp_clock_kind;
|
||||
OC_CLOCK_MONOTONIC, // clock that increment monotonically
|
||||
OC_CLOCK_UPTIME, // clock that increment monotonically during uptime
|
||||
OC_CLOCK_DATE // clock that is driven by the platform time
|
||||
} oc_clock_kind;
|
||||
|
||||
MP_API void mp_clock_init(); // initialize the clock subsystem
|
||||
MP_API u64 mp_get_timestamp(mp_clock_kind clock);
|
||||
MP_API f64 mp_get_time(mp_clock_kind clock);
|
||||
MP_API void mp_sleep_nanoseconds(u64 nanoseconds); // sleep for a given number of nanoseconds
|
||||
ORCA_API void oc_clock_init(); // initialize the clock subsystem
|
||||
ORCA_API u64 oc_clock_timestamp(oc_clock_kind clock);
|
||||
ORCA_API f64 oc_clock_time(oc_clock_kind clock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -7,34 +7,34 @@
|
|||
*****************************************************************/
|
||||
#include"platform_debug.h"
|
||||
|
||||
typedef struct log_config
|
||||
typedef struct oc_log_config
|
||||
{
|
||||
log_output* output;
|
||||
log_level level;
|
||||
} log_config;
|
||||
oc_log_output* output;
|
||||
oc_log_level level;
|
||||
} oc_log_config;
|
||||
|
||||
//TODO: make default output a compile-time constant to avoid check in log_push()?
|
||||
static log_config __logConfig = {0, LOG_LEVEL_INFO};
|
||||
//TODO: make default output a compile-time constant to avoid check in oc_log_ext()?
|
||||
static oc_log_config __logConfig = {0, OC_LOG_LEVEL_INFO};
|
||||
|
||||
void log_set_output(log_output* output)
|
||||
void oc_log_set_output(oc_log_output* output)
|
||||
{
|
||||
__logConfig.output = output;
|
||||
}
|
||||
|
||||
void log_set_level(log_level level)
|
||||
void oc_log_set_level(oc_log_level level)
|
||||
{
|
||||
__logConfig.level = level;
|
||||
}
|
||||
|
||||
void platform_log_push(log_output* output,
|
||||
log_level level,
|
||||
void platform_log_push(oc_log_output* output,
|
||||
oc_log_level level,
|
||||
const char* file,
|
||||
const char* function,
|
||||
int line,
|
||||
const char* fmt,
|
||||
va_list ap);
|
||||
|
||||
void log_push(log_level level,
|
||||
void oc_log_ext(oc_log_level level,
|
||||
const char* function,
|
||||
const char* file,
|
||||
int line,
|
||||
|
@ -43,7 +43,7 @@ void log_push(log_level level,
|
|||
{
|
||||
if(!__logConfig.output)
|
||||
{
|
||||
__logConfig.output = LOG_DEFAULT_OUTPUT;
|
||||
__logConfig.output = OC_LOG_DEFAULT_OUTPUT;
|
||||
}
|
||||
|
||||
if(level <= __logConfig.level)
|
||||
|
|
|
@ -14,30 +14,30 @@
|
|||
// Assert / Abort
|
||||
//----------------------------------------------------------------
|
||||
|
||||
MP_API _Noreturn void orca_abort(const char* file, const char* function, int line, const char* fmt, ...);
|
||||
MP_API _Noreturn void orca_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...);
|
||||
ORCA_API _Noreturn void oc_abort_ext(const char* file, const char* function, int line, const char* fmt, ...);
|
||||
ORCA_API _Noreturn void oc_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...);
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Logging
|
||||
//----------------------------------------------------------------
|
||||
|
||||
typedef enum { LOG_LEVEL_ERROR,
|
||||
LOG_LEVEL_WARNING,
|
||||
LOG_LEVEL_INFO,
|
||||
LOG_LEVEL_COUNT } log_level;
|
||||
typedef enum { OC_LOG_LEVEL_ERROR,
|
||||
OC_LOG_LEVEL_WARNING,
|
||||
OC_LOG_LEVEL_INFO,
|
||||
OC_LOG_LEVEL_COUNT } oc_log_level;
|
||||
|
||||
typedef struct log_output log_output;
|
||||
typedef struct oc_log_output oc_log_output;
|
||||
|
||||
extern log_output* LOG_DEFAULT_OUTPUT;
|
||||
extern oc_log_output* OC_LOG_DEFAULT_OUTPUT;
|
||||
|
||||
MP_API void log_set_level(log_level level);
|
||||
MP_API void log_set_output(log_output* output);
|
||||
MP_API void log_push(log_level level,
|
||||
const char* function,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* fmt,
|
||||
...);
|
||||
ORCA_API void oc_log_set_level(oc_log_level level);
|
||||
ORCA_API void oc_log_set_output(oc_log_output* output);
|
||||
ORCA_API void oc_log_ext(oc_log_level level,
|
||||
const char* function,
|
||||
const char* file,
|
||||
int line,
|
||||
const char* fmt,
|
||||
...);
|
||||
|
||||
|
||||
#endif //__PLATFORM_DEBUG_H_
|
||||
|
|
|
@ -15,56 +15,56 @@
|
|||
// IO API
|
||||
//----------------------------------------------------------------
|
||||
|
||||
typedef struct { u64 h; } file_handle;
|
||||
typedef struct { u64 h; } oc_file;
|
||||
|
||||
typedef u16 file_open_flags;
|
||||
enum _file_open_flags
|
||||
typedef u16 oc_file_open_flags;
|
||||
enum oc_file_open_flags_enum
|
||||
{
|
||||
FILE_OPEN_NONE = 0,
|
||||
FILE_OPEN_APPEND = 1<<1,
|
||||
FILE_OPEN_TRUNCATE = 1<<2,
|
||||
FILE_OPEN_CREATE = 1<<3,
|
||||
OC_FILE_OPEN_NONE = 0,
|
||||
OC_FILE_OPEN_APPEND = 1<<1,
|
||||
OC_FILE_OPEN_TRUNCATE = 1<<2,
|
||||
OC_FILE_OPEN_CREATE = 1<<3,
|
||||
|
||||
FILE_OPEN_SYMLINK = 1<<4,
|
||||
FILE_OPEN_NO_FOLLOW = 1<<5,
|
||||
FILE_OPEN_RESTRICT = 1<<6,
|
||||
OC_FILE_OPEN_SYMLINK = 1<<4,
|
||||
OC_FILE_OPEN_NO_FOLLOW = 1<<5,
|
||||
OC_FILE_OPEN_RESTRICT = 1<<6,
|
||||
//...
|
||||
};
|
||||
|
||||
typedef u16 file_access_rights;
|
||||
enum _file_access_rights
|
||||
typedef u16 oc_file_access;
|
||||
enum oc_file_access_enum
|
||||
{
|
||||
FILE_ACCESS_NONE = 0,
|
||||
FILE_ACCESS_READ = 1<<1,
|
||||
FILE_ACCESS_WRITE = 1<<2,
|
||||
OC_FILE_ACCESS_NONE = 0,
|
||||
OC_FILE_ACCESS_READ = 1<<1,
|
||||
OC_FILE_ACCESS_WRITE = 1<<2,
|
||||
};
|
||||
|
||||
|
||||
typedef enum { FILE_SEEK_SET, FILE_SEEK_END, FILE_SEEK_CURRENT } file_whence;
|
||||
typedef enum { OC_FILE_SEEK_SET, OC_FILE_SEEK_END, OC_FILE_SEEK_CURRENT } oc_file_whence;
|
||||
|
||||
typedef u64 io_req_id;
|
||||
typedef u64 oc_io_req_id;
|
||||
|
||||
typedef u32 io_op;
|
||||
enum _io_op
|
||||
typedef u32 oc_io_op;
|
||||
enum oc_io_op_enum
|
||||
{
|
||||
IO_OP_OPEN_AT = 0,
|
||||
IO_OP_CLOSE,
|
||||
OC_IO_OPEN_AT = 0,
|
||||
OC_IO_CLOSE,
|
||||
|
||||
IO_OP_FSTAT,
|
||||
OC_IO_FSTAT,
|
||||
|
||||
IO_OP_SEEK,
|
||||
IO_OP_READ,
|
||||
IO_OP_WRITE,
|
||||
OC_IO_SEEK,
|
||||
OC_IO_READ,
|
||||
OC_IO_WRITE,
|
||||
|
||||
IO_OP_ERROR,
|
||||
OC_OC_IO_ERROR,
|
||||
//...
|
||||
};
|
||||
|
||||
typedef struct io_req
|
||||
typedef struct oc_io_req
|
||||
{
|
||||
io_req_id id;
|
||||
io_op op;
|
||||
file_handle handle;
|
||||
oc_io_req_id id;
|
||||
oc_io_op op;
|
||||
oc_file handle;
|
||||
|
||||
i64 offset;
|
||||
u64 size;
|
||||
|
@ -78,133 +78,133 @@ typedef struct io_req
|
|||
{
|
||||
struct
|
||||
{
|
||||
file_access_rights rights;
|
||||
file_open_flags flags;
|
||||
oc_file_access rights;
|
||||
oc_file_open_flags flags;
|
||||
} open;
|
||||
|
||||
file_whence whence;
|
||||
oc_file_whence whence;
|
||||
};
|
||||
|
||||
} io_req;
|
||||
} oc_io_req;
|
||||
|
||||
typedef i32 io_error;
|
||||
enum _io_error {
|
||||
IO_OK = 0,
|
||||
IO_ERR_UNKNOWN,
|
||||
IO_ERR_OP, // unsupported operation
|
||||
IO_ERR_HANDLE, // invalid handle
|
||||
IO_ERR_PREV, // previously had a fatal error (last error stored on handle)
|
||||
IO_ERR_ARG, // invalid argument or argument combination
|
||||
IO_ERR_PERM, // access denied
|
||||
IO_ERR_SPACE, // no space left
|
||||
IO_ERR_NO_ENTRY, // file or directory does not exist
|
||||
IO_ERR_EXISTS, // file already exists
|
||||
IO_ERR_NOT_DIR, // path element is not a directory
|
||||
IO_ERR_DIR, // attempted to write directory
|
||||
IO_ERR_MAX_FILES, // max open files reached
|
||||
IO_ERR_MAX_LINKS, // too many symbolic links in path
|
||||
IO_ERR_PATH_LENGTH, // path too long
|
||||
IO_ERR_FILE_SIZE, // file too big
|
||||
IO_ERR_OVERFLOW, // offset too big
|
||||
IO_ERR_NOT_READY, // no data ready to be read/written
|
||||
IO_ERR_MEM, // failed to allocate memory
|
||||
IO_ERR_INTERRUPT, // operation interrupted by a signal
|
||||
IO_ERR_PHYSICAL, // physical IO error
|
||||
IO_ERR_NO_DEVICE, // device not found
|
||||
IO_ERR_WALKOUT, // attempted to walk out of root directory
|
||||
typedef i32 oc_io_error;
|
||||
enum oc_io_error_enum {
|
||||
OC_IO_OK = 0,
|
||||
OC_IO_ERR_UNKNOWN,
|
||||
OC_IO_ERR_OP, // unsupported operation
|
||||
OC_IO_ERR_HANDLE, // invalid handle
|
||||
OC_IO_ERR_PREV, // previously had a fatal error (last error stored on handle)
|
||||
OC_IO_ERR_ARG, // invalid argument or argument combination
|
||||
OC_IO_ERR_PERM, // access denied
|
||||
OC_IO_ERR_SPACE, // no space left
|
||||
OC_IO_ERR_NO_ENTRY, // file or directory does not exist
|
||||
OC_IO_ERR_EXISTS, // file already exists
|
||||
OC_IO_ERR_NOT_DIR, // path element is not a directory
|
||||
OC_IO_ERR_DIR, // attempted to write directory
|
||||
OC_IO_ERR_MAX_FILES, // max open files reached
|
||||
OC_IO_ERR_MAX_LINKS, // too many symbolic links in path
|
||||
OC_IO_ERR_PATH_LENGTH, // path too long
|
||||
OC_IO_ERR_FILE_SIZE, // file too big
|
||||
OC_IO_ERR_OVERFLOW, // offset too big
|
||||
OC_IO_ERR_NOT_READY, // no data ready to be read/written
|
||||
OC_IO_ERR_MEM, // failed to allocate memory
|
||||
OC_IO_ERR_INTERRUPT, // operation interrupted by a signal
|
||||
OC_IO_ERR_PHYSICAL, // physical IO error
|
||||
OC_IO_ERR_NO_DEVICE, // device not found
|
||||
OC_IO_ERR_WALKOUT, // attempted to walk out of root directory
|
||||
|
||||
//...
|
||||
};
|
||||
|
||||
typedef struct io_cmp
|
||||
typedef struct oc_io_cmp
|
||||
{
|
||||
io_req_id id;
|
||||
io_error error;
|
||||
oc_io_req_id id;
|
||||
oc_io_error error;
|
||||
|
||||
union
|
||||
{
|
||||
i64 result;
|
||||
u64 size;
|
||||
i64 offset;
|
||||
file_handle handle;
|
||||
oc_file handle;
|
||||
//...
|
||||
};
|
||||
} io_cmp;
|
||||
} oc_io_cmp;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
//TODO: complete io queue api
|
||||
//----------------------------------------------------------------
|
||||
MP_API io_cmp io_wait_single_req(io_req* req);
|
||||
ORCA_API oc_io_cmp oc_io_wait_single_req(oc_io_req* req);
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// File IO wrapper API
|
||||
//----------------------------------------------------------------
|
||||
|
||||
MP_API file_handle file_handle_nil();
|
||||
MP_API bool file_handle_is_nil(file_handle handle);
|
||||
ORCA_API oc_file oc_file_nil();
|
||||
ORCA_API bool oc_file_is_nil(oc_file handle);
|
||||
|
||||
MP_API file_handle file_open(str8 path, file_access_rights rights, file_open_flags flags);
|
||||
MP_API file_handle file_open_at(file_handle dir, str8 path, file_access_rights rights, file_open_flags flags);
|
||||
MP_API void file_close(file_handle file);
|
||||
ORCA_API oc_file oc_file_open(oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
|
||||
ORCA_API oc_file oc_file_open_at(oc_file dir, oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
|
||||
ORCA_API void oc_file_close(oc_file file);
|
||||
|
||||
MP_API i64 file_pos(file_handle file);
|
||||
MP_API i64 file_seek(file_handle file, i64 offset, file_whence whence);
|
||||
ORCA_API i64 oc_file_pos(oc_file file);
|
||||
ORCA_API i64 oc_file_seek(oc_file file, i64 offset, oc_file_whence whence);
|
||||
|
||||
MP_API u64 file_write(file_handle file, u64 size, char* buffer);
|
||||
MP_API u64 file_read(file_handle file, u64 size, char* buffer);
|
||||
ORCA_API u64 oc_file_write(oc_file file, u64 size, char* buffer);
|
||||
ORCA_API u64 oc_file_read(oc_file file, u64 size, char* buffer);
|
||||
|
||||
MP_API io_error file_last_error(file_handle handle);
|
||||
ORCA_API oc_io_error oc_file_last_error(oc_file handle);
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// File System wrapper API
|
||||
//----------------------------------------------------------------
|
||||
|
||||
typedef enum file_type
|
||||
typedef enum oc_file_type
|
||||
{
|
||||
MP_FILE_UNKNOWN,
|
||||
MP_FILE_REGULAR,
|
||||
MP_FILE_DIRECTORY,
|
||||
MP_FILE_SYMLINK,
|
||||
MP_FILE_BLOCK,
|
||||
MP_FILE_CHARACTER,
|
||||
MP_FILE_FIFO,
|
||||
MP_FILE_SOCKET,
|
||||
OC_FILE_UNKNOWN,
|
||||
OC_FILE_REGULAR,
|
||||
OC_FILE_DIRECTORY,
|
||||
OC_FILE_SYMLINK,
|
||||
OC_FILE_BLOCK,
|
||||
OC_FILE_CHARACTER,
|
||||
OC_FILE_FIFO,
|
||||
OC_FILE_SOCKET,
|
||||
|
||||
} file_type;
|
||||
} oc_file_type;
|
||||
|
||||
typedef u16 file_perm;
|
||||
enum file_perm
|
||||
typedef u16 oc_file_perm;
|
||||
enum oc_file_perm
|
||||
{
|
||||
MP_FILE_OTHER_EXEC = 1<<0,
|
||||
MP_FILE_OTHER_WRITE = 1<<1,
|
||||
MP_FILE_OTHER_READ = 1<<2,
|
||||
OC_FILE_OTHER_EXEC = 1<<0,
|
||||
OC_FILE_OTHER_WRITE = 1<<1,
|
||||
OC_FILE_OTHER_READ = 1<<2,
|
||||
|
||||
MP_FILE_GROUP_EXEC = 1<<3,
|
||||
MP_FILE_GROUP_WRITE = 1<<4,
|
||||
MP_FILE_GROUP_READ = 1<<5,
|
||||
OC_FILE_GROUP_EXEC = 1<<3,
|
||||
OC_FILE_GROUP_WRITE = 1<<4,
|
||||
OC_FILE_GROUP_READ = 1<<5,
|
||||
|
||||
MP_FILE_OWNER_EXEC = 1<<6,
|
||||
MP_FILE_OWNER_WRITE = 1<<7,
|
||||
MP_FILE_OWNER_READ = 1<<8,
|
||||
OC_FILE_OWNER_EXEC = 1<<6,
|
||||
OC_FILE_OWNER_WRITE = 1<<7,
|
||||
OC_FILE_OWNER_READ = 1<<8,
|
||||
|
||||
MP_FILE_STICKY_BIT = 1<<9,
|
||||
MP_FILE_SET_GID = 1<<10,
|
||||
MP_FILE_SET_UID = 1<<11,
|
||||
OC_FILE_STICKY_BIT = 1<<9,
|
||||
OC_FILE_SET_GID = 1<<10,
|
||||
OC_FILE_SET_UID = 1<<11,
|
||||
};
|
||||
|
||||
typedef struct file_status
|
||||
typedef struct oc_file_status
|
||||
{
|
||||
u64 uid;
|
||||
file_type type;
|
||||
file_perm perm;
|
||||
oc_file_type type;
|
||||
oc_file_perm perm;
|
||||
u64 size;
|
||||
|
||||
//TODO times
|
||||
|
||||
} file_status;
|
||||
} oc_file_status;
|
||||
|
||||
MP_API file_status file_get_status(file_handle file);
|
||||
MP_API u64 file_size(file_handle file);
|
||||
ORCA_API oc_file_status oc_file_get_status(oc_file file);
|
||||
ORCA_API u64 oc_file_size(oc_file file);
|
||||
|
||||
//TODO: Complete as needed...
|
||||
|
||||
|
|
|
@ -11,112 +11,112 @@
|
|||
// File stream read/write API
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
file_handle file_handle_nil()
|
||||
oc_file oc_file_nil()
|
||||
{
|
||||
return((file_handle){0});
|
||||
return((oc_file){0});
|
||||
}
|
||||
|
||||
bool file_handle_is_nil(file_handle handle)
|
||||
bool oc_file_is_nil(oc_file handle)
|
||||
{
|
||||
return(handle.h == 0);
|
||||
}
|
||||
|
||||
file_handle file_open(str8 path, file_access_rights rights, file_open_flags flags)
|
||||
oc_file oc_file_open(oc_str8 path, oc_file_access rights, oc_file_open_flags flags)
|
||||
{
|
||||
io_req req = {.op = IO_OP_OPEN_AT,
|
||||
oc_io_req req = {.op = OC_IO_OPEN_AT,
|
||||
.size = path.len,
|
||||
.buffer = path.ptr,
|
||||
.open.rights = rights,
|
||||
.open.flags = flags };
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||
|
||||
//WARN: we always return a handle that can be queried for errors. Handles must be closed
|
||||
// even if there was an error when opening
|
||||
return(cmp.handle);
|
||||
}
|
||||
|
||||
file_handle file_open_at(file_handle dir, str8 path, file_access_rights rights, 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)
|
||||
{
|
||||
io_req req = {.op = IO_OP_OPEN_AT,
|
||||
oc_io_req req = {.op = OC_IO_OPEN_AT,
|
||||
.handle = dir,
|
||||
.size = path.len,
|
||||
.buffer = path.ptr,
|
||||
.open.rights = rights,
|
||||
.open.flags = flags,};
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||
return(cmp.handle);
|
||||
}
|
||||
|
||||
void file_close(file_handle file)
|
||||
void oc_file_close(oc_file file)
|
||||
{
|
||||
io_req req = {.op = IO_OP_CLOSE,
|
||||
oc_io_req req = {.op = OC_IO_CLOSE,
|
||||
.handle = file};
|
||||
io_wait_single_req(&req);
|
||||
oc_io_wait_single_req(&req);
|
||||
}
|
||||
|
||||
i64 file_seek(file_handle file, i64 offset, file_whence whence)
|
||||
i64 oc_file_seek(oc_file file, i64 offset, oc_file_whence whence)
|
||||
{
|
||||
io_req req = {.op = IO_OP_SEEK,
|
||||
oc_io_req req = {.op = OC_IO_SEEK,
|
||||
.handle = file,
|
||||
.offset = offset,
|
||||
.whence = whence};
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||
return(cmp.offset);
|
||||
}
|
||||
|
||||
i64 file_pos(file_handle file)
|
||||
i64 oc_file_pos(oc_file file)
|
||||
{
|
||||
return(file_seek(file, 0, FILE_SEEK_CURRENT));
|
||||
return(oc_file_seek(file, 0, OC_FILE_SEEK_CURRENT));
|
||||
}
|
||||
|
||||
u64 file_write(file_handle file, u64 size, char* buffer)
|
||||
u64 oc_file_write(oc_file file, u64 size, char* buffer)
|
||||
{
|
||||
io_req req = {.op = IO_OP_WRITE,
|
||||
oc_io_req req = {.op = OC_IO_WRITE,
|
||||
.handle = file,
|
||||
.size = size,
|
||||
.buffer = buffer};
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||
return(cmp.size);
|
||||
}
|
||||
|
||||
u64 file_read(file_handle file, u64 size, char* buffer)
|
||||
u64 oc_file_read(oc_file file, u64 size, char* buffer)
|
||||
{
|
||||
io_req req = {.op = IO_OP_READ,
|
||||
oc_io_req req = {.op = OC_IO_READ,
|
||||
.handle = file,
|
||||
.size = size,
|
||||
.buffer = buffer};
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||
return(cmp.size);
|
||||
}
|
||||
|
||||
io_error file_last_error(file_handle file)
|
||||
oc_io_error oc_file_last_error(oc_file file)
|
||||
{
|
||||
io_req req = {.op = IO_OP_ERROR,
|
||||
oc_io_req req = {.op = OC_OC_IO_ERROR,
|
||||
.handle = file};
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
return((io_error)cmp.result);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||
return((oc_io_error)cmp.result);
|
||||
}
|
||||
|
||||
file_status file_get_status(file_handle file)
|
||||
oc_file_status oc_file_get_status(oc_file file)
|
||||
{
|
||||
file_status status = {0};
|
||||
io_req req = {.op = IO_OP_FSTAT,
|
||||
oc_file_status status = {0};
|
||||
oc_io_req req = {.op = OC_IO_FSTAT,
|
||||
.handle = file,
|
||||
.size = sizeof(file_status),
|
||||
.size = sizeof(oc_file_status),
|
||||
.buffer = (char*)&status};
|
||||
|
||||
io_cmp cmp = io_wait_single_req(&req);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||
return(status);
|
||||
}
|
||||
|
||||
u64 file_size(file_handle file)
|
||||
u64 oc_file_size(oc_file file)
|
||||
{
|
||||
file_status status = file_get_status(file);
|
||||
oc_file_status status = oc_file_get_status(file);
|
||||
return(status.size);
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
#include"platform_io_internal.h"
|
||||
#include"platform_path.h"
|
||||
|
||||
file_table __globalFileTable = {0};
|
||||
oc_file_table oc_globalFileTable = {0};
|
||||
|
||||
file_slot* file_slot_alloc(file_table* table)
|
||||
oc_file_slot* oc_file_slot_alloc(oc_file_table* table)
|
||||
{
|
||||
file_slot* slot = list_pop_entry(&table->freeList, file_slot, freeListElt);
|
||||
if(!slot && table->nextSlot < ORCA_MAX_FILE_SLOTS)
|
||||
oc_file_slot* slot = oc_list_pop_entry(&table->freeList, oc_file_slot, freeListElt);
|
||||
if(!slot && table->nextSlot < OC_IO_MAX_FILE_SLOTS)
|
||||
{
|
||||
slot = &table->slots[table->nextSlot];
|
||||
slot->generation = 1;
|
||||
|
@ -22,36 +22,36 @@ file_slot* file_slot_alloc(file_table* table)
|
|||
}
|
||||
|
||||
u32 tmpGeneration = slot->generation;
|
||||
memset(slot, 0, sizeof(file_slot));
|
||||
memset(slot, 0, sizeof(oc_file_slot));
|
||||
slot->generation = tmpGeneration;
|
||||
|
||||
return(slot);
|
||||
}
|
||||
|
||||
void file_slot_recycle(file_table* table, file_slot* slot)
|
||||
void oc_file_slot_recycle(oc_file_table* table, oc_file_slot* slot)
|
||||
{
|
||||
slot->generation++;
|
||||
list_push(&table->freeList, &slot->freeListElt);
|
||||
oc_list_push(&table->freeList, &slot->freeListElt);
|
||||
}
|
||||
|
||||
file_handle file_handle_from_slot(file_table* table, file_slot* slot)
|
||||
oc_file oc_file_from_slot(oc_file_table* table, oc_file_slot* slot)
|
||||
{
|
||||
u64 index = slot - table->slots;
|
||||
u64 generation = slot->generation;
|
||||
file_handle handle = {.h = (generation<<32) | index };
|
||||
oc_file handle = {.h = (generation<<32) | index };
|
||||
return(handle);
|
||||
}
|
||||
|
||||
file_slot* file_slot_from_handle(file_table* table, file_handle handle)
|
||||
oc_file_slot* oc_file_slot_from_handle(oc_file_table* table, oc_file handle)
|
||||
{
|
||||
file_slot* slot = 0;
|
||||
oc_file_slot* slot = 0;
|
||||
|
||||
u64 index = handle.h & 0xffffffff;
|
||||
u64 generation = handle.h>>32;
|
||||
|
||||
if(index < table->nextSlot)
|
||||
{
|
||||
file_slot* candidate = &table->slots[index];
|
||||
oc_file_slot* candidate = &table->slots[index];
|
||||
if(candidate->generation == generation)
|
||||
{
|
||||
slot = candidate;
|
||||
|
@ -60,149 +60,149 @@ file_slot* file_slot_from_handle(file_table* table, file_handle handle)
|
|||
return(slot);
|
||||
}
|
||||
|
||||
io_cmp io_wait_single_req(io_req* req)
|
||||
oc_io_cmp oc_io_wait_single_req(oc_io_req* req)
|
||||
{
|
||||
return(io_wait_single_req_with_table(req, &__globalFileTable));
|
||||
return(oc_io_wait_single_req_with_table(req, &oc_globalFileTable));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// io common primitives
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
typedef struct io_open_restrict_context
|
||||
typedef struct oc_io_open_restrict_context
|
||||
{
|
||||
io_error error;
|
||||
oc_io_error error;
|
||||
u64 rootUID;
|
||||
io_file_desc rootFd;
|
||||
io_file_desc fd;
|
||||
oc_file_desc rootFd;
|
||||
oc_file_desc fd;
|
||||
|
||||
} io_open_restrict_context;
|
||||
} oc_io_open_restrict_context;
|
||||
|
||||
io_error io_open_restrict_enter(io_open_restrict_context* context, str8 name, file_access_rights accessRights, file_open_flags openFlags)
|
||||
oc_io_error oc_io_open_restrict_enter(oc_io_open_restrict_context* context, oc_str8 name, oc_file_access accessRights, oc_file_open_flags openFlags)
|
||||
{
|
||||
io_file_desc nextFd = io_raw_open_at(context->fd, name, accessRights, openFlags);
|
||||
if(io_file_desc_is_nil(nextFd))
|
||||
oc_file_desc nextFd = oc_io_raw_open_at(context->fd, name, accessRights, openFlags);
|
||||
if(oc_file_desc_is_nil(nextFd))
|
||||
{
|
||||
context->error = io_raw_last_error();
|
||||
context->error = oc_io_raw_last_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(context->fd != context->rootFd)
|
||||
{
|
||||
io_raw_close(context->fd);
|
||||
oc_io_raw_close(context->fd);
|
||||
}
|
||||
context->fd = nextFd;
|
||||
}
|
||||
return(context->error);
|
||||
}
|
||||
|
||||
typedef struct io_open_restrict_result
|
||||
typedef struct oc_io_open_restrict_result
|
||||
{
|
||||
io_error error;
|
||||
io_file_desc fd;
|
||||
} io_open_restrict_result;
|
||||
oc_io_error error;
|
||||
oc_file_desc fd;
|
||||
} oc_io_open_restrict_result;
|
||||
|
||||
|
||||
io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_access_rights accessRights, file_open_flags openFlags)
|
||||
oc_io_open_restrict_result oc_io_open_restrict(oc_file_desc dirFd, oc_str8 path, oc_file_access accessRights, oc_file_open_flags openFlags)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
|
||||
str8_list sep = {0};
|
||||
str8_list_push(scratch.arena, &sep, STR8("/"));
|
||||
str8_list_push(scratch.arena, &sep, STR8("\\"));
|
||||
str8_list pathElements = str8_split(scratch.arena, path, sep);
|
||||
oc_str8_list sep = {0};
|
||||
oc_str8_list_push(scratch.arena, &sep, OC_STR8("/"));
|
||||
oc_str8_list_push(scratch.arena, &sep, OC_STR8("\\"));
|
||||
oc_str8_list pathElements = oc_str8_split(scratch.arena, path, sep);
|
||||
|
||||
io_open_restrict_context context = {
|
||||
.error = IO_OK,
|
||||
oc_io_open_restrict_context context = {
|
||||
.error = OC_IO_OK,
|
||||
.rootFd = dirFd,
|
||||
.fd = dirFd,
|
||||
};
|
||||
|
||||
if(io_file_desc_is_nil(dirFd))
|
||||
if(oc_file_desc_is_nil(dirFd))
|
||||
{
|
||||
context.error = IO_ERR_HANDLE;
|
||||
context.error = OC_IO_ERR_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
file_status status;
|
||||
context.error = io_raw_fstat(dirFd, &status);
|
||||
oc_file_status status;
|
||||
context.error = oc_io_raw_fstat(dirFd, &status);
|
||||
context.rootUID = status.uid;
|
||||
}
|
||||
|
||||
if(context.error == IO_OK)
|
||||
if(context.error == OC_IO_OK)
|
||||
{
|
||||
for_list(&pathElements.list, elt, str8_elt, listElt)
|
||||
oc_list_for(&pathElements.list, elt, oc_str8_elt, listElt)
|
||||
{
|
||||
str8 name = elt->string;
|
||||
file_access_rights eltAccessRights = FILE_ACCESS_READ;
|
||||
file_open_flags eltOpenFlags = 0;
|
||||
oc_str8 name = elt->string;
|
||||
oc_file_access eltAccessRights = OC_FILE_ACCESS_READ;
|
||||
oc_file_open_flags eltOpenFlags = 0;
|
||||
|
||||
bool atLastElement = (&elt->listElt == list_last(&pathElements.list));
|
||||
bool atLastElement = (&elt->listElt == oc_list_last(&pathElements.list));
|
||||
if(atLastElement)
|
||||
{
|
||||
eltAccessRights = accessRights;
|
||||
eltOpenFlags = openFlags;
|
||||
}
|
||||
|
||||
if( !str8_cmp(name, STR8("."))
|
||||
if( !oc_str8_cmp(name, OC_STR8("."))
|
||||
&& !atLastElement)
|
||||
{
|
||||
//NOTE: if we're not at the last element we can just skip '.' elements
|
||||
continue;
|
||||
}
|
||||
else if(!str8_cmp(name, STR8("..")))
|
||||
else if(!oc_str8_cmp(name, OC_STR8("..")))
|
||||
{
|
||||
//NOTE: check that we don't escape root dir
|
||||
file_status status;
|
||||
context.error = io_raw_fstat(context.fd, &status);
|
||||
oc_file_status status;
|
||||
context.error = oc_io_raw_fstat(context.fd, &status);
|
||||
if(context.error)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if(status.uid == context.rootUID)
|
||||
{
|
||||
context.error = IO_ERR_WALKOUT;
|
||||
context.error = OC_IO_ERR_WALKOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(!io_raw_file_exists_at(context.fd, name, FILE_OPEN_SYMLINK))
|
||||
else if(!oc_io_raw_file_exists_at(context.fd, name, OC_FILE_OPEN_SYMLINK))
|
||||
{
|
||||
//NOTE: if the file doesn't exists, but we're at the last element and FILE_OPEN_CREATE
|
||||
// is set, we create the file. Otherwise it is a IO_ERROR_NO_ENTRY error.
|
||||
//NOTE: if the file doesn't exists, but we're at the last element and OC_FILE_OPEN_CREATE
|
||||
// is set, we create the file. Otherwise it is a OC_IO_ERROR_NO_ENTRY error.
|
||||
if( !atLastElement
|
||||
|| !(openFlags & FILE_OPEN_CREATE))
|
||||
|| !(openFlags & OC_FILE_OPEN_CREATE))
|
||||
{
|
||||
context.error = IO_ERR_NO_ENTRY;
|
||||
context.error = OC_IO_ERR_NO_ENTRY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//NOTE: if the file exists, we check the type of file
|
||||
file_status status = {0};
|
||||
context.error = io_raw_fstat_at(context.fd, name, FILE_OPEN_SYMLINK, &status);
|
||||
oc_file_status status = {0};
|
||||
context.error = oc_io_raw_fstat_at(context.fd, name, OC_FILE_OPEN_SYMLINK, &status);
|
||||
if(context.error)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(status.type == MP_FILE_REGULAR)
|
||||
if(status.type == OC_FILE_REGULAR)
|
||||
{
|
||||
if(!atLastElement)
|
||||
{
|
||||
context.error = IO_ERR_NOT_DIR;
|
||||
context.error = OC_IO_ERR_NOT_DIR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(status.type == MP_FILE_SYMLINK)
|
||||
else if(status.type == OC_FILE_SYMLINK)
|
||||
{
|
||||
//TODO - do we need a FILE_OPEN_NO_FOLLOW that fails if last element is a symlink?
|
||||
// - do we need a FILE_OPEN_NO_SYMLINKS that fails if _any_ element is a symlink?
|
||||
//TODO - do we need a OC_FILE_OPEN_NO_FOLLOW that fails if last element is a symlink?
|
||||
// - do we need a OC_FILE_OPEN_NO_SYMLINKS that fails if _any_ element is a symlink?
|
||||
|
||||
if( !atLastElement
|
||||
|| !(openFlags & FILE_OPEN_SYMLINK))
|
||||
|| !(openFlags & OC_FILE_OPEN_SYMLINK))
|
||||
{
|
||||
io_raw_read_link_result link = io_raw_read_link_at(scratch.arena, context.fd, name);
|
||||
oc_io_raw_read_link_result link = oc_io_raw_read_link_at(scratch.arena, context.fd, name);
|
||||
if(link.error)
|
||||
{
|
||||
context.error = link.error;
|
||||
|
@ -211,19 +211,19 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
|||
if(link.target.len == 0)
|
||||
{
|
||||
//NOTE: treat an empty target as a '.'
|
||||
link.target = STR8(".");
|
||||
link.target = OC_STR8(".");
|
||||
}
|
||||
else if(path_is_absolute(link.target))
|
||||
else if(oc_path_is_absolute(link.target))
|
||||
{
|
||||
context.error = IO_ERR_WALKOUT;
|
||||
context.error = OC_IO_ERR_WALKOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
str8_list linkElements = str8_split(scratch.arena, link.target, sep);
|
||||
if(!list_empty(&linkElements.list))
|
||||
oc_str8_list linkElements = oc_str8_split(scratch.arena, link.target, sep);
|
||||
if(!oc_list_empty(&linkElements.list))
|
||||
{
|
||||
//NOTE: insert linkElements into pathElements after elt
|
||||
list_elt* tmp = elt->listElt.next;
|
||||
oc_list_elt* tmp = elt->listElt.next;
|
||||
elt->listElt.next = linkElements.list.first;
|
||||
linkElements.list.last->next = tmp;
|
||||
if(!tmp)
|
||||
|
@ -234,63 +234,63 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if(status.type != MP_FILE_DIRECTORY)
|
||||
else if(status.type != OC_FILE_DIRECTORY)
|
||||
{
|
||||
context.error = IO_ERR_NOT_DIR;
|
||||
context.error = OC_IO_ERR_NOT_DIR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: if we arrive here, we have no errors and the correct flags are set,
|
||||
// so we can enter the element
|
||||
DEBUG_ASSERT(context.error == IO_OK);
|
||||
io_open_restrict_enter(&context, name, eltAccessRights, eltOpenFlags);
|
||||
OC_DEBUG_ASSERT(context.error == OC_IO_OK);
|
||||
oc_io_open_restrict_enter(&context, name, eltAccessRights, eltOpenFlags);
|
||||
}
|
||||
}
|
||||
|
||||
if(context.error && !io_file_desc_is_nil(context.fd))
|
||||
if(context.error && !oc_file_desc_is_nil(context.fd))
|
||||
{
|
||||
if(context.fd != context.rootFd)
|
||||
{
|
||||
io_raw_close(context.fd);
|
||||
oc_io_raw_close(context.fd);
|
||||
}
|
||||
context.fd = io_file_desc_nil();
|
||||
context.fd = oc_file_desc_nil();
|
||||
}
|
||||
|
||||
io_open_restrict_result result = {
|
||||
oc_io_open_restrict_result result = {
|
||||
.error = context.error,
|
||||
.fd = context.fd
|
||||
};
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
io_cmp io_open_at(file_slot* atSlot, io_req* req, file_table* table)
|
||||
oc_io_cmp oc_io_open_at(oc_file_slot* atSlot, oc_io_req* req, oc_file_table* table)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
file_slot* slot = file_slot_alloc(table);
|
||||
oc_file_slot* slot = oc_file_slot_alloc(table);
|
||||
if(!slot)
|
||||
{
|
||||
cmp.error = IO_ERR_MAX_FILES;
|
||||
cmp.error = OC_IO_ERR_MAX_FILES;
|
||||
cmp.result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->fd = io_file_desc_nil();
|
||||
cmp.handle = file_handle_from_slot(table, slot);
|
||||
slot->fd = oc_file_desc_nil();
|
||||
cmp.handle = oc_file_from_slot(table, slot);
|
||||
|
||||
|
||||
str8 path = str8_from_buffer(req->size, req->buffer);
|
||||
oc_str8 path = oc_str8_from_buffer(req->size, req->buffer);
|
||||
|
||||
if(!path.len)
|
||||
{
|
||||
slot->error = IO_ERR_ARG;
|
||||
slot->error = OC_IO_ERR_ARG;
|
||||
}
|
||||
else if(!atSlot && !file_handle_is_nil(req->handle))
|
||||
else if(!atSlot && !oc_file_is_nil(req->handle))
|
||||
{
|
||||
slot->error = IO_ERR_HANDLE;
|
||||
slot->error = OC_IO_ERR_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -302,34 +302,34 @@ io_cmp io_open_at(file_slot* atSlot, io_req* req, file_table* table)
|
|||
|
||||
if(slot->rights != req->open.rights)
|
||||
{
|
||||
slot->error = IO_ERR_PERM;
|
||||
slot->error = OC_IO_ERR_PERM;
|
||||
}
|
||||
else
|
||||
{
|
||||
io_file_desc dirFd = atSlot ? atSlot->fd : io_file_desc_nil();
|
||||
oc_file_desc dirFd = atSlot ? atSlot->fd : oc_file_desc_nil();
|
||||
|
||||
if(req->open.flags & FILE_OPEN_RESTRICT)
|
||||
if(req->open.flags & OC_FILE_OPEN_RESTRICT)
|
||||
{
|
||||
io_open_restrict_result res = io_open_restrict(dirFd, path, slot->rights, req->open.flags);
|
||||
oc_io_open_restrict_result res = oc_io_open_restrict(dirFd, path, slot->rights, req->open.flags);
|
||||
slot->error = res.error;
|
||||
slot->fd = res.fd;
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->fd = io_raw_open_at(dirFd, path, slot->rights, req->open.flags);
|
||||
if(io_file_desc_is_nil(slot->fd))
|
||||
slot->fd = oc_io_raw_open_at(dirFd, path, slot->rights, req->open.flags);
|
||||
if(oc_file_desc_is_nil(slot->fd))
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(slot->error == IO_OK)
|
||||
if(slot->error == OC_IO_OK)
|
||||
{
|
||||
file_status status;
|
||||
slot->error = io_raw_fstat(slot->fd, &status);
|
||||
if(slot->error == IO_OK)
|
||||
oc_file_status status;
|
||||
slot->error = oc_io_raw_fstat(slot->fd, &status);
|
||||
if(slot->error == OC_IO_OK)
|
||||
{
|
||||
slot->type = status.type;
|
||||
}
|
||||
|
|
|
@ -11,60 +11,60 @@
|
|||
#include"platform_io.h"
|
||||
#include"platform.h"
|
||||
|
||||
#if PLATFORM_MACOS || PLATFORM_LINUX
|
||||
typedef int io_file_desc;
|
||||
#elif PLATFORM_WINDOWS
|
||||
#if OC_PLATFORM_MACOS || PLATFORM_LINUX
|
||||
typedef int oc_file_desc;
|
||||
#elif OC_PLATFORM_WINDOWS
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include<windows.h>
|
||||
typedef HANDLE io_file_desc;
|
||||
typedef HANDLE oc_file_desc;
|
||||
#endif
|
||||
|
||||
typedef struct file_slot
|
||||
typedef struct oc_file_slot
|
||||
{
|
||||
u32 generation;
|
||||
io_error error;
|
||||
oc_io_error error;
|
||||
bool fatal;
|
||||
list_elt freeListElt;
|
||||
oc_list_elt freeListElt;
|
||||
|
||||
file_type type;
|
||||
file_access_rights rights;
|
||||
io_file_desc fd;
|
||||
oc_file_type type;
|
||||
oc_file_access rights;
|
||||
oc_file_desc fd;
|
||||
|
||||
} file_slot;
|
||||
} oc_file_slot;
|
||||
|
||||
enum
|
||||
{
|
||||
ORCA_MAX_FILE_SLOTS = 256,
|
||||
OC_IO_MAX_FILE_SLOTS = 256,
|
||||
};
|
||||
|
||||
typedef struct file_table
|
||||
typedef struct oc_file_table
|
||||
{
|
||||
file_slot slots[ORCA_MAX_FILE_SLOTS];
|
||||
oc_file_slot slots[OC_IO_MAX_FILE_SLOTS];
|
||||
u32 nextSlot;
|
||||
list_info freeList;
|
||||
} file_table;
|
||||
oc_list freeList;
|
||||
} oc_file_table;
|
||||
|
||||
file_slot* file_slot_alloc(file_table* table);
|
||||
void file_slot_recycle(file_table* table, file_slot* slot);
|
||||
file_handle file_handle_from_slot(file_table* table, file_slot* slot);
|
||||
file_slot* file_slot_from_handle(file_table* table, file_handle handle);
|
||||
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);
|
||||
|
||||
MP_API io_cmp io_wait_single_req_with_table(io_req* req, file_table* table);
|
||||
ORCA_API oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// raw io primitives
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
io_file_desc io_file_desc_nil();
|
||||
bool io_file_desc_is_nil(io_file_desc fd);
|
||||
oc_file_desc oc_file_desc_nil();
|
||||
bool oc_file_desc_is_nil(oc_file_desc fd);
|
||||
|
||||
/*WARN
|
||||
io_raw_xxx_at functions are similar to posix openat() regarding path resolution,
|
||||
oc_io_raw_xxx_at functions are similar to posix openat() regarding path resolution,
|
||||
but with some important differences:
|
||||
- If dirFd is a non-nil fd, path is considered relative to dirFd _even if it is an absolute path_
|
||||
- If dirFd is a non-nil fd, path is considered relative to dirFd _even if it is an absolute oc_path_
|
||||
- If dirFd is a nil fd, it is _ignored_ (i.e., path can be absolute, or relative to the current directory)
|
||||
|
||||
This means that:
|
||||
|
@ -72,19 +72,19 @@ bool io_file_desc_is_nil(io_file_desc fd);
|
|||
- we don't need a special handle value to use a path relative to the current working directory
|
||||
(we just pass a nil dirFd with a relative path)
|
||||
*/
|
||||
io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights accessRights, file_open_flags openFlags);
|
||||
void io_raw_close(io_file_desc fd);
|
||||
io_error io_raw_last_error();
|
||||
bool io_raw_file_exists_at(io_file_desc dirFd, str8 path, file_open_flags openFlags);
|
||||
io_error io_raw_fstat(io_file_desc fd, file_status* status);
|
||||
io_error io_raw_fstat_at(io_file_desc dirFd, str8 path, file_open_flags openFlags, file_status* status);
|
||||
oc_file_desc oc_io_raw_open_at(oc_file_desc dirFd, oc_str8 path, oc_file_access accessRights, oc_file_open_flags openFlags);
|
||||
void oc_io_raw_close(oc_file_desc fd);
|
||||
oc_io_error oc_io_raw_last_error();
|
||||
bool oc_io_raw_file_exists_at(oc_file_desc dirFd, oc_str8 path, oc_file_open_flags openFlags);
|
||||
oc_io_error oc_io_raw_fstat(oc_file_desc fd, oc_file_status* status);
|
||||
oc_io_error oc_io_raw_fstat_at(oc_file_desc dirFd, oc_str8 path, oc_file_open_flags openFlags, oc_file_status* status);
|
||||
|
||||
typedef struct io_raw_read_link_result
|
||||
typedef struct oc_io_raw_read_link_result
|
||||
{
|
||||
io_error error;
|
||||
str8 target;
|
||||
} io_raw_read_link_result;
|
||||
oc_io_error error;
|
||||
oc_str8 target;
|
||||
} oc_io_raw_read_link_result;
|
||||
|
||||
io_raw_read_link_result io_raw_read_link_at(mem_arena* arena, io_file_desc dirFd, str8 path);
|
||||
oc_io_raw_read_link_result oc_io_raw_read_link_at(oc_arena* arena, oc_file_desc dirFd, oc_str8 path);
|
||||
|
||||
#endif //__PLATFORM_IO_INTERNAL_H_
|
||||
|
|
|
@ -19,40 +19,34 @@ extern "C" {
|
|||
//--------------------------------------------------------------------------------
|
||||
//NOTE(martin): base allocator
|
||||
//--------------------------------------------------------------------------------
|
||||
typedef struct mem_base_allocator mem_base_allocator;
|
||||
typedef struct oc_base_allocator oc_base_allocator;
|
||||
|
||||
typedef void*(*mem_reserve_function)(mem_base_allocator* context, u64 size);
|
||||
typedef void(*mem_modify_function)(mem_base_allocator* context, void* ptr, u64 size);
|
||||
typedef void*(*oc_mem_reserve_function)(oc_base_allocator* context, u64 size);
|
||||
typedef void(*oc_mem_modify_function)(oc_base_allocator* context, void* ptr, u64 size);
|
||||
|
||||
typedef struct mem_base_allocator
|
||||
typedef struct oc_base_allocator
|
||||
{
|
||||
mem_reserve_function reserve;
|
||||
mem_modify_function commit;
|
||||
mem_modify_function decommit;
|
||||
mem_modify_function release;
|
||||
oc_mem_reserve_function reserve;
|
||||
oc_mem_modify_function commit;
|
||||
oc_mem_modify_function decommit;
|
||||
oc_mem_modify_function release;
|
||||
|
||||
} mem_base_allocator;
|
||||
} oc_base_allocator;
|
||||
|
||||
MP_API mem_base_allocator* mem_base_allocator_default();
|
||||
ORCA_API oc_base_allocator* oc_base_allocator_default();
|
||||
|
||||
#define mem_base_reserve(base, size) base->reserve(base, size)
|
||||
#define mem_base_commit(base, ptr, size) base->commit(base, ptr, size)
|
||||
#define mem_base_decommit(base, ptr, size) base->decommit(base, ptr, size)
|
||||
#define mem_base_release(base, ptr, size) base->release(base, ptr, size)
|
||||
#define oc_base_reserve(base, size) base->reserve(base, size)
|
||||
#define oc_base_commit(base, ptr, size) base->commit(base, ptr, size)
|
||||
#define oc_base_decommit(base, ptr, size) base->decommit(base, ptr, size)
|
||||
#define oc_base_release(base, ptr, size) base->release(base, ptr, size)
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
//NOTE(martin): malloc/free
|
||||
//--------------------------------------------------------------------------------
|
||||
#if PLATFORM_ORCA
|
||||
void* malloc(size_t size);
|
||||
void* realloc(void* ptr, size_t size);
|
||||
void free(void* ptr);
|
||||
#else
|
||||
#include<stdlib.h>
|
||||
#endif
|
||||
#include<stdlib.h>
|
||||
|
||||
#define malloc_type(type) ((type*)malloc(sizeof(type)))
|
||||
#define malloc_array(type, count) ((type*)malloc(sizeof(type)*count))
|
||||
#define oc_malloc_type(type) ((type*)malloc(sizeof(type)))
|
||||
#define oc_malloc_array(type, count) ((type*)malloc(sizeof(type)*count))
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
//NOTE(martin): memset / memcpy
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include"platform_path.h"
|
||||
|
||||
str8 path_slice_directory(str8 fullPath)
|
||||
oc_str8 oc_path_slice_directory(oc_str8 fullPath)
|
||||
{
|
||||
i64 lastSlashIndex = -1;
|
||||
|
||||
|
@ -20,11 +20,11 @@ str8 path_slice_directory(str8 fullPath)
|
|||
break;
|
||||
}
|
||||
}
|
||||
str8 directory = str8_slice(fullPath, 0, lastSlashIndex+1);
|
||||
oc_str8 directory = oc_str8_slice(fullPath, 0, lastSlashIndex+1);
|
||||
return(directory);
|
||||
}
|
||||
|
||||
str8 path_slice_filename(str8 fullPath)
|
||||
oc_str8 oc_path_slice_filename(oc_str8 fullPath)
|
||||
{
|
||||
i64 lastSlashIndex = -1;
|
||||
|
||||
|
@ -37,69 +37,69 @@ str8 path_slice_filename(str8 fullPath)
|
|||
}
|
||||
}
|
||||
|
||||
str8 basename = str8_slice(fullPath, lastSlashIndex+1, fullPath.len);
|
||||
oc_str8 basename = oc_str8_slice(fullPath, lastSlashIndex+1, fullPath.len);
|
||||
return(basename);
|
||||
}
|
||||
|
||||
str8_list path_split(mem_arena* arena, str8 path)
|
||||
oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path)
|
||||
{
|
||||
mem_arena_scope tmp = mem_scratch_begin_next(arena);
|
||||
str8_list split = {0};
|
||||
str8_list_push(tmp.arena, &split, STR8("/"));
|
||||
str8_list res = str8_split(arena, path, split);
|
||||
mem_scratch_end(tmp);
|
||||
oc_arena_scope tmp = oc_scratch_begin_next(arena);
|
||||
oc_str8_list split = {0};
|
||||
oc_str8_list_push(tmp.arena, &split, OC_STR8("/"));
|
||||
oc_str8_list res = oc_str8_split(arena, path, split);
|
||||
oc_scratch_end(tmp);
|
||||
return(res);
|
||||
}
|
||||
|
||||
str8 path_join(mem_arena* arena, str8_list elements)
|
||||
oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements)
|
||||
{
|
||||
//TODO: check if elements have ending/begining '/' ?
|
||||
str8 res = str8_list_collate(arena, elements, STR8("/"), STR8("/"), (str8){0});
|
||||
oc_str8 res = oc_str8_list_collate(arena, elements, OC_STR8("/"), OC_STR8("/"), (oc_str8){0});
|
||||
return(res);
|
||||
}
|
||||
|
||||
str8 path_append(mem_arena* arena, str8 parent, str8 relPath)
|
||||
oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath)
|
||||
{
|
||||
str8 result = {0};
|
||||
oc_str8 result = {0};
|
||||
|
||||
if(parent.len == 0)
|
||||
{
|
||||
result = str8_push_copy(arena, relPath);
|
||||
result = oc_str8_push_copy(arena, relPath);
|
||||
}
|
||||
else if(relPath.len == 0)
|
||||
{
|
||||
result = str8_push_copy(arena, parent);
|
||||
result = oc_str8_push_copy(arena, parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_arena_scope tmp = mem_scratch_begin_next(arena);
|
||||
oc_arena_scope tmp = oc_scratch_begin_next(arena);
|
||||
|
||||
str8_list list = {0};
|
||||
str8_list_push(tmp.arena, &list, parent);
|
||||
oc_str8_list list = {0};
|
||||
oc_str8_list_push(tmp.arena, &list, parent);
|
||||
if( (parent.ptr[parent.len-1] != '/')
|
||||
&&(relPath.ptr[relPath.len-1] != '/'))
|
||||
{
|
||||
str8_list_push(tmp.arena, &list, STR8("/"));
|
||||
oc_str8_list_push(tmp.arena, &list, OC_STR8("/"));
|
||||
}
|
||||
str8_list_push(tmp.arena, &list, relPath);
|
||||
oc_str8_list_push(tmp.arena, &list, relPath);
|
||||
|
||||
result = str8_list_join(arena, list);
|
||||
result = oc_str8_list_join(arena, list);
|
||||
|
||||
mem_scratch_end(tmp);
|
||||
oc_scratch_end(tmp);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
str8 path_executable_relative(mem_arena* arena, str8 relPath)
|
||||
oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath)
|
||||
{
|
||||
str8_list list = {0};
|
||||
mem_arena_scope scratch = mem_scratch_begin_next(arena);
|
||||
oc_str8_list list = {0};
|
||||
oc_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||
|
||||
str8 executablePath = path_executable(scratch.arena);
|
||||
str8 dirPath = path_slice_directory(executablePath);
|
||||
oc_str8 executablePath = oc_path_executable(scratch.arena);
|
||||
oc_str8 dirPath = oc_path_slice_directory(executablePath);
|
||||
|
||||
str8 path = path_append(arena, dirPath, relPath);
|
||||
oc_str8 path = oc_path_append(arena, dirPath, relPath);
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
return(path);
|
||||
}
|
||||
|
|
|
@ -16,18 +16,18 @@
|
|||
the string.
|
||||
*/
|
||||
|
||||
MP_API str8 path_slice_directory(str8 path);
|
||||
MP_API str8 path_slice_filename(str8 path);
|
||||
ORCA_API oc_str8 oc_path_slice_directory(oc_str8 path);
|
||||
ORCA_API oc_str8 oc_path_slice_filename(oc_str8 path);
|
||||
|
||||
MP_API str8_list path_split(mem_arena* arena, str8 path);
|
||||
MP_API str8 path_join(mem_arena* arena, str8_list elements);
|
||||
MP_API str8 path_append(mem_arena* arena, str8 parent, str8 relPath);
|
||||
ORCA_API oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path);
|
||||
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);
|
||||
|
||||
MP_API bool path_is_absolute(str8 path);
|
||||
MP_API str8 path_executable(mem_arena* arena);
|
||||
MP_API str8 path_canonical(mem_arena* arena, str8 path);
|
||||
ORCA_API bool oc_path_is_absolute(oc_str8 path);
|
||||
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 path_executable() and appends relPath
|
||||
MP_API str8 path_executable_relative(mem_arena* arena, str8 relPath);
|
||||
// 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 //__PLATFORM_PATH_H_
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: platform_rng.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 06/03/2020
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __PLATFORM_RANDOM_H_
|
||||
#define __PLATFORM_RANDOM_H_
|
||||
|
||||
#include"typedefs.h"
|
||||
|
||||
int RandomSeedFromDevice();
|
||||
u32 RandomU32();
|
||||
u64 RandomU64();
|
||||
|
||||
#endif //__PLATFORM_RANDOM_H_
|
|
@ -1,161 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: platform_socket.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 22/03/2019
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __PLATFORM_SOCKET_H_
|
||||
#define __PLATFORM_SOCKET_H_
|
||||
|
||||
#include<sys/time.h> // timeval
|
||||
#include"typedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#else
|
||||
typedef struct timeval timeval;
|
||||
#endif //__cplusplus
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Errors
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
//TODO(martin): extend these error codes
|
||||
const int SOCK_ERR_OK = 0,
|
||||
SOCK_ERR_UNKNOWN = -1,
|
||||
SOCK_ERR_ACCESS = -2,
|
||||
SOCK_ERR_MEM = -3,
|
||||
SOCK_ERR_INTR = -4,
|
||||
SOCK_ERR_USED = -5,
|
||||
SOCK_ERR_BADF = -6,
|
||||
SOCK_ERR_ABORT = -7,
|
||||
SOCK_ERR_NBLOCK = -8;
|
||||
|
||||
int SocketGetLastError();
|
||||
const char* SocketGetLastErrorMessage();
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Addresses
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
//NOTE(martin): net_ip and net_port are stored in network byte order
|
||||
// host_ip and host_port are stored in host byte order
|
||||
typedef uint32 net_ip;
|
||||
typedef uint16 net_port;
|
||||
typedef uint32 host_ip;
|
||||
typedef uint16 host_port;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
net_ip ip;
|
||||
net_port port;
|
||||
} socket_address;
|
||||
|
||||
//NOTE(martin): these are in host byte order !
|
||||
const host_ip SOCK_IP_LOOPBACK = 0x7f000001;
|
||||
const host_ip SOCK_IP_ANY = 0;
|
||||
const host_port SOCK_PORT_ANY = 0;
|
||||
|
||||
net_ip StringToNetIP(const char* addr);
|
||||
const char* NetIPToString(net_ip ip);
|
||||
|
||||
host_ip StringToHostIP(const char* addr);
|
||||
const char* HostIPToString(host_ip ip);
|
||||
|
||||
net_ip HostToNetIP(host_ip ip);
|
||||
net_port HostToNetPort(host_port port);
|
||||
host_ip NetToHostIP(net_ip ip);
|
||||
host_port NetToHostPort(net_port port);
|
||||
|
||||
|
||||
int SocketGetIFAddresses(int* count, net_ip* ips);
|
||||
net_ip SocketGetDefaultExternalIP();
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Socket API
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
typedef struct platform_socket platform_socket;
|
||||
|
||||
typedef enum { SOCK_UDP, SOCK_TCP } socket_transport;
|
||||
|
||||
const int SOCK_MSG_OOB = 0x01,
|
||||
SOCK_MSG_PEEK = 0x02,
|
||||
SOCK_MSG_DONTROUTE = 0x04,
|
||||
SOCK_MSG_WAITALL = 0x40;
|
||||
|
||||
platform_socket* SocketOpen(socket_transport transport);
|
||||
int SocketClose(platform_socket* socket);
|
||||
|
||||
int SocketBind(platform_socket* socket, socket_address* addr);
|
||||
int SocketListen(platform_socket* socket, int backlog);
|
||||
platform_socket* SocketAccept(platform_socket* socket, socket_address* from);
|
||||
|
||||
int SocketConnect(platform_socket* socket, socket_address* addr);
|
||||
|
||||
int64 SocketReceive(platform_socket* socket, void* buffer, uint64 size, int flags);
|
||||
int64 SocketReceiveFrom(platform_socket* socket, void* buffer, uint64 size, int flags, socket_address* from);
|
||||
|
||||
int64 SocketSend(platform_socket* socket, void* buffer, uint64 size, int flags);
|
||||
int64 SocketSendTo(platform_socket* socket, void* buffer, uint64 size, int flags, socket_address* to);
|
||||
|
||||
int SocketGetAddress(platform_socket* socket, socket_address* addr);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Multiplexing
|
||||
//----------------------------------------------------------------------------------
|
||||
const uint8 SOCK_ACTIVITY_IN = 1<<0,
|
||||
SOCK_ACTIVITY_OUT = 1<<2,
|
||||
SOCK_ACTIVITY_ERR = 1<<3;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
platform_socket* sock;
|
||||
uint8 watch;
|
||||
uint8 set;
|
||||
} socket_activity;
|
||||
|
||||
int SocketSelect(uint32 count, socket_activity* set, double timeout);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Socket Options
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
int SocketSetReceiveTimeout(platform_socket* socket, timeval* tv);
|
||||
int SocketSetSendTimeout(platform_socket* socket, timeval* tv);
|
||||
int SocketSetBroadcast(platform_socket* sock, bool enable);
|
||||
int SocketSetReuseAddress(platform_socket* sock, bool enable);
|
||||
int SocketSetReusePort(platform_socket* sock, bool enable);
|
||||
int SocketSetReceiveTimestamping(platform_socket* socket, bool enable);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Multicast
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
int SocketSetMulticastLoop(platform_socket* sock, bool enable);
|
||||
int SocketJoinMulticastGroup(platform_socket* socket, host_ip group, host_ip interface);
|
||||
int SocketLeaveMulticastGroup(platform_socket* socket, host_ip group, host_ip interface);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//Ancillary data API
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef struct
|
||||
{
|
||||
u64 messageBufferSize;
|
||||
char* messageBuffer;
|
||||
|
||||
u64 controlBufferSize;
|
||||
char* controlBuffer;
|
||||
} socket_msg;
|
||||
|
||||
int SocketReceiveMessage(platform_socket* socket, socket_msg* msg, socket_address* from);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif //__PLATFORM_SOCKET_H_
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef __PLATFORM_THREAD_H_
|
||||
#define __PLATFORM_THREAD_H_
|
||||
|
||||
#include"util/strings.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include<atomic>
|
||||
|
@ -27,59 +28,64 @@ extern "C" {
|
|||
|
||||
enum
|
||||
{
|
||||
MP_THREAD_NAME_MAX_SIZE = 64, // including null terminator
|
||||
OC_THREAD_NAME_MAX_SIZE = 64, // including null terminator
|
||||
};
|
||||
|
||||
typedef struct mp_thread mp_thread;
|
||||
typedef struct oc_thread oc_thread;
|
||||
|
||||
typedef i32 (*mp_thread_start_function)(void* userPointer);
|
||||
typedef i32 (*oc_thread_start_function)(void* userPointer);
|
||||
|
||||
MP_API mp_thread* mp_thread_create(mp_thread_start_function start, void* userPointer);
|
||||
MP_API mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* userPointer, const char* name);
|
||||
MP_API const char* mp_thread_get_name(mp_thread* thread);
|
||||
MP_API u64 mp_thread_unique_id(mp_thread* thread);
|
||||
MP_API u64 mp_thread_self_id();
|
||||
MP_API int mp_thread_signal(mp_thread* thread, int sig);
|
||||
MP_API int mp_thread_join(mp_thread* thread, i64* exitCode);
|
||||
MP_API int mp_thread_detach(mp_thread* thread);
|
||||
ORCA_API oc_thread* oc_thread_create(oc_thread_start_function start, void* userPointer);
|
||||
ORCA_API oc_thread* oc_thread_create_with_name(oc_thread_start_function start, void* userPointer, oc_str8 name);
|
||||
ORCA_API oc_str8 oc_thread_get_name(oc_thread* thread);
|
||||
ORCA_API u64 oc_thread_unique_id(oc_thread* thread);
|
||||
ORCA_API u64 oc_thread_self_id();
|
||||
ORCA_API int oc_thread_signal(oc_thread* thread, int sig);
|
||||
ORCA_API int oc_thread_join(oc_thread* thread, i64* exitCode);
|
||||
ORCA_API int oc_thread_detach(oc_thread* thread);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Platform Mutex API
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef struct mp_mutex mp_mutex;
|
||||
typedef struct oc_mutex oc_mutex;
|
||||
|
||||
MP_API mp_mutex* mp_mutex_create();
|
||||
MP_API int mp_mutex_destroy(mp_mutex* mutex);
|
||||
MP_API int mp_mutex_lock(mp_mutex* mutex);
|
||||
MP_API int mp_mutex_unlock(mp_mutex* mutex);
|
||||
ORCA_API oc_mutex* oc_mutex_create();
|
||||
ORCA_API int oc_mutex_destroy(oc_mutex* mutex);
|
||||
ORCA_API int oc_mutex_lock(oc_mutex* mutex);
|
||||
ORCA_API int oc_mutex_unlock(oc_mutex* mutex);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Lightweight ticket mutex API
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef struct mp_ticket_spin_mutex
|
||||
typedef struct oc_ticket
|
||||
{
|
||||
volatile _Atomic(u64) nextTicket;
|
||||
volatile _Atomic(u64) serving;
|
||||
} mp_ticket_spin_mutex;
|
||||
} oc_ticket;
|
||||
|
||||
MP_API void mp_ticket_spin_mutex_init(mp_ticket_spin_mutex* mutex);
|
||||
MP_API void mp_ticket_spin_mutex_lock(mp_ticket_spin_mutex* mutex);
|
||||
MP_API void mp_ticket_spin_mutex_unlock(mp_ticket_spin_mutex* mutex);
|
||||
ORCA_API void oc_ticket_init(oc_ticket* mutex);
|
||||
ORCA_API void oc_ticket_lock(oc_ticket* mutex);
|
||||
ORCA_API void oc_ticket_unlock(oc_ticket* mutex);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Platform condition variable API
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef struct mp_condition mp_condition;
|
||||
typedef struct oc_condition oc_condition;
|
||||
|
||||
MP_API mp_condition* mp_condition_create();
|
||||
MP_API int mp_condition_destroy(mp_condition* cond);
|
||||
MP_API int mp_condition_wait(mp_condition* cond, mp_mutex* mutex);
|
||||
MP_API int mp_condition_timedwait(mp_condition* cond, mp_mutex* mutex, f64 seconds);
|
||||
MP_API int mp_condition_signal(mp_condition* cond);
|
||||
MP_API int mp_condition_broadcast(mp_condition* cond);
|
||||
ORCA_API oc_condition* oc_condition_create();
|
||||
ORCA_API int oc_condition_destroy(oc_condition* cond);
|
||||
ORCA_API int oc_condition_wait(oc_condition* cond, oc_mutex* mutex);
|
||||
ORCA_API int oc_condition_timedwait(oc_condition* cond, oc_mutex* mutex, f64 seconds);
|
||||
ORCA_API int oc_condition_signal(oc_condition* cond);
|
||||
ORCA_API int oc_condition_broadcast(oc_condition* cond);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Putting threads to sleep
|
||||
//---------------------------------------------------------------
|
||||
ORCA_API void oc_sleep_nano(u64 nanoseconds); // sleep for a given number of nanoseconds
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -15,116 +15,116 @@
|
|||
#include"platform_io_common.c"
|
||||
#include"platform_io_internal.c"
|
||||
|
||||
io_file_desc io_file_desc_nil()
|
||||
oc_file_desc oc_file_desc_nil()
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
bool io_file_desc_is_nil(io_file_desc fd)
|
||||
bool oc_file_desc_is_nil(oc_file_desc fd)
|
||||
{
|
||||
return(fd < 0);
|
||||
}
|
||||
|
||||
io_error io_raw_last_error()
|
||||
oc_io_error oc_io_raw_last_error()
|
||||
{
|
||||
io_error error = IO_OK;
|
||||
oc_io_error error = OC_IO_OK;
|
||||
switch(errno)
|
||||
{
|
||||
case EPERM:
|
||||
case EACCES:
|
||||
case EROFS:
|
||||
error = IO_ERR_PERM;
|
||||
error = OC_IO_ERR_PERM;
|
||||
break;
|
||||
|
||||
case ENOENT:
|
||||
error = IO_ERR_NO_ENTRY;
|
||||
error = OC_IO_ERR_NO_ENTRY;
|
||||
break;
|
||||
|
||||
case EINTR:
|
||||
error = IO_ERR_INTERRUPT;
|
||||
error = OC_IO_ERR_INTERRUPT;
|
||||
break;
|
||||
|
||||
case EIO:
|
||||
error = IO_ERR_PHYSICAL;
|
||||
error = OC_IO_ERR_PHYSICAL;
|
||||
break;
|
||||
|
||||
case ENXIO:
|
||||
error = IO_ERR_NO_DEVICE;
|
||||
error = OC_IO_ERR_NO_DEVICE;
|
||||
break;
|
||||
|
||||
case EBADF:
|
||||
// this should only happen when user tries to write/read to a file handle
|
||||
// opened with readonly/writeonly access
|
||||
error = IO_ERR_PERM;
|
||||
error = OC_IO_ERR_PERM;
|
||||
break;
|
||||
|
||||
case ENOMEM:
|
||||
error = IO_ERR_MEM;
|
||||
error = OC_IO_ERR_MEM;
|
||||
break;
|
||||
|
||||
case EFAULT:
|
||||
case EINVAL:
|
||||
case EDOM:
|
||||
error = IO_ERR_ARG;
|
||||
error = OC_IO_ERR_ARG;
|
||||
break;
|
||||
|
||||
case EBUSY:
|
||||
case EAGAIN:
|
||||
error = IO_ERR_NOT_READY;
|
||||
error = OC_IO_ERR_NOT_READY;
|
||||
break;
|
||||
|
||||
case EEXIST:
|
||||
error = IO_ERR_EXISTS;
|
||||
error = OC_IO_ERR_EXISTS;
|
||||
break;
|
||||
|
||||
case ENOTDIR:
|
||||
error = IO_ERR_NOT_DIR;
|
||||
error = OC_IO_ERR_NOT_DIR;
|
||||
break;
|
||||
|
||||
case EISDIR:
|
||||
error = IO_ERR_DIR;
|
||||
error = OC_IO_ERR_DIR;
|
||||
break;
|
||||
|
||||
case ENFILE:
|
||||
case EMFILE:
|
||||
error = IO_ERR_MAX_FILES;
|
||||
error = OC_IO_ERR_MAX_FILES;
|
||||
break;
|
||||
|
||||
case EFBIG:
|
||||
error = IO_ERR_FILE_SIZE;
|
||||
error = OC_IO_ERR_FILE_SIZE;
|
||||
break;
|
||||
|
||||
case ENOSPC:
|
||||
case EDQUOT:
|
||||
error = IO_ERR_SPACE;
|
||||
error = OC_IO_ERR_SPACE;
|
||||
break;
|
||||
|
||||
case ELOOP:
|
||||
error = IO_ERR_MAX_LINKS;
|
||||
error = OC_IO_ERR_MAX_LINKS;
|
||||
break;
|
||||
|
||||
case ENAMETOOLONG:
|
||||
error = IO_ERR_PATH_LENGTH;
|
||||
error = OC_IO_ERR_PATH_LENGTH;
|
||||
break;
|
||||
|
||||
case EOVERFLOW:
|
||||
error = IO_ERR_OVERFLOW;
|
||||
error = OC_IO_ERR_OVERFLOW;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = IO_ERR_UNKNOWN;
|
||||
error = OC_IO_ERR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
int io_convert_access_rights(file_access_rights rights)
|
||||
static int oc_io_convert_access_rights(oc_file_access rights)
|
||||
{
|
||||
int oflags = 0;
|
||||
|
||||
if(rights & FILE_ACCESS_READ)
|
||||
if(rights & OC_FILE_ACCESS_READ)
|
||||
{
|
||||
if(rights & FILE_ACCESS_WRITE)
|
||||
if(rights & OC_FILE_ACCESS_WRITE)
|
||||
{
|
||||
oflags = O_RDWR;
|
||||
}
|
||||
|
@ -133,41 +133,41 @@ int io_convert_access_rights(file_access_rights rights)
|
|||
oflags = O_RDONLY;
|
||||
}
|
||||
}
|
||||
else if(rights & FILE_ACCESS_WRITE)
|
||||
else if(rights & OC_FILE_ACCESS_WRITE)
|
||||
{
|
||||
oflags = O_WRONLY;
|
||||
}
|
||||
return(oflags);
|
||||
}
|
||||
|
||||
int io_convert_open_flags(file_open_flags flags)
|
||||
static int oc_io_convert_open_flags(oc_file_open_flags flags)
|
||||
{
|
||||
int oflags = 0;
|
||||
|
||||
if(flags & FILE_OPEN_TRUNCATE)
|
||||
if(flags & OC_FILE_OPEN_TRUNCATE)
|
||||
{
|
||||
oflags |= O_TRUNC;
|
||||
}
|
||||
if(flags & FILE_OPEN_APPEND)
|
||||
if(flags & OC_FILE_OPEN_APPEND)
|
||||
{
|
||||
oflags |= O_APPEND;
|
||||
}
|
||||
if(flags & FILE_OPEN_CREATE)
|
||||
if(flags & OC_FILE_OPEN_CREATE)
|
||||
{
|
||||
oflags |= O_CREAT;
|
||||
}
|
||||
if(flags & FILE_OPEN_NO_FOLLOW)
|
||||
if(flags & OC_FILE_OPEN_NO_FOLLOW)
|
||||
{
|
||||
oflags |= O_NOFOLLOW;
|
||||
}
|
||||
if(flags & FILE_OPEN_SYMLINK)
|
||||
if(flags & OC_FILE_OPEN_SYMLINK)
|
||||
{
|
||||
oflags |= O_SYMLINK;
|
||||
}
|
||||
return(oflags);
|
||||
}
|
||||
|
||||
int io_update_dir_flags_at(int dirFd, char* path, int flags)
|
||||
static int oc_io_update_dir_flags_at(int dirFd, char* path, int flags)
|
||||
{
|
||||
struct stat s;
|
||||
if(!fstatat(dirFd, path, &s, AT_SYMLINK_NOFOLLOW))
|
||||
|
@ -188,10 +188,10 @@ int io_update_dir_flags_at(int dirFd, char* path, int flags)
|
|||
return(flags);
|
||||
}
|
||||
|
||||
io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights accessRights, file_open_flags openFlags)
|
||||
oc_file_desc oc_io_raw_open_at(oc_file_desc dirFd, oc_str8 path, oc_file_access accessRights, oc_file_open_flags openFlags)
|
||||
{
|
||||
int flags = io_convert_access_rights(accessRights);
|
||||
flags |= io_convert_open_flags(openFlags);
|
||||
int flags = oc_io_convert_access_rights(accessRights);
|
||||
flags |= oc_io_convert_open_flags(openFlags);
|
||||
|
||||
mode_t mode = S_IRUSR
|
||||
| S_IWUSR
|
||||
|
@ -200,18 +200,18 @@ io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights ac
|
|||
| S_IROTH
|
||||
| S_IWOTH;
|
||||
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
|
||||
io_file_desc fd = -1;
|
||||
oc_file_desc fd = -1;
|
||||
if(dirFd >= 0)
|
||||
{
|
||||
if(path.len && path.ptr[0] == '/')
|
||||
{
|
||||
//NOTE: if path is absolute, change for a relative one, otherwise openat ignores fd.
|
||||
str8_list list = {0};
|
||||
str8_list_push(scratch.arena, &list, STR8("."));
|
||||
str8_list_push(scratch.arena, &list, path);
|
||||
path = str8_list_join(scratch.arena, list);
|
||||
oc_str8_list list = {0};
|
||||
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||
oc_str8_list_push(scratch.arena, &list, path);
|
||||
path = oc_str8_list_join(scratch.arena, list);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -219,98 +219,98 @@ io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights ac
|
|||
dirFd = AT_FDCWD;
|
||||
}
|
||||
|
||||
char* pathCStr = str8_to_cstring(scratch.arena, path);
|
||||
char* pathCStr = oc_str8_to_cstring(scratch.arena, path);
|
||||
|
||||
flags = io_update_dir_flags_at(dirFd, pathCStr, flags);
|
||||
flags = oc_io_update_dir_flags_at(dirFd, pathCStr, flags);
|
||||
|
||||
fd = openat(dirFd, pathCStr, flags, mode);
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
|
||||
return(fd);
|
||||
}
|
||||
|
||||
void io_raw_close(io_file_desc fd)
|
||||
void oc_io_raw_close(oc_file_desc fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
file_perm io_convert_perm_from_stat(u16 mode)
|
||||
static oc_file_perm oc_io_convert_perm_from_stat(u16 mode)
|
||||
{
|
||||
file_perm perm = mode & 07777;
|
||||
oc_file_perm perm = mode & 07777;
|
||||
return(perm);
|
||||
}
|
||||
|
||||
file_type io_convert_type_from_stat(u16 mode)
|
||||
static oc_file_type oc_io_convert_type_from_stat(u16 mode)
|
||||
{
|
||||
file_type type;
|
||||
oc_file_type type;
|
||||
switch(mode & S_IFMT)
|
||||
{
|
||||
case S_IFIFO:
|
||||
type = MP_FILE_FIFO;
|
||||
type = OC_FILE_FIFO;
|
||||
break;
|
||||
|
||||
case S_IFCHR:
|
||||
type = MP_FILE_CHARACTER;
|
||||
type = OC_FILE_CHARACTER;
|
||||
break;
|
||||
|
||||
case S_IFDIR:
|
||||
type = MP_FILE_DIRECTORY;
|
||||
type = OC_FILE_DIRECTORY;
|
||||
break;
|
||||
|
||||
case S_IFBLK:
|
||||
type = MP_FILE_BLOCK;
|
||||
type = OC_FILE_BLOCK;
|
||||
break;
|
||||
|
||||
case S_IFREG:
|
||||
type = MP_FILE_REGULAR;
|
||||
type = OC_FILE_REGULAR;
|
||||
break;
|
||||
|
||||
case S_IFLNK:
|
||||
type = MP_FILE_SYMLINK;
|
||||
type = OC_FILE_SYMLINK;
|
||||
break;
|
||||
|
||||
case S_IFSOCK:
|
||||
type = MP_FILE_SOCKET;
|
||||
type = OC_FILE_SOCKET;
|
||||
break;
|
||||
|
||||
default:
|
||||
type = MP_FILE_UNKNOWN;
|
||||
type = OC_FILE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return(type);
|
||||
}
|
||||
|
||||
io_error io_raw_fstat(io_file_desc fd, file_status* status)
|
||||
oc_io_error oc_io_raw_fstat(oc_file_desc fd, oc_file_status* status)
|
||||
{
|
||||
io_error error = IO_OK;
|
||||
oc_io_error error = OC_IO_OK;
|
||||
struct stat s;
|
||||
if(fstat(fd, &s))
|
||||
{
|
||||
error = io_raw_last_error();
|
||||
error = oc_io_raw_last_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
status->uid = s.st_ino;
|
||||
status->perm = io_convert_perm_from_stat(s.st_mode);
|
||||
status->type = io_convert_type_from_stat(s.st_mode);
|
||||
status->perm = oc_io_convert_perm_from_stat(s.st_mode);
|
||||
status->type = oc_io_convert_type_from_stat(s.st_mode);
|
||||
status->size = s.st_size;
|
||||
//TODO: times
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
io_error io_raw_fstat_at(io_file_desc dirFd, str8 path, file_open_flags flags, file_status* status)
|
||||
oc_io_error oc_io_raw_fstat_at(oc_file_desc dirFd, oc_str8 path, oc_file_open_flags flags, oc_file_status* status)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
|
||||
if(dirFd >= 0)
|
||||
{
|
||||
if(path.len && path.ptr[0] == '/')
|
||||
{
|
||||
str8_list list = {0};
|
||||
str8_list_push(scratch.arena, &list, STR8("."));
|
||||
str8_list_push(scratch.arena, &list, path);
|
||||
path = str8_list_join(scratch.arena, list);
|
||||
oc_str8_list list = {0};
|
||||
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||
oc_str8_list_push(scratch.arena, &list, path);
|
||||
path = oc_str8_list_join(scratch.arena, list);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -318,40 +318,40 @@ io_error io_raw_fstat_at(io_file_desc dirFd, str8 path, file_open_flags flags, f
|
|||
dirFd = AT_FDCWD;
|
||||
}
|
||||
|
||||
char* pathCStr = str8_to_cstring(scratch.arena, path);
|
||||
char* pathCStr = oc_str8_to_cstring(scratch.arena, path);
|
||||
|
||||
int statFlag = (flags & FILE_OPEN_SYMLINK)? AT_SYMLINK_NOFOLLOW : 0;
|
||||
io_error error = IO_OK;
|
||||
int statFlag = (flags & OC_FILE_OPEN_SYMLINK)? AT_SYMLINK_NOFOLLOW : 0;
|
||||
oc_io_error error = OC_IO_OK;
|
||||
struct stat s;
|
||||
if(fstatat(dirFd, pathCStr, &s, statFlag))
|
||||
{
|
||||
error = io_raw_last_error();
|
||||
error = oc_io_raw_last_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
status->uid = s.st_ino;
|
||||
status->perm = io_convert_perm_from_stat(s.st_mode);
|
||||
status->type = io_convert_type_from_stat(s.st_mode);
|
||||
status->perm = oc_io_convert_perm_from_stat(s.st_mode);
|
||||
status->type = oc_io_convert_type_from_stat(s.st_mode);
|
||||
status->size = s.st_size;
|
||||
//TODO: times
|
||||
}
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
return(error);
|
||||
}
|
||||
|
||||
io_raw_read_link_result io_raw_read_link_at(mem_arena* arena, io_file_desc dirFd, str8 path)
|
||||
oc_io_raw_read_link_result oc_io_raw_read_link_at(oc_arena* arena, oc_file_desc dirFd, oc_str8 path)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin_next(arena);
|
||||
oc_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||
|
||||
if(dirFd >= 0)
|
||||
{
|
||||
if(path.len && path.ptr[0] == '/')
|
||||
{
|
||||
str8_list list = {0};
|
||||
str8_list_push(scratch.arena, &list, STR8("."));
|
||||
str8_list_push(scratch.arena, &list, path);
|
||||
path = str8_list_join(scratch.arena, list);
|
||||
oc_str8_list list = {0};
|
||||
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||
oc_str8_list_push(scratch.arena, &list, path);
|
||||
path = oc_str8_list_join(scratch.arena, list);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -359,9 +359,9 @@ io_raw_read_link_result io_raw_read_link_at(mem_arena* arena, io_file_desc dirFd
|
|||
dirFd = AT_FDCWD;
|
||||
}
|
||||
|
||||
char* pathCStr = str8_to_cstring(scratch.arena, path);
|
||||
char* pathCStr = oc_str8_to_cstring(scratch.arena, path);
|
||||
|
||||
io_raw_read_link_result result = {0};
|
||||
oc_io_raw_read_link_result result = {0};
|
||||
|
||||
char buffer[PATH_MAX];
|
||||
u64 bufferSize = PATH_MAX;
|
||||
|
@ -369,31 +369,31 @@ io_raw_read_link_result io_raw_read_link_at(mem_arena* arena, io_file_desc dirFd
|
|||
|
||||
if(r<0)
|
||||
{
|
||||
result.error = io_raw_last_error();
|
||||
result.error = oc_io_raw_last_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
result.target.len = r;
|
||||
result.target.ptr = mem_arena_alloc_array(arena, char, result.target.len);
|
||||
result.target.ptr = oc_arena_push_array(arena, char, result.target.len);
|
||||
memcpy(result.target.ptr, buffer, result.target.len);
|
||||
}
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
bool io_raw_file_exists_at(io_file_desc dirFd, str8 path, file_open_flags openFlags)
|
||||
bool oc_io_raw_file_exists_at(oc_file_desc dirFd, oc_str8 path, oc_file_open_flags openFlags)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
|
||||
if(dirFd >= 0)
|
||||
{
|
||||
if(path.len && path.ptr[0] == '/')
|
||||
{
|
||||
str8_list list = {0};
|
||||
str8_list_push(scratch.arena, &list, STR8("."));
|
||||
str8_list_push(scratch.arena, &list, path);
|
||||
path = str8_list_join(scratch.arena, list);
|
||||
oc_str8_list list = {0};
|
||||
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||
oc_str8_list_push(scratch.arena, &list, path);
|
||||
path = oc_str8_list_join(scratch.arena, list);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -401,48 +401,48 @@ bool io_raw_file_exists_at(io_file_desc dirFd, str8 path, file_open_flags openFl
|
|||
dirFd = AT_FDCWD;
|
||||
}
|
||||
|
||||
char* pathCStr = str8_to_cstring(scratch.arena, path);
|
||||
char* pathCStr = oc_str8_to_cstring(scratch.arena, path);
|
||||
|
||||
int flags = (openFlags & FILE_OPEN_SYMLINK)? AT_SYMLINK_NOFOLLOW : 0;
|
||||
int flags = (openFlags & OC_FILE_OPEN_SYMLINK)? AT_SYMLINK_NOFOLLOW : 0;
|
||||
int r = faccessat(dirFd, pathCStr, F_OK, flags);
|
||||
bool result = (r == 0);
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
io_cmp io_close(file_slot* slot, io_req* req, file_table* table)
|
||||
oc_io_cmp oc_io_close(oc_file_slot* slot, oc_io_req* req, oc_file_table* table)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
if(slot->fd >= 0)
|
||||
{
|
||||
close(slot->fd);
|
||||
}
|
||||
file_slot_recycle(table, slot);
|
||||
oc_file_slot_recycle(table, slot);
|
||||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_fstat(file_slot* slot, io_req* req)
|
||||
oc_io_cmp oc_io_fstat(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
if(req->size < sizeof(file_status))
|
||||
if(req->size < sizeof(oc_file_status))
|
||||
{
|
||||
cmp.error = IO_ERR_ARG;
|
||||
cmp.error = OC_IO_ERR_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stat s;
|
||||
if(fstat(slot->fd, &s))
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
else
|
||||
{
|
||||
file_status* status = (file_status*)req->buffer;
|
||||
status->perm = io_convert_perm_from_stat(s.st_mode);
|
||||
status->type = io_convert_type_from_stat(s.st_mode);
|
||||
oc_file_status* status = (oc_file_status*)req->buffer;
|
||||
status->perm = oc_io_convert_perm_from_stat(s.st_mode);
|
||||
status->type = oc_io_convert_type_from_stat(s.st_mode);
|
||||
status->size = s.st_size;
|
||||
//TODO: times
|
||||
}
|
||||
|
@ -450,44 +450,44 @@ io_cmp io_fstat(file_slot* slot, io_req* req)
|
|||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_seek(file_slot* slot, io_req* req)
|
||||
oc_io_cmp oc_io_seek(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
int whence;
|
||||
switch(req->whence)
|
||||
{
|
||||
case FILE_SEEK_CURRENT:
|
||||
case OC_FILE_SEEK_CURRENT:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
|
||||
case FILE_SEEK_SET:
|
||||
case OC_FILE_SEEK_SET:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
|
||||
case FILE_SEEK_END:
|
||||
case OC_FILE_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
}
|
||||
cmp.result = lseek(slot->fd, req->offset, whence);
|
||||
|
||||
if(cmp.result < 0)
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
|
||||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_read(file_slot* slot, io_req* req)
|
||||
oc_io_cmp oc_io_read(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
cmp.result = read(slot->fd, req->buffer, req->size);
|
||||
|
||||
if(cmp.result < 0)
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
cmp.result = 0;
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
|
@ -495,15 +495,15 @@ io_cmp io_read(file_slot* slot, io_req* req)
|
|||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_write(file_slot* slot, io_req* req)
|
||||
oc_io_cmp oc_io_write(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
cmp.result = write(slot->fd, req->buffer, req->size);
|
||||
|
||||
if(cmp.result < 0)
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
cmp.result = 0;
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
|
@ -511,66 +511,66 @@ io_cmp io_write(file_slot* slot, io_req* req)
|
|||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_get_error(file_slot* slot, io_req* req)
|
||||
oc_io_cmp oc_io_get_error(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
cmp.result = slot->error;
|
||||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_wait_single_req_with_table(io_req* req, file_table* table)
|
||||
oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
file_slot* slot = file_slot_from_handle(table, req->handle);
|
||||
oc_file_slot* slot = oc_file_slot_from_handle(table, req->handle);
|
||||
if(!slot)
|
||||
{
|
||||
if(req->op != IO_OP_OPEN_AT)
|
||||
if(req->op != OC_IO_OPEN_AT)
|
||||
{
|
||||
cmp.error = IO_ERR_HANDLE;
|
||||
cmp.error = OC_IO_ERR_HANDLE;
|
||||
}
|
||||
}
|
||||
else if( slot->fatal
|
||||
&& req->op != IO_OP_CLOSE
|
||||
&& req->op != IO_OP_ERROR)
|
||||
&& req->op != OC_IO_CLOSE
|
||||
&& req->op != OC_OC_IO_ERROR)
|
||||
{
|
||||
cmp.error = IO_ERR_PREV;
|
||||
cmp.error = OC_IO_ERR_PREV;
|
||||
}
|
||||
|
||||
if(cmp.error == IO_OK)
|
||||
if(cmp.error == OC_IO_OK)
|
||||
{
|
||||
switch(req->op)
|
||||
{
|
||||
case IO_OP_OPEN_AT:
|
||||
cmp = io_open_at(slot, req, table);
|
||||
case OC_IO_OPEN_AT:
|
||||
cmp = oc_io_open_at(slot, req, table);
|
||||
break;
|
||||
|
||||
case IO_OP_FSTAT:
|
||||
cmp = io_fstat(slot, req);
|
||||
case OC_IO_FSTAT:
|
||||
cmp = oc_io_fstat(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_CLOSE:
|
||||
cmp = io_close(slot, req, table);
|
||||
case OC_IO_CLOSE:
|
||||
cmp = oc_io_close(slot, req, table);
|
||||
break;
|
||||
|
||||
case IO_OP_READ:
|
||||
cmp = io_read(slot, req);
|
||||
case OC_IO_READ:
|
||||
cmp = oc_io_read(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_WRITE:
|
||||
cmp = io_write(slot, req);
|
||||
case OC_IO_WRITE:
|
||||
cmp = oc_io_write(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_SEEK:
|
||||
cmp = io_seek(slot, req);
|
||||
case OC_IO_SEEK:
|
||||
cmp = oc_io_seek(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_ERROR:
|
||||
cmp = io_get_error(slot, req);
|
||||
case OC_OC_IO_ERROR:
|
||||
cmp = oc_io_get_error(slot, req);
|
||||
break;
|
||||
|
||||
default:
|
||||
cmp.error = IO_ERR_OP;
|
||||
cmp.error = OC_IO_ERR_OP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,511 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: posix_socket.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 22/03/2019
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include<sys/socket.h> // socket()
|
||||
#include<netinet/ip.h> // socaddr_in
|
||||
#include<arpa/inet.h> // inet_addr()
|
||||
#include<ifaddrs.h> // getifaddrs() / freeifaddrs()
|
||||
#include<unistd.h> // close()
|
||||
#include<string.h> // strerror()
|
||||
#include<errno.h> // errno
|
||||
#include<stdlib.h> // malloc()/free()
|
||||
|
||||
#include"platform_socket.h"
|
||||
#include"platform_debug.h"
|
||||
|
||||
typedef struct in_addr in_addr;
|
||||
typedef struct sockaddr_in sockaddr_in;
|
||||
typedef struct sockaddr sockaddr;
|
||||
typedef struct msghdr msghdr;
|
||||
typedef struct cmsghdr cmsghdr;
|
||||
typedef struct ip_mreq ip_mreq;
|
||||
typedef struct iovec iovec;
|
||||
|
||||
net_ip StringToNetIP(const char* addr)
|
||||
{
|
||||
return(inet_addr(addr));
|
||||
}
|
||||
const char* NetIPToString(net_ip ip)
|
||||
{
|
||||
in_addr in;
|
||||
in.s_addr = ip;
|
||||
return(inet_ntoa(in));
|
||||
}
|
||||
|
||||
host_ip StringToHostIP(const char* addr)
|
||||
{
|
||||
return(NetToHostIP(StringToNetIP(addr)));
|
||||
}
|
||||
const char* HostIPToString(host_ip ip)
|
||||
{
|
||||
return(NetIPToString(HostToNetIP(ip)));
|
||||
}
|
||||
|
||||
net_ip HostToNetIP(uint32 ip)
|
||||
{
|
||||
return(htonl(ip));
|
||||
}
|
||||
net_port HostToNetPort(uint16 port)
|
||||
{
|
||||
return(htons(port));
|
||||
}
|
||||
uint32 NetToHostIP(net_ip ip)
|
||||
{
|
||||
return(ntohl(ip));
|
||||
}
|
||||
uint16 NetToHostPort(net_port port)
|
||||
{
|
||||
return(ntohs(port));
|
||||
}
|
||||
|
||||
static int PlatformToSocketFlags(int flags)
|
||||
{
|
||||
int sflags = 0;
|
||||
if(flags & SOCK_MSG_OOB)
|
||||
{
|
||||
sflags |= MSG_OOB;
|
||||
}
|
||||
if(flags & SOCK_MSG_PEEK)
|
||||
{
|
||||
sflags |= MSG_PEEK;
|
||||
}
|
||||
if(flags & SOCK_MSG_DONTROUTE)
|
||||
{
|
||||
sflags |= MSG_DONTROUTE;
|
||||
}
|
||||
if(flags & SOCK_MSG_WAITALL)
|
||||
{
|
||||
sflags |= MSG_WAITALL;
|
||||
}
|
||||
|
||||
return(sflags);
|
||||
}
|
||||
|
||||
static int ErrnoToSocketError(int err)
|
||||
{
|
||||
//TODO(martin): extend these error codes
|
||||
switch(err)
|
||||
{
|
||||
case 0: return(SOCK_ERR_OK);
|
||||
case EACCES: return(SOCK_ERR_ACCESS);
|
||||
case ENOBUFS:
|
||||
case ENOMEM: return(SOCK_ERR_MEM);
|
||||
case EINTR: return(SOCK_ERR_INTR);
|
||||
case EADDRINUSE: return(SOCK_ERR_USED);
|
||||
case EBADF: return(SOCK_ERR_BADF);
|
||||
case ECONNABORTED: return(SOCK_ERR_ABORT);
|
||||
|
||||
case EWOULDBLOCK:
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
case EAGAIN:
|
||||
#endif
|
||||
return(SOCK_ERR_NBLOCK);
|
||||
|
||||
default:
|
||||
return(SOCK_ERR_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
int SocketGetLastError()
|
||||
{
|
||||
return(ErrnoToSocketError(errno));
|
||||
}
|
||||
|
||||
const char* SocketGetLastErrorMessage()
|
||||
{
|
||||
return(strerror(errno));
|
||||
}
|
||||
|
||||
struct platform_socket
|
||||
{
|
||||
int sd;
|
||||
};
|
||||
|
||||
platform_socket* SocketOpen(socket_transport transport)
|
||||
{
|
||||
int sd = 0;
|
||||
switch(transport)
|
||||
{
|
||||
case SOCK_UDP:
|
||||
sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
break;
|
||||
|
||||
case SOCK_TCP:
|
||||
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
}
|
||||
if(!sd)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
platform_socket* sock = (platform_socket*)malloc(sizeof(platform_socket));
|
||||
if(!sock)
|
||||
{
|
||||
close(sd);
|
||||
return(0);
|
||||
}
|
||||
sock->sd = sd;
|
||||
return(sock);
|
||||
}
|
||||
|
||||
int SocketClose(platform_socket* sock)
|
||||
{
|
||||
if(!sock)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
int res = close(sock->sd);
|
||||
free(sock);
|
||||
return(res);
|
||||
}
|
||||
|
||||
int SocketBind(platform_socket* sock, socket_address* addr)
|
||||
{
|
||||
sockaddr_in saddr;
|
||||
saddr.sin_addr.s_addr = addr->ip;
|
||||
saddr.sin_port = addr->port;
|
||||
saddr.sin_family = AF_INET;
|
||||
|
||||
return(bind(sock->sd, (sockaddr*)&saddr, sizeof(saddr)));
|
||||
}
|
||||
|
||||
int SocketListen(platform_socket* sock, int backlog)
|
||||
{
|
||||
return(listen(sock->sd, backlog));
|
||||
}
|
||||
platform_socket* SocketAccept(platform_socket* sock, socket_address* from)
|
||||
{
|
||||
sockaddr_in saddr;
|
||||
socklen_t saddrSize = sizeof(saddr);
|
||||
int sd = accept(sock->sd, (sockaddr*)&saddr, &saddrSize);
|
||||
|
||||
from->ip = saddr.sin_addr.s_addr;
|
||||
from->port = saddr.sin_port;
|
||||
|
||||
if(sd <= 0)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
platform_socket* client = (platform_socket*)malloc(sizeof(platform_socket));
|
||||
if(!client)
|
||||
{
|
||||
close(sd);
|
||||
return(0);
|
||||
}
|
||||
client->sd = sd;
|
||||
return(client);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int SocketConnect(platform_socket* sock, socket_address* addr)
|
||||
{
|
||||
sockaddr_in saddr;
|
||||
saddr.sin_addr.s_addr = addr->ip;
|
||||
saddr.sin_port = addr->port;
|
||||
saddr.sin_family = AF_INET;
|
||||
|
||||
return(connect(sock->sd, (sockaddr*)&saddr, sizeof(saddr)));
|
||||
}
|
||||
|
||||
int64 SocketReceive(platform_socket* sock, void* buffer, uint64 size, int flags)
|
||||
{
|
||||
return(recv(sock->sd, buffer, size, PlatformToSocketFlags(flags)));
|
||||
}
|
||||
|
||||
int64 SocketReceiveFrom(platform_socket* sock, void* buffer, uint64 size, int flags, socket_address* from)
|
||||
{
|
||||
sockaddr_in saddr;
|
||||
socklen_t saddrSize = sizeof(saddr);
|
||||
|
||||
int res = recvfrom(sock->sd, buffer, size, PlatformToSocketFlags(flags), (sockaddr*)&saddr, &saddrSize);
|
||||
|
||||
from->ip = saddr.sin_addr.s_addr;
|
||||
from->port = saddr.sin_port;
|
||||
return(res);
|
||||
}
|
||||
|
||||
int64 SocketSend(platform_socket* sock, void* buffer, uint64 size, int flags)
|
||||
{
|
||||
return(send(sock->sd, buffer, size, PlatformToSocketFlags(flags)));
|
||||
}
|
||||
int64 SocketSendTo(platform_socket* sock, void* buffer, uint64 size, int flags, socket_address* to)
|
||||
{
|
||||
sockaddr_in saddr;
|
||||
saddr.sin_addr.s_addr = to->ip;
|
||||
saddr.sin_port = to->port;
|
||||
saddr.sin_family = AF_INET;
|
||||
|
||||
return(sendto(sock->sd, buffer, size, PlatformToSocketFlags(flags), (sockaddr*)&saddr, sizeof(saddr)));
|
||||
}
|
||||
|
||||
|
||||
int SocketSetReceiveTimeout(platform_socket* sock, timeval* tv)
|
||||
{
|
||||
DEBUG_ASSERT(sock);
|
||||
DEBUG_ASSERT(sock->sd);
|
||||
return(setsockopt(sock->sd, SOL_SOCKET, SO_RCVTIMEO, tv, sizeof(timeval)));
|
||||
}
|
||||
|
||||
int SocketSetSendTimeout(platform_socket* sock, timeval* tv)
|
||||
{
|
||||
DEBUG_ASSERT(sock);
|
||||
DEBUG_ASSERT(sock->sd);
|
||||
return(setsockopt(sock->sd, SOL_SOCKET, SO_SNDTIMEO, tv, sizeof(timeval)));
|
||||
}
|
||||
|
||||
int SocketSetReceiveTimestamping(platform_socket* socket, bool enable)
|
||||
{
|
||||
int opt = enable ? 1 : 0;
|
||||
socklen_t len = sizeof(int);
|
||||
return(setsockopt(socket->sd, SOL_SOCKET, SO_TIMESTAMP, &enable, len));
|
||||
}
|
||||
|
||||
int SocketSetBroadcast(platform_socket* sock, bool enable)
|
||||
{
|
||||
DEBUG_ASSERT(sock);
|
||||
DEBUG_ASSERT(sock->sd);
|
||||
|
||||
int opt = enable ? 1 : 0;
|
||||
return(setsockopt(sock->sd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int)));
|
||||
}
|
||||
|
||||
|
||||
int SocketSelect(uint32 count, socket_activity* set, double timeout)
|
||||
{
|
||||
fd_set fdInSet;
|
||||
fd_set fdOutSet;
|
||||
fd_set fdErrSet;
|
||||
FD_ZERO(&fdInSet);
|
||||
FD_ZERO(&fdOutSet);
|
||||
FD_ZERO(&fdErrSet);
|
||||
|
||||
int maxSd = -1;
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
socket_activity* item = &(set[i]);
|
||||
if(item->sock)
|
||||
{
|
||||
item->set = 0;
|
||||
if(item->watch & SOCK_ACTIVITY_IN)
|
||||
{
|
||||
FD_SET(item->sock->sd, &fdInSet);
|
||||
}
|
||||
if(item->watch & SOCK_ACTIVITY_OUT)
|
||||
{
|
||||
FD_SET(item->sock->sd, &fdOutSet);
|
||||
}
|
||||
if(item->watch & SOCK_ACTIVITY_ERR)
|
||||
{
|
||||
FD_SET(item->sock->sd, &fdErrSet);
|
||||
}
|
||||
|
||||
if(item->watch && (item->sock->sd > maxSd))
|
||||
{
|
||||
maxSd = item->sock->sd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(maxSd <= 0)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
timeval tv;
|
||||
tv.tv_sec = (time_t)timeout;
|
||||
tv.tv_usec = (suseconds_t)((timeout - tv.tv_sec)*1000000);
|
||||
|
||||
timeval* ptv = timeout >= 0 ? &tv : 0;
|
||||
|
||||
int activity = select(maxSd+1, &fdInSet, &fdOutSet, &fdErrSet, ptv);
|
||||
if(activity < 0)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int processed = 0;
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
if(processed >= activity)
|
||||
{
|
||||
break;
|
||||
}
|
||||
socket_activity* item = &(set[i]);
|
||||
if(item->sock)
|
||||
{
|
||||
if(FD_ISSET(item->sock->sd, &fdInSet))
|
||||
{
|
||||
item->set |= SOCK_ACTIVITY_IN;
|
||||
}
|
||||
if(FD_ISSET(item->sock->sd, &fdOutSet))
|
||||
{
|
||||
item->set |= SOCK_ACTIVITY_OUT;
|
||||
}
|
||||
if(FD_ISSET(item->sock->sd, &fdErrSet))
|
||||
{
|
||||
item->set |= SOCK_ACTIVITY_ERR;
|
||||
}
|
||||
if(item->set)
|
||||
{
|
||||
processed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(activity);
|
||||
}
|
||||
|
||||
|
||||
int SocketGetAddress(platform_socket* sock, socket_address* addr)
|
||||
{
|
||||
sockaddr_in saddr;
|
||||
socklen_t sockLen = sizeof(saddr);
|
||||
if(getsockname(sock->sd, (sockaddr*)&saddr, &sockLen))
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
addr->ip = saddr.sin_addr.s_addr;
|
||||
addr->port = saddr.sin_port;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int SocketGetIFAddresses(int* count, net_ip* ips)
|
||||
{
|
||||
struct ifaddrs* ifaList = 0;
|
||||
if(getifaddrs(&ifaList))
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int maxCount = *count;
|
||||
int i = 0;
|
||||
|
||||
for(struct ifaddrs* ifa = ifaList; ifa != 0 ; ifa = ifa->ifa_next)
|
||||
{
|
||||
if(i >= maxCount)
|
||||
{
|
||||
freeifaddrs(ifaList);
|
||||
*count = i;
|
||||
return(-1);
|
||||
}
|
||||
if(ifa->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
struct in_addr in = ((sockaddr_in*)ifa->ifa_addr)->sin_addr;
|
||||
ips[i] = in.s_addr;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaList);
|
||||
*count = i;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int SocketSetReuseAddress(platform_socket* sock, bool enable)
|
||||
{
|
||||
int reuse = enable ? 1 : 0;
|
||||
return(setsockopt(sock->sd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)));
|
||||
}
|
||||
|
||||
int SocketSetReusePort(platform_socket* sock, bool enable)
|
||||
{
|
||||
int reuse = enable ? 1 : 0;
|
||||
return(setsockopt(sock->sd, SOL_SOCKET, SO_REUSEPORT, (char*)&reuse, sizeof(reuse)));
|
||||
}
|
||||
|
||||
int SocketSetMulticastLoop(platform_socket* sock, bool enable)
|
||||
{
|
||||
int on = enable ? 1 : 0;
|
||||
return(setsockopt(sock->sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&on, sizeof(on)));
|
||||
}
|
||||
|
||||
int SocketJoinMulticastGroup(platform_socket* sock, host_ip group, host_ip interface)
|
||||
{
|
||||
ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = HostToNetIP(group);
|
||||
mreq.imr_interface.s_addr = HostToNetIP(interface);
|
||||
return(setsockopt(sock->sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)));
|
||||
}
|
||||
|
||||
int SocketLeaveMulticastGroup(platform_socket* sock, host_ip group, host_ip interface)
|
||||
{
|
||||
ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = HostToNetIP(group);
|
||||
mreq.imr_interface.s_addr = HostToNetIP(interface);
|
||||
return(setsockopt(sock->sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&mreq, sizeof(mreq)));
|
||||
}
|
||||
|
||||
|
||||
net_ip SocketGetDefaultExternalIP()
|
||||
{
|
||||
//NOTE(martin): get the default local ip. This is a dumb way to do this
|
||||
// 'cause I can't be bothered to think of a better way right now :(
|
||||
|
||||
socket_address addr = {.ip = StringToNetIP("8.8.8.8"),
|
||||
.port = HostToNetPort(5001)};
|
||||
|
||||
platform_socket* sock = SocketOpen(SOCK_UDP);
|
||||
if(!sock)
|
||||
{
|
||||
log_error("can't create socket");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(SocketConnect(sock, &addr) != 0)
|
||||
{
|
||||
log_error("can't connect socket: %s\n", SocketGetLastErrorMessage());
|
||||
log_warning("try loopback interface\n");
|
||||
|
||||
addr.ip = HostToNetIP(SOCK_IP_LOOPBACK);
|
||||
if(SocketConnect(sock, &addr) != 0)
|
||||
{
|
||||
log_error("can't connect socket: %s\n", SocketGetLastErrorMessage());
|
||||
SocketClose(sock);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
SocketGetAddress(sock, &addr);
|
||||
SocketClose(sock);
|
||||
return(addr.ip);
|
||||
}
|
||||
|
||||
int SocketReceiveMessage(platform_socket* socket, socket_msg* msg, socket_address* from)
|
||||
{
|
||||
sockaddr_in saddr;
|
||||
|
||||
iovec iov;
|
||||
iov.iov_base = msg->messageBuffer;
|
||||
iov.iov_len = msg->messageBufferSize;
|
||||
|
||||
msghdr hdr;
|
||||
hdr.msg_name = &saddr;
|
||||
hdr.msg_namelen = sizeof(saddr);
|
||||
hdr.msg_iov = &iov;
|
||||
hdr.msg_iovlen = 1;
|
||||
hdr.msg_control = msg->controlBuffer;
|
||||
hdr.msg_controllen = msg->controlBufferSize;
|
||||
|
||||
int size = recvmsg(socket->sd, &hdr, 0);
|
||||
if(size <= 0)
|
||||
{
|
||||
return(size);
|
||||
}
|
||||
|
||||
from->ip = saddr.sin_addr.s_addr;
|
||||
from->port = saddr.sin_port;
|
||||
|
||||
msg->controlBufferSize = hdr.msg_controllen;
|
||||
msg->messageBufferSize = iov.iov_len;
|
||||
|
||||
return(size);
|
||||
}
|
|
@ -11,50 +11,54 @@
|
|||
#include<signal.h> //needed for pthread_kill() on linux
|
||||
#include<string.h>
|
||||
#include<sys/time.h>
|
||||
#include<unistd.h> // nanosleep()
|
||||
|
||||
#include"platform_thread.h"
|
||||
|
||||
struct mp_thread
|
||||
struct oc_thread
|
||||
{
|
||||
bool valid;
|
||||
pthread_t pthread;
|
||||
mp_thread_start_function start;
|
||||
oc_thread_start_function start;
|
||||
void* userPointer;
|
||||
char name[MP_THREAD_NAME_MAX_SIZE];
|
||||
oc_str8 name;
|
||||
char nameBuffer[OC_THREAD_NAME_MAX_SIZE];
|
||||
};
|
||||
|
||||
static void* mp_thread_bootstrap(void* data)
|
||||
static void* oc_thread_bootstrap(void* data)
|
||||
{
|
||||
mp_thread* thread = (mp_thread*)data;
|
||||
if(strlen(thread->name))
|
||||
oc_thread* thread = (oc_thread*)data;
|
||||
if(thread->name.len)
|
||||
{
|
||||
pthread_setname_np(thread->name);
|
||||
pthread_setname_np(thread->nameBuffer);
|
||||
}
|
||||
i32 exitCode = thread->start(thread->userPointer);
|
||||
return((void*)(ptrdiff_t)exitCode);
|
||||
}
|
||||
|
||||
mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* userPointer, const char* name)
|
||||
oc_thread* oc_thread_create_with_name(oc_thread_start_function start, void* userPointer, oc_str8 name)
|
||||
{
|
||||
mp_thread* thread = (mp_thread*)malloc(sizeof(mp_thread));
|
||||
oc_thread* thread = (oc_thread*)malloc(sizeof(oc_thread));
|
||||
if(!thread)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(name)
|
||||
if(name.len && name.ptr)
|
||||
{
|
||||
char* end = stpncpy(thread->name, name, MP_THREAD_NAME_MAX_SIZE-1);
|
||||
char* end = stpncpy(thread->nameBuffer, name.ptr, oc_min(name.len, OC_THREAD_NAME_MAX_SIZE-1));
|
||||
*end = '\0';
|
||||
thread->name = oc_str8_from_buffer(end - thread->nameBuffer, thread->nameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
thread->name[0] = '\0';
|
||||
thread->nameBuffer[0] = '\0';
|
||||
thread->name = oc_str8_from_buffer(0, thread->nameBuffer);
|
||||
}
|
||||
thread->start = start;
|
||||
thread->userPointer = userPointer;
|
||||
|
||||
if(pthread_create(&thread->pthread, 0, mp_thread_bootstrap, thread) != 0)
|
||||
if(pthread_create(&thread->pthread, 0, oc_thread_bootstrap, thread) != 0)
|
||||
{
|
||||
free(thread);
|
||||
return(0);
|
||||
|
@ -66,24 +70,24 @@ mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* user
|
|||
}
|
||||
}
|
||||
|
||||
mp_thread* mp_thread_create(mp_thread_start_function start, void* userPointer)
|
||||
oc_thread* oc_thread_create(oc_thread_start_function start, void* userPointer)
|
||||
{
|
||||
return(mp_thread_create_with_name(start, userPointer, 0));
|
||||
return(oc_thread_create_with_name(start, userPointer, (oc_str8){0}));
|
||||
}
|
||||
|
||||
const char* mp_thread_get_name(mp_thread* thread)
|
||||
oc_str8 oc_thread_get_name(oc_thread* thread)
|
||||
{
|
||||
return(thread->name);
|
||||
}
|
||||
|
||||
u64 mp_thread_unique_id(mp_thread* thread)
|
||||
u64 oc_thread_unique_id(oc_thread* thread)
|
||||
{
|
||||
u64 id;
|
||||
pthread_threadid_np(thread->pthread, &id);
|
||||
return(id);
|
||||
}
|
||||
|
||||
u64 mp_thread_self_id()
|
||||
u64 oc_thread_self_id()
|
||||
{
|
||||
pthread_t thread = pthread_self();
|
||||
u64 id;
|
||||
|
@ -91,12 +95,12 @@ u64 mp_thread_self_id()
|
|||
return(id);
|
||||
}
|
||||
|
||||
int mp_thread_signal(mp_thread* thread, int sig)
|
||||
int oc_thread_signal(oc_thread* thread, int sig)
|
||||
{
|
||||
return(pthread_kill(thread->pthread, sig));
|
||||
}
|
||||
|
||||
int mp_thread_join(mp_thread* thread, i64* exitCode)
|
||||
int oc_thread_join(oc_thread* thread, i64* exitCode)
|
||||
{
|
||||
void* ret;
|
||||
if(pthread_join(thread->pthread, &ret))
|
||||
|
@ -112,7 +116,7 @@ int mp_thread_join(mp_thread* thread, i64* exitCode)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int mp_thread_detach(mp_thread* thread)
|
||||
int oc_thread_detach(oc_thread* thread)
|
||||
{
|
||||
if(pthread_detach(thread->pthread))
|
||||
{
|
||||
|
@ -123,14 +127,14 @@ int mp_thread_detach(mp_thread* thread)
|
|||
}
|
||||
|
||||
|
||||
struct mp_mutex
|
||||
struct oc_mutex
|
||||
{
|
||||
pthread_mutex_t pmutex;
|
||||
};
|
||||
|
||||
mp_mutex* mp_mutex_create()
|
||||
oc_mutex* oc_mutex_create()
|
||||
{
|
||||
mp_mutex* mutex = (mp_mutex*)malloc(sizeof(mp_mutex));
|
||||
oc_mutex* mutex = (oc_mutex*)malloc(sizeof(oc_mutex));
|
||||
if(!mutex)
|
||||
{
|
||||
return(0);
|
||||
|
@ -143,7 +147,7 @@ mp_mutex* mp_mutex_create()
|
|||
return(mutex);
|
||||
}
|
||||
|
||||
int mp_mutex_destroy(mp_mutex* mutex)
|
||||
int oc_mutex_destroy(oc_mutex* mutex)
|
||||
{
|
||||
if(pthread_mutex_destroy(&mutex->pmutex) != 0)
|
||||
{
|
||||
|
@ -153,44 +157,44 @@ int mp_mutex_destroy(mp_mutex* mutex)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int mp_mutex_lock(mp_mutex* mutex)
|
||||
int oc_mutex_lock(oc_mutex* mutex)
|
||||
{
|
||||
return(pthread_mutex_lock(&mutex->pmutex));
|
||||
}
|
||||
|
||||
int mp_mutex_unlock(mp_mutex* mutex)
|
||||
int oc_mutex_unlock(oc_mutex* mutex)
|
||||
{
|
||||
return(pthread_mutex_unlock(&mutex->pmutex));
|
||||
}
|
||||
|
||||
// mp_ticket_spin_mutex has a mirrored implementation in win32_thread.c
|
||||
// oc_ticket has a mirrored implementation in win32_thread.c
|
||||
|
||||
void mp_ticket_spin_mutex_init(mp_ticket_spin_mutex* mutex)
|
||||
void oc_ticket_init(oc_ticket* mutex)
|
||||
{
|
||||
mutex->nextTicket = 0;
|
||||
mutex->serving = 0;
|
||||
}
|
||||
|
||||
void mp_ticket_spin_mutex_lock(mp_ticket_spin_mutex* mutex)
|
||||
void oc_ticket_lock(oc_ticket* mutex)
|
||||
{
|
||||
u64 ticket = atomic_fetch_add(&mutex->nextTicket, 1ULL);
|
||||
while(ticket != mutex->serving); //spin
|
||||
}
|
||||
|
||||
void mp_ticket_spin_mutex_unlock(mp_ticket_spin_mutex* mutex)
|
||||
void oc_ticket_unlock(oc_ticket* mutex)
|
||||
{
|
||||
atomic_fetch_add(&mutex->serving, 1ULL);
|
||||
}
|
||||
|
||||
|
||||
struct mp_condition
|
||||
struct oc_condition
|
||||
{
|
||||
pthread_cond_t pcond;
|
||||
};
|
||||
|
||||
mp_condition* mp_condition_create()
|
||||
oc_condition* oc_condition_create()
|
||||
{
|
||||
mp_condition* cond = (mp_condition*)malloc(sizeof(mp_condition));
|
||||
oc_condition* cond = (oc_condition*)malloc(sizeof(oc_condition));
|
||||
if(!cond)
|
||||
{
|
||||
return(0);
|
||||
|
@ -203,7 +207,7 @@ mp_condition* mp_condition_create()
|
|||
return(cond);
|
||||
}
|
||||
|
||||
int mp_condition_destroy(mp_condition* cond)
|
||||
int oc_condition_destroy(oc_condition* cond)
|
||||
{
|
||||
if(pthread_cond_destroy(&cond->pcond) != 0)
|
||||
{
|
||||
|
@ -213,12 +217,12 @@ int mp_condition_destroy(mp_condition* cond)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int mp_condition_wait(mp_condition* cond, mp_mutex* mutex)
|
||||
int oc_condition_wait(oc_condition* cond, oc_mutex* mutex)
|
||||
{
|
||||
return(pthread_cond_wait(&cond->pcond, &mutex->pmutex));
|
||||
}
|
||||
|
||||
int mp_condition_timedwait(mp_condition* cond, mp_mutex* mutex, f64 seconds)
|
||||
int oc_condition_timedwait(oc_condition* cond, oc_mutex* mutex, f64 seconds)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
|
@ -235,12 +239,21 @@ int mp_condition_timedwait(mp_condition* cond, mp_mutex* mutex, f64 seconds)
|
|||
return(pthread_cond_timedwait(&cond->pcond, &mutex->pmutex, &ts));
|
||||
}
|
||||
|
||||
int mp_condition_signal(mp_condition* cond)
|
||||
int oc_condition_signal(oc_condition* cond)
|
||||
{
|
||||
return(pthread_cond_signal(&cond->pcond));
|
||||
}
|
||||
|
||||
int mp_condition_broadcast(mp_condition* cond)
|
||||
int oc_condition_broadcast(oc_condition* cond)
|
||||
{
|
||||
return(pthread_cond_broadcast(&cond->pcond));
|
||||
}
|
||||
|
||||
|
||||
void oc_sleep_nano(u64 nanoseconds)
|
||||
{
|
||||
timespec rqtp;
|
||||
rqtp.tv_sec = nanoseconds / 1000000000;
|
||||
rqtp.tv_nsec = nanoseconds - rqtp.tv_sec * 1000000000;
|
||||
nanosleep(&rqtp, 0);
|
||||
}
|
||||
|
|
|
@ -12,27 +12,27 @@
|
|||
/*NOTE(martin):
|
||||
Linux and MacOS don't make a distinction between reserved and committed memory, contrary to Windows
|
||||
*/
|
||||
void mem_base_nop(mem_base_allocator* context, void* ptr, u64 size) {}
|
||||
void oc_base_nop(oc_base_allocator* context, void* ptr, u64 size) {}
|
||||
|
||||
void* mem_base_reserve_mmap(mem_base_allocator* context, u64 size)
|
||||
void* oc_base_reserve_mmap(oc_base_allocator* context, u64 size)
|
||||
{
|
||||
return(mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0));
|
||||
}
|
||||
|
||||
void mem_base_release_mmap(mem_base_allocator* context, void* ptr, u64 size)
|
||||
void oc_base_release_mmap(oc_base_allocator* context, void* ptr, u64 size)
|
||||
{
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
mem_base_allocator* mem_base_allocator_default()
|
||||
oc_base_allocator* oc_base_allocator_default()
|
||||
{
|
||||
static mem_base_allocator base = {};
|
||||
static oc_base_allocator base = {};
|
||||
if(base.reserve == 0)
|
||||
{
|
||||
base.reserve = mem_base_reserve_mmap;
|
||||
base.commit = mem_base_nop;
|
||||
base.decommit = mem_base_nop;
|
||||
base.release = mem_base_release_mmap;
|
||||
base.reserve = oc_base_reserve_mmap;
|
||||
base.commit = oc_base_nop;
|
||||
base.decommit = oc_base_nop;
|
||||
base.release = oc_base_release_mmap;
|
||||
}
|
||||
return(&base);
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: unix_rng.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 06/03/2020
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
|
||||
#include"platform_debug.h"
|
||||
#include"typedefs.h"
|
||||
|
||||
int RandomSeedFromDevice()
|
||||
{
|
||||
FILE* urandom = fopen("/dev/urandom", "r");
|
||||
if(!urandom)
|
||||
{
|
||||
log_error("can't open /dev/urandom\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
u32 u;
|
||||
char buff[4];
|
||||
} seed;
|
||||
|
||||
int size = fread(seed.buff, 1, 4, urandom);
|
||||
if(size != 4)
|
||||
{
|
||||
log_error("couldn't read from /dev/urandom\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
fclose(urandom);
|
||||
srandom(seed.u);
|
||||
return(0);
|
||||
}
|
||||
|
||||
u32 RandomU32()
|
||||
{
|
||||
u32 u1 = (u32)random();
|
||||
u32 u2 = (u32)random();
|
||||
return((u1<<1) | (u2 & 0x01));
|
||||
}
|
||||
|
||||
u64 RandomU64()
|
||||
{
|
||||
u64 u1 = (u64)random();
|
||||
u64 u2 = (u64)random();
|
||||
u64 u3 = (u64)random();
|
||||
return((u1<<33) | (u2<<2) | (u3 & 0x03));
|
||||
}
|
|
@ -17,14 +17,14 @@ extern "C" {
|
|||
|
||||
static u64 __performanceCounterFreq = 0;
|
||||
|
||||
void mp_clock_init()
|
||||
void oc_clock_init()
|
||||
{
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
__performanceCounterFreq = freq.QuadPart;
|
||||
}
|
||||
|
||||
f64 mp_get_time(mp_clock_kind clock)
|
||||
f64 oc_clock_time(oc_clock_kind clock)
|
||||
{
|
||||
LARGE_INTEGER counter;
|
||||
QueryPerformanceCounter(&counter);
|
||||
|
|
|
@ -15,72 +15,72 @@
|
|||
#include"platform_io_internal.c"
|
||||
#include"platform_io_common.c"
|
||||
|
||||
io_error io_raw_last_error()
|
||||
oc_io_error oc_io_raw_last_error()
|
||||
{
|
||||
io_error error = 0;
|
||||
oc_io_error error = 0;
|
||||
|
||||
int winError = GetLastError();
|
||||
switch(winError)
|
||||
{
|
||||
case ERROR_SUCCESS:
|
||||
error = IO_OK;
|
||||
error = OC_IO_OK;
|
||||
break;
|
||||
|
||||
case ERROR_ACCESS_DENIED:
|
||||
error = IO_ERR_PERM;
|
||||
error = OC_IO_ERR_PERM;
|
||||
break;
|
||||
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
case ERROR_DIRECTORY:
|
||||
error = IO_ERR_NO_ENTRY;
|
||||
error = OC_IO_ERR_NO_ENTRY;
|
||||
break;
|
||||
|
||||
case ERROR_TOO_MANY_OPEN_FILES:
|
||||
error = IO_ERR_MAX_FILES;
|
||||
error = OC_IO_ERR_MAX_FILES;
|
||||
break;
|
||||
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
case ERROR_OUTOFMEMORY:
|
||||
error = IO_ERR_MEM;
|
||||
error = OC_IO_ERR_MEM;
|
||||
break;
|
||||
|
||||
case ERROR_DEV_NOT_EXIST:
|
||||
error = IO_ERR_NO_DEVICE;
|
||||
error = OC_IO_ERR_NO_DEVICE;
|
||||
break;
|
||||
|
||||
case ERROR_FILE_EXISTS:
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
error = IO_ERR_EXISTS;
|
||||
error = OC_IO_ERR_EXISTS;
|
||||
break;
|
||||
|
||||
case ERROR_BUFFER_OVERFLOW:
|
||||
case ERROR_FILENAME_EXCED_RANGE:
|
||||
error = IO_ERR_PATH_LENGTH;
|
||||
error = OC_IO_ERR_PATH_LENGTH;
|
||||
break;
|
||||
|
||||
case ERROR_FILE_TOO_LARGE:
|
||||
error = IO_ERR_FILE_SIZE;
|
||||
error = OC_IO_ERR_FILE_SIZE;
|
||||
break;
|
||||
|
||||
//TODO: complete
|
||||
|
||||
default:
|
||||
error = IO_ERR_UNKNOWN;
|
||||
error = OC_IO_ERR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
str16 win32_path_from_handle_null_terminated(mem_arena* arena, HANDLE handle)
|
||||
static oc_str16 win32_path_from_handle_null_terminated(oc_arena* arena, HANDLE handle)
|
||||
{
|
||||
str16 res = {0};
|
||||
oc_str16 res = {0};
|
||||
|
||||
res.len = GetFinalPathNameByHandleW(handle, NULL, 0, FILE_NAME_NORMALIZED);
|
||||
if(res.len)
|
||||
{
|
||||
res.ptr = mem_arena_alloc_array(arena, u16, res.len);
|
||||
res.ptr = oc_arena_push_array(arena, u16, res.len);
|
||||
if(!GetFinalPathNameByHandleW(handle, res.ptr, res.len, FILE_NAME_NORMALIZED))
|
||||
{
|
||||
res.len = 0;
|
||||
|
@ -90,36 +90,36 @@ str16 win32_path_from_handle_null_terminated(mem_arena* arena, HANDLE handle)
|
|||
return(res);
|
||||
}
|
||||
|
||||
typedef HANDLE io_file_desc;
|
||||
typedef HANDLE oc_file_desc;
|
||||
|
||||
io_file_desc io_file_desc_nil()
|
||||
oc_file_desc oc_file_desc_nil()
|
||||
{
|
||||
return(INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
bool io_file_desc_is_nil(io_file_desc fd)
|
||||
bool oc_file_desc_is_nil(oc_file_desc fd)
|
||||
{
|
||||
return(fd == NULL || fd == INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
str16 win32_get_path_at_null_terminated(mem_arena* arena, io_file_desc dirFd, str8 path)
|
||||
static oc_str16 win32_get_path_at_null_terminated(oc_arena* arena, oc_file_desc dirFd, oc_str8 path)
|
||||
{
|
||||
str16 result = {0};
|
||||
mem_arena_scope scratch = mem_scratch_begin_next(arena);
|
||||
oc_str16 result = {0};
|
||||
oc_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||
|
||||
str16 dirPathW = win32_path_from_handle_null_terminated(scratch.arena, dirFd);
|
||||
str16 pathW = win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||
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);
|
||||
|
||||
if(dirPathW.len && pathW.len)
|
||||
{
|
||||
u64 fullPathWSize = dirPathW.len + pathW.len;
|
||||
LPWSTR fullPathW = mem_arena_alloc_array(scratch.arena, u16, fullPathWSize);
|
||||
LPWSTR fullPathW = oc_arena_push_array(scratch.arena, u16, fullPathWSize);
|
||||
memcpy(fullPathW, dirPathW.ptr, (dirPathW.len-1)*sizeof(u16));
|
||||
fullPathW[dirPathW.len-1] = '\\';
|
||||
memcpy(fullPathW + dirPathW.len, pathW.ptr, pathW.len*sizeof(u16));
|
||||
|
||||
result.len = fullPathWSize;
|
||||
result.ptr = mem_arena_alloc_array(arena, wchar_t, result.len);
|
||||
result.ptr = oc_arena_push_array(arena, wchar_t, result.len);
|
||||
|
||||
if(PathCanonicalizeW(result.ptr, fullPathW))
|
||||
{
|
||||
|
@ -131,12 +131,12 @@ str16 win32_get_path_at_null_terminated(mem_arena* arena, io_file_desc dirFd, st
|
|||
result.len = 0;
|
||||
}
|
||||
}
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights accessRights, file_open_flags openFlags)
|
||||
oc_file_desc oc_io_raw_open_at(oc_file_desc dirFd, oc_str8 path, oc_file_access accessRights, oc_file_open_flags openFlags)
|
||||
{
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
|
@ -147,13 +147,13 @@ io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights ac
|
|||
DWORD win32AttributeFlags = FILE_ATTRIBUTE_NORMAL
|
||||
| FILE_FLAG_BACKUP_SEMANTICS;
|
||||
|
||||
if(accessRights & FILE_ACCESS_READ)
|
||||
if(accessRights & OC_FILE_ACCESS_READ)
|
||||
{
|
||||
win32AccessFlags |= GENERIC_READ;
|
||||
}
|
||||
if(accessRights & FILE_ACCESS_WRITE)
|
||||
if(accessRights & OC_FILE_ACCESS_WRITE)
|
||||
{
|
||||
if(accessRights & FILE_OPEN_APPEND)
|
||||
if(accessRights & OC_FILE_OPEN_APPEND)
|
||||
{
|
||||
win32AccessFlags |= FILE_APPEND_DATA;
|
||||
}
|
||||
|
@ -163,9 +163,9 @@ io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights ac
|
|||
}
|
||||
}
|
||||
|
||||
if(openFlags & FILE_OPEN_TRUNCATE)
|
||||
if(openFlags & OC_FILE_OPEN_TRUNCATE)
|
||||
{
|
||||
if(openFlags & FILE_OPEN_CREATE)
|
||||
if(openFlags & OC_FILE_OPEN_CREATE)
|
||||
{
|
||||
win32CreateFlags |= CREATE_ALWAYS;
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights ac
|
|||
win32CreateFlags |= TRUNCATE_EXISTING;
|
||||
}
|
||||
}
|
||||
if(openFlags & FILE_OPEN_CREATE)
|
||||
if(openFlags & OC_FILE_OPEN_CREATE)
|
||||
{
|
||||
if(!(win32CreateFlags & CREATE_ALWAYS))
|
||||
{
|
||||
|
@ -188,13 +188,13 @@ io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights ac
|
|||
win32CreateFlags |= OPEN_EXISTING;
|
||||
}
|
||||
|
||||
if(openFlags & FILE_OPEN_SYMLINK)
|
||||
if(openFlags & OC_FILE_OPEN_SYMLINK)
|
||||
{
|
||||
win32AttributeFlags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
}
|
||||
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
str16 pathW = win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||
|
||||
if(dirFd == NULL || dirFd == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
|
@ -202,41 +202,41 @@ io_file_desc io_raw_open_at(io_file_desc dirFd, str8 path, file_access_rights ac
|
|||
}
|
||||
else
|
||||
{
|
||||
str16 fullPathW = win32_get_path_at_null_terminated(scratch.arena, dirFd, path);
|
||||
oc_str16 fullPathW = win32_get_path_at_null_terminated(scratch.arena, dirFd, path);
|
||||
if(fullPathW.len)
|
||||
{
|
||||
handle = CreateFileW(fullPathW.ptr, win32AccessFlags, win32ShareMode, NULL, win32CreateFlags, win32AttributeFlags, NULL);
|
||||
}
|
||||
}
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
return(handle);
|
||||
}
|
||||
|
||||
void io_raw_close(io_file_desc fd)
|
||||
void oc_io_raw_close(oc_file_desc fd)
|
||||
{
|
||||
CloseHandle(fd);
|
||||
}
|
||||
|
||||
bool io_raw_file_exists_at(io_file_desc dirFd, str8 path, file_open_flags openFlags)
|
||||
bool oc_io_raw_file_exists_at(oc_file_desc dirFd, oc_str8 path, oc_file_open_flags openFlags)
|
||||
{
|
||||
bool result = false;
|
||||
io_file_desc fd = io_raw_open_at(dirFd, path, FILE_ACCESS_NONE, (openFlags & FILE_OPEN_SYMLINK));
|
||||
if(!io_file_desc_is_nil(fd))
|
||||
oc_file_desc fd = oc_io_raw_open_at(dirFd, path, OC_FILE_ACCESS_NONE, (openFlags & OC_FILE_OPEN_SYMLINK));
|
||||
if(!oc_file_desc_is_nil(fd))
|
||||
{
|
||||
result = true;
|
||||
io_raw_close(fd);
|
||||
oc_io_raw_close(fd);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
io_error io_raw_fstat(io_file_desc fd, file_status* status)
|
||||
oc_io_error oc_io_raw_fstat(oc_file_desc fd, oc_file_status* status)
|
||||
{
|
||||
io_error error = IO_OK;
|
||||
oc_io_error error = OC_IO_OK;
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
if(!GetFileInformationByHandle(fd, &info))
|
||||
{
|
||||
error = io_raw_last_error();
|
||||
error = oc_io_raw_last_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -260,53 +260,53 @@ io_error io_raw_fstat(io_file_desc fd, file_status* status)
|
|||
FILE_ATTRIBUTE_TAG_INFO tagInfo;
|
||||
if(!GetFileInformationByHandleEx(fd, FileAttributeTagInfo, &tagInfo, sizeof(tagInfo)))
|
||||
{
|
||||
error = io_raw_last_error();
|
||||
error = oc_io_raw_last_error();
|
||||
}
|
||||
else if(tagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||
{
|
||||
status->type = MP_FILE_SYMLINK;
|
||||
status->type = OC_FILE_SYMLINK;
|
||||
}
|
||||
else
|
||||
{
|
||||
status->type = MP_FILE_UNKNOWN;
|
||||
status->type = OC_FILE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
else if(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
status->type = MP_FILE_DIRECTORY;
|
||||
status->type = OC_FILE_DIRECTORY;
|
||||
}
|
||||
else if(info.dwFileAttributes & attrRegularSet)
|
||||
{
|
||||
status->type = MP_FILE_REGULAR;
|
||||
status->type = OC_FILE_REGULAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: might want to check for socket/block/character devices? (otoh MS STL impl. doesn't seem to do it)
|
||||
status->type = MP_FILE_UNKNOWN;
|
||||
status->type = OC_FILE_UNKNOWN;
|
||||
}
|
||||
|
||||
status->perm = MP_FILE_OWNER_READ | MP_FILE_GROUP_READ | MP_FILE_OTHER_READ;
|
||||
status->perm = OC_FILE_OWNER_READ | OC_FILE_GROUP_READ | OC_FILE_OTHER_READ;
|
||||
if(!(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
|
||||
{
|
||||
status->perm = MP_FILE_OWNER_WRITE | MP_FILE_GROUP_WRITE | MP_FILE_OTHER_WRITE;
|
||||
status->perm = OC_FILE_OWNER_WRITE | OC_FILE_GROUP_WRITE | OC_FILE_OTHER_WRITE;
|
||||
}
|
||||
//TODO: times
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
io_error io_raw_fstat_at(io_file_desc dirFd, str8 name, file_open_flags openFlags, file_status* status)
|
||||
oc_io_error oc_io_raw_fstat_at(oc_file_desc dirFd, oc_str8 name, oc_file_open_flags openFlags, oc_file_status* status)
|
||||
{
|
||||
io_error error = IO_OK;
|
||||
io_file_desc fd = io_raw_open_at(dirFd, name, FILE_ACCESS_NONE, FILE_OPEN_SYMLINK);
|
||||
if(io_file_desc_is_nil(fd))
|
||||
oc_io_error error = OC_IO_OK;
|
||||
oc_file_desc fd = oc_io_raw_open_at(dirFd, name, OC_FILE_ACCESS_NONE, OC_FILE_OPEN_SYMLINK);
|
||||
if(oc_file_desc_is_nil(fd))
|
||||
{
|
||||
error = io_raw_last_error();
|
||||
error = oc_io_raw_last_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
error = io_raw_fstat(fd, status);
|
||||
io_raw_close(fd);
|
||||
error = oc_io_raw_fstat(fd, status);
|
||||
oc_io_raw_close(fd);
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
@ -342,88 +342,88 @@ typedef struct
|
|||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
};
|
||||
} REPARSE_DATA_BUFFER;
|
||||
} oc_win32_reparse_data_buffer;
|
||||
|
||||
io_raw_read_link_result io_raw_read_link(mem_arena* arena, io_file_desc fd)
|
||||
oc_io_raw_read_link_result oc_io_raw_read_link(oc_arena* arena, oc_file_desc fd)
|
||||
{
|
||||
io_raw_read_link_result result = {0};
|
||||
oc_io_raw_read_link_result result = {0};
|
||||
|
||||
char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
DWORD bytesReturned;
|
||||
|
||||
if(!DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, 0))
|
||||
{
|
||||
result.error = io_raw_last_error();
|
||||
result.error = oc_io_raw_last_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
REPARSE_DATA_BUFFER* reparse = (REPARSE_DATA_BUFFER*)buffer;
|
||||
oc_win32_reparse_data_buffer* reparse = (oc_win32_reparse_data_buffer*)buffer;
|
||||
if(reparse->ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||
{
|
||||
str16 nameW = {0};
|
||||
oc_str16 nameW = {0};
|
||||
nameW.len = reparse->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
|
||||
nameW.ptr = (u16*)((char*)reparse->SymbolicLinkReparseBuffer.PathBuffer + reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset);
|
||||
result.target = win32_wide_to_utf8(arena, nameW);
|
||||
result.target = oc_win32_wide_to_utf8(arena, nameW);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.error = IO_ERR_UNKNOWN;
|
||||
result.error = OC_IO_ERR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
io_raw_read_link_result io_raw_read_link_at(mem_arena* arena, io_file_desc dirFd, str8 name)
|
||||
oc_io_raw_read_link_result oc_io_raw_read_link_at(oc_arena* arena, oc_file_desc dirFd, oc_str8 name)
|
||||
{
|
||||
io_file_desc fd = io_raw_open_at(dirFd, name, FILE_ACCESS_READ, FILE_OPEN_SYMLINK);
|
||||
io_raw_read_link_result result = io_raw_read_link(arena, fd);
|
||||
io_raw_close(fd);
|
||||
oc_file_desc fd = oc_io_raw_open_at(dirFd, name, OC_FILE_ACCESS_READ, OC_FILE_OPEN_SYMLINK);
|
||||
oc_io_raw_read_link_result result = oc_io_raw_read_link(arena, fd);
|
||||
oc_io_raw_close(fd);
|
||||
return(result);
|
||||
}
|
||||
|
||||
io_cmp io_close(file_slot* slot, io_req* req, file_table* table)
|
||||
static oc_io_cmp oc_io_close(oc_file_slot* slot, oc_io_req* req, oc_file_table* table)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
if(slot->fd)
|
||||
{
|
||||
CloseHandle(slot->fd);
|
||||
}
|
||||
file_slot_recycle(table, slot);
|
||||
oc_file_slot_recycle(table, slot);
|
||||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_fstat(file_slot* slot, io_req* req)
|
||||
static oc_io_cmp oc_io_fstat(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
if(req->size < sizeof(file_status))
|
||||
if(req->size < sizeof(oc_file_status))
|
||||
{
|
||||
cmp.error = IO_ERR_ARG;
|
||||
cmp.error = OC_IO_ERR_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
slot->error = io_raw_fstat(slot->fd, (file_status*)req->buffer);
|
||||
slot->error = oc_io_raw_fstat(slot->fd, (oc_file_status*)req->buffer);
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_seek(file_slot* slot, io_req* req)
|
||||
static oc_io_cmp oc_io_seek(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
DWORD whence;
|
||||
switch(req->whence)
|
||||
{
|
||||
case FILE_SEEK_CURRENT:
|
||||
case OC_FILE_SEEK_CURRENT:
|
||||
whence = FILE_CURRENT;
|
||||
break;
|
||||
|
||||
case FILE_SEEK_SET:
|
||||
case OC_FILE_SEEK_SET:
|
||||
whence = FILE_BEGIN;
|
||||
break;
|
||||
|
||||
case FILE_SEEK_END:
|
||||
case OC_FILE_SEEK_END:
|
||||
whence = FILE_END;
|
||||
}
|
||||
|
||||
|
@ -432,7 +432,7 @@ io_cmp io_seek(file_slot* slot, io_req* req)
|
|||
|
||||
if(!SetFilePointerEx(slot->fd, off, &newPos, whence))
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
else
|
||||
|
@ -443,13 +443,13 @@ io_cmp io_seek(file_slot* slot, io_req* req)
|
|||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_read(file_slot* slot, io_req* req)
|
||||
static oc_io_cmp oc_io_read(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
if(slot->type != MP_FILE_REGULAR)
|
||||
if(slot->type != OC_FILE_REGULAR)
|
||||
{
|
||||
slot->error = IO_ERR_PERM;
|
||||
slot->error = OC_IO_ERR_PERM;
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
else
|
||||
|
@ -458,7 +458,7 @@ io_cmp io_read(file_slot* slot, io_req* req)
|
|||
|
||||
if(!ReadFile(slot->fd, req->buffer, req->size, &bytesRead, NULL))
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
cmp.result = 0;
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
|
@ -470,13 +470,13 @@ io_cmp io_read(file_slot* slot, io_req* req)
|
|||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_write(file_slot* slot, io_req* req)
|
||||
static oc_io_cmp oc_io_write(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
if(slot->type != MP_FILE_REGULAR)
|
||||
if(slot->type != OC_FILE_REGULAR)
|
||||
{
|
||||
slot->error = IO_ERR_PERM;
|
||||
slot->error = OC_IO_ERR_PERM;
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
else
|
||||
|
@ -485,7 +485,7 @@ io_cmp io_write(file_slot* slot, io_req* req)
|
|||
|
||||
if(!WriteFile(slot->fd, req->buffer, req->size, &bytesWritten, NULL))
|
||||
{
|
||||
slot->error = io_raw_last_error();
|
||||
slot->error = oc_io_raw_last_error();
|
||||
cmp.result = 0;
|
||||
cmp.error = slot->error;
|
||||
}
|
||||
|
@ -497,64 +497,64 @@ io_cmp io_write(file_slot* slot, io_req* req)
|
|||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_get_error(file_slot* slot, io_req* req)
|
||||
static oc_io_cmp oc_io_get_error(oc_file_slot* slot, oc_io_req* req)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
cmp.result = slot->error;
|
||||
return(cmp);
|
||||
}
|
||||
|
||||
io_cmp io_wait_single_req_with_table(io_req* req, file_table* table)
|
||||
oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table)
|
||||
{
|
||||
io_cmp cmp = {0};
|
||||
oc_io_cmp cmp = {0};
|
||||
|
||||
file_slot* slot = file_slot_from_handle(table, req->handle);
|
||||
oc_file_slot* slot = oc_file_slot_from_handle(table, req->handle);
|
||||
if(!slot)
|
||||
{
|
||||
if(req->op != IO_OP_OPEN_AT)
|
||||
if(req->op != OC_IO_OPEN_AT)
|
||||
{
|
||||
cmp.error = IO_ERR_HANDLE;
|
||||
cmp.error = OC_IO_ERR_HANDLE;
|
||||
}
|
||||
}
|
||||
else if(slot->fatal && req->op != IO_OP_CLOSE && req->op != IO_OP_ERROR)
|
||||
else if(slot->fatal && req->op != OC_IO_CLOSE && req->op != OC_OC_IO_ERROR)
|
||||
{
|
||||
cmp.error = IO_ERR_PREV;
|
||||
cmp.error = OC_IO_ERR_PREV;
|
||||
}
|
||||
|
||||
if(cmp.error == IO_OK)
|
||||
if(cmp.error == OC_IO_OK)
|
||||
{
|
||||
switch(req->op)
|
||||
{
|
||||
case IO_OP_OPEN_AT:
|
||||
cmp = io_open_at(slot, req, table);
|
||||
case OC_IO_OPEN_AT:
|
||||
cmp = oc_io_open_at(slot, req, table);
|
||||
break;
|
||||
|
||||
case IO_OP_FSTAT:
|
||||
cmp = io_fstat(slot, req);
|
||||
case OC_IO_FSTAT:
|
||||
cmp = oc_io_fstat(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_CLOSE:
|
||||
cmp = io_close(slot, req, table);
|
||||
case OC_IO_CLOSE:
|
||||
cmp = oc_io_close(slot, req, table);
|
||||
break;
|
||||
|
||||
case IO_OP_READ:
|
||||
cmp = io_read(slot, req);
|
||||
case OC_IO_READ:
|
||||
cmp = oc_io_read(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_WRITE:
|
||||
cmp = io_write(slot, req);
|
||||
case OC_IO_WRITE:
|
||||
cmp = oc_io_write(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_SEEK:
|
||||
cmp = io_seek(slot, req);
|
||||
case OC_IO_SEEK:
|
||||
cmp = oc_io_seek(slot, req);
|
||||
break;
|
||||
|
||||
case IO_OP_ERROR:
|
||||
cmp = io_get_error(slot, req);
|
||||
case OC_OC_IO_ERROR:
|
||||
cmp = oc_io_get_error(slot, req);
|
||||
break;
|
||||
|
||||
default:
|
||||
cmp.error = IO_ERR_OP;
|
||||
cmp.error = OC_IO_ERR_OP;
|
||||
if(slot)
|
||||
{
|
||||
slot->error = cmp.error;
|
||||
|
|
|
@ -10,36 +10,36 @@
|
|||
#include<windows.h>
|
||||
#include"platform_memory.h"
|
||||
|
||||
void* mem_base_reserve_win32(mem_base_allocator* context, u64 size)
|
||||
void* oc_base_reserve_win32(oc_base_allocator* context, u64 size)
|
||||
{
|
||||
void* result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
||||
return(result);
|
||||
}
|
||||
|
||||
void mem_base_commit_win32(mem_base_allocator* context, void* ptr, u64 size)
|
||||
void oc_base_commit_win32(oc_base_allocator* context, void* ptr, u64 size)
|
||||
{
|
||||
VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void mem_base_release_win32(mem_base_allocator* context, void* ptr, u64 size)
|
||||
void oc_base_release_win32(oc_base_allocator* context, void* ptr, u64 size)
|
||||
{
|
||||
VirtualFree(ptr, size, MEM_RELEASE);
|
||||
}
|
||||
|
||||
void mem_base_decommit_win32(mem_base_allocator* context, void* ptr, u64 size)
|
||||
void oc_base_decommit_win32(oc_base_allocator* context, void* ptr, u64 size)
|
||||
{
|
||||
VirtualFree(ptr, size, MEM_DECOMMIT);
|
||||
}
|
||||
|
||||
mem_base_allocator* mem_base_allocator_default()
|
||||
oc_base_allocator* oc_base_allocator_default()
|
||||
{
|
||||
static mem_base_allocator base = {0};
|
||||
static oc_base_allocator base = {0};
|
||||
if(base.reserve == 0)
|
||||
{
|
||||
base.reserve = mem_base_reserve_win32;
|
||||
base.commit = mem_base_commit_win32;
|
||||
base.decommit = mem_base_decommit_win32;
|
||||
base.release = mem_base_release_win32;
|
||||
base.reserve = oc_base_reserve_win32;
|
||||
base.commit = oc_base_commit_win32;
|
||||
base.decommit = oc_base_decommit_win32;
|
||||
base.release = oc_base_release_win32;
|
||||
}
|
||||
return(&base);
|
||||
}
|
||||
|
|
|
@ -10,23 +10,23 @@
|
|||
#include"win32_string_helpers.h"
|
||||
#include"platform_path.c"
|
||||
|
||||
bool path_is_absolute(str8 path)
|
||||
bool oc_path_is_absolute(oc_str8 path)
|
||||
{
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
str16 pathW = win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||
oc_arena_scope scratch = oc_scratch_begin();
|
||||
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||
bool result = !PathIsRelativeW(pathW.ptr);
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
oc_scratch_end(scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
str8 path_executable(mem_arena* arena)
|
||||
oc_str8 oc_path_executable(oc_arena* arena)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//TODO use wide chars
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
char* buffer = mem_arena_alloc_array(arena, char, MAX_PATH+2);
|
||||
char* buffer = oc_arena_push_array(arena, char, MAX_PATH+2);
|
||||
int size = GetModuleFileName(NULL, buffer, MAX_PATH+1);
|
||||
//TODO: check for errors...
|
||||
for(int i=0; i<size; i++)
|
||||
|
@ -36,7 +36,7 @@ str8 path_executable(mem_arena* arena)
|
|||
buffer[i] = '/';
|
||||
}
|
||||
}
|
||||
return(str8_from_buffer(size, buffer));
|
||||
return(oc_str8_from_buffer(size, buffer));
|
||||
}
|
||||
|
||||
str8 path_canonical(mem_arena* arena, str8 path); //TODO
|
||||
oc_str8 oc_path_canonical(oc_arena* arena, oc_str8 path); //TODO
|
||||
|
|
|
@ -11,21 +11,21 @@
|
|||
|
||||
#include"win32_string_helpers.h"
|
||||
|
||||
str16 win32_utf8_to_wide_null_terminated(mem_arena* arena, str8 s)
|
||||
oc_str16 oc_win32_utf8_to_wide_null_terminated(oc_arena* arena, oc_str8 s)
|
||||
{
|
||||
str16 res = {0};
|
||||
oc_str16 res = {0};
|
||||
res.len = 1 + MultiByteToWideChar(CP_UTF8, 0, s.ptr, s.len, NULL, 0);
|
||||
res.ptr = mem_arena_alloc_array(arena, u16, res.len);
|
||||
res.ptr = oc_arena_push_array(arena, u16, res.len);
|
||||
MultiByteToWideChar(CP_UTF8, 0, s.ptr, s.len, res.ptr, res.len);
|
||||
res.ptr[res.len-1] = '\0';
|
||||
return(res);
|
||||
}
|
||||
|
||||
str8 win32_wide_to_utf8(mem_arena* arena, str16 s)
|
||||
oc_str8 oc_win32_wide_to_utf8(oc_arena* arena, oc_str16 s)
|
||||
{
|
||||
str8 res = {0};
|
||||
oc_str8 res = {0};
|
||||
res.len = WideCharToMultiByte(CP_UTF8, 0, s.ptr, s.len, NULL, 0, NULL, NULL);
|
||||
res.ptr = mem_arena_alloc_array(arena, u8, res.len);
|
||||
res.ptr = oc_arena_push_array(arena, u8, res.len);
|
||||
WideCharToMultiByte(CP_UTF8, 0, s.ptr, s.len, res.ptr, res.len, NULL, NULL);
|
||||
return(res);
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
#include"util/strings.h"
|
||||
|
||||
str16 win32_utf8_to_wide_null_terminated(mem_arena* arena, str8 s);
|
||||
str8 win32_wide_to_utf8(mem_arena* arena, str16 s);
|
||||
oc_str16 oc_win32_utf8_to_wide_null_terminated(oc_arena* arena, oc_str8 s);
|
||||
oc_str8 oc_win32_wide_to_utf8(oc_arena* arena, oc_str16 s);
|
||||
|
||||
|
||||
#endif // __WIN32_STRING_HELPERS_H_
|
||||
|
|
|
@ -12,36 +12,39 @@
|
|||
|
||||
#include"platform_thread.h"
|
||||
|
||||
struct mp_thread
|
||||
struct oc_thread
|
||||
{
|
||||
mp_thread_start_function start;
|
||||
oc_thread_start_function start;
|
||||
HANDLE handle;
|
||||
DWORD threadId;
|
||||
void* userPointer;
|
||||
char name[MP_THREAD_NAME_MAX_SIZE];
|
||||
oc_str8 name;
|
||||
char nameBuffer[OC_THREAD_NAME_MAX_SIZE];
|
||||
};
|
||||
|
||||
static DWORD WINAPI mp_thread_bootstrap(LPVOID lpParameter)
|
||||
static DWORD WINAPI oc_thread_bootstrap(LPVOID lpParameter)
|
||||
{
|
||||
mp_thread* thread = (mp_thread*)lpParameter;
|
||||
oc_thread* thread = (oc_thread*)lpParameter;
|
||||
i32 exitCode = thread->start(thread->userPointer);
|
||||
return(exitCode);
|
||||
}
|
||||
|
||||
mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* userPointer, const char* name)
|
||||
oc_thread* oc_thread_create_with_name(oc_thread_start_function start, void* userPointer, oc_str8 name)
|
||||
{
|
||||
mp_thread* thread = (mp_thread*)malloc(sizeof(mp_thread));
|
||||
oc_thread* thread = (oc_thread*)malloc(sizeof(oc_thread));
|
||||
thread->start = start;
|
||||
thread->handle = INVALID_HANDLE_VALUE;
|
||||
thread->userPointer = userPointer;
|
||||
if(name)
|
||||
if(name.len && name.ptr)
|
||||
{
|
||||
char* end = strncpy(thread->name, name, MP_THREAD_NAME_MAX_SIZE-1);
|
||||
*end = '\0';
|
||||
strncpy(thread->nameBuffer, name.ptr, oc_min(name.len, OC_THREAD_NAME_MAX_SIZE-1));
|
||||
thread->nameBuffer[OC_THREAD_NAME_MAX_SIZE-1] = '\0';
|
||||
thread->name = OC_STR8(thread->nameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
thread->name[0] = '\0';
|
||||
thread->nameBuffer[0] = '\0';
|
||||
thread->name = oc_str8_from_buffer(0, thread->nameBuffer);
|
||||
}
|
||||
|
||||
SECURITY_ATTRIBUTES childProcessSecurity = {
|
||||
|
@ -51,7 +54,7 @@ mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* user
|
|||
SIZE_T stackSize = 0; // uses process default
|
||||
DWORD flags = 0;
|
||||
DWORD threadId = 0;
|
||||
thread->handle = CreateThread(&childProcessSecurity, stackSize, mp_thread_bootstrap, thread, flags, &threadId);
|
||||
thread->handle = CreateThread(&childProcessSecurity, stackSize, oc_thread_bootstrap, thread, flags, &threadId);
|
||||
if (thread->handle == NULL) {
|
||||
free(thread);
|
||||
return(NULL);
|
||||
|
@ -59,9 +62,9 @@ mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* user
|
|||
|
||||
thread->threadId = threadId;
|
||||
|
||||
if (thread->name[0]) {
|
||||
wchar_t widename[MP_THREAD_NAME_MAX_SIZE];
|
||||
size_t length = mbstowcs(widename, thread->name, MP_THREAD_NAME_MAX_SIZE - 1);
|
||||
if (thread->name.len) {
|
||||
wchar_t widename[OC_THREAD_NAME_MAX_SIZE];
|
||||
size_t length = mbstowcs(widename, thread->nameBuffer, OC_THREAD_NAME_MAX_SIZE - 1);
|
||||
widename[length] = '\0';
|
||||
|
||||
SetThreadDescription(thread->handle, widename);
|
||||
|
@ -70,33 +73,33 @@ mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* user
|
|||
return(thread);
|
||||
}
|
||||
|
||||
mp_thread* mp_thread_create(mp_thread_start_function start, void* userPointer)
|
||||
oc_thread* oc_thread_create(oc_thread_start_function start, void* userPointer)
|
||||
{
|
||||
return(mp_thread_create_with_name(start, userPointer, NULL));
|
||||
return(oc_thread_create_with_name(start, userPointer, (oc_str8){0}));
|
||||
}
|
||||
|
||||
const char* mp_thread_get_name(mp_thread* thread)
|
||||
oc_str8 oc_thread_get_name(oc_thread* thread)
|
||||
{
|
||||
return(thread->name);
|
||||
}
|
||||
|
||||
u64 mp_thread_unique_id(mp_thread* thread)
|
||||
u64 oc_thread_unique_id(oc_thread* thread)
|
||||
{
|
||||
return(thread->threadId);
|
||||
}
|
||||
|
||||
u64 mp_thread_self_id()
|
||||
u64 oc_thread_self_id()
|
||||
{
|
||||
return(GetCurrentThreadId());
|
||||
}
|
||||
|
||||
int mp_thread_signal(mp_thread* thread, int sig)
|
||||
int oc_thread_signal(oc_thread* thread, int sig)
|
||||
{
|
||||
BOOL success = TerminateThread(thread->handle, (DWORD)sig);
|
||||
return(success ? 0 : -1);
|
||||
}
|
||||
|
||||
int mp_thread_join(mp_thread* thread, i64* exitCode)
|
||||
int oc_thread_join(oc_thread* thread, i64* exitCode)
|
||||
{
|
||||
DWORD result = WaitForSingleObject(thread->handle, INFINITE);
|
||||
if (result == WAIT_FAILED) {
|
||||
|
@ -116,7 +119,7 @@ int mp_thread_join(mp_thread* thread, i64* exitCode)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int mp_thread_detach(mp_thread* thread)
|
||||
int oc_thread_detach(oc_thread* thread)
|
||||
{
|
||||
if (CloseHandle(thread->handle))
|
||||
{
|
||||
|
@ -127,86 +130,86 @@ int mp_thread_detach(mp_thread* thread)
|
|||
}
|
||||
|
||||
|
||||
struct mp_mutex
|
||||
struct oc_mutex
|
||||
{
|
||||
u64 owningThreadId;
|
||||
SRWLOCK lock;
|
||||
};
|
||||
|
||||
mp_mutex* mp_mutex_create()
|
||||
oc_mutex* oc_mutex_create()
|
||||
{
|
||||
mp_mutex* mutex = (mp_mutex*)malloc(sizeof(mp_mutex));
|
||||
oc_mutex* mutex = (oc_mutex*)malloc(sizeof(oc_mutex));
|
||||
mutex->owningThreadId = 0;
|
||||
InitializeSRWLock(&mutex->lock);
|
||||
return mutex;
|
||||
}
|
||||
|
||||
int mp_mutex_destroy(mp_mutex* mutex)
|
||||
int oc_mutex_destroy(oc_mutex* mutex)
|
||||
{
|
||||
DEBUG_ASSERT(mutex->owningThreadId == 0);
|
||||
OC_DEBUG_ASSERT(mutex->owningThreadId == 0);
|
||||
free(mutex);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int mp_mutex_lock(mp_mutex* mutex)
|
||||
int oc_mutex_lock(oc_mutex* mutex)
|
||||
{
|
||||
DEBUG_ASSERT(mutex->owningThreadId == 0);
|
||||
OC_DEBUG_ASSERT(mutex->owningThreadId == 0);
|
||||
AcquireSRWLockExclusive(&mutex->lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int mp_mutex_unlock(mp_mutex* mutex)
|
||||
int oc_mutex_unlock(oc_mutex* mutex)
|
||||
{
|
||||
DEBUG_ASSERT(mp_thread_self_id() == mutex->owningThreadId);
|
||||
OC_DEBUG_ASSERT(oc_thread_self_id() == mutex->owningThreadId);
|
||||
ReleaseSRWLockExclusive(&mutex->lock);
|
||||
mutex->owningThreadId = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
// mp_ticket_spin_mutex has a mirrored implementation in posix_thread.c
|
||||
// oc_ticket has a mirrored implementation in posix_thread.c
|
||||
|
||||
void mp_ticket_spin_mutex_init(mp_ticket_spin_mutex* mutex)
|
||||
void oc_ticket_init(oc_ticket* mutex)
|
||||
{
|
||||
mutex->nextTicket = 0;
|
||||
mutex->serving = 0;
|
||||
}
|
||||
|
||||
void mp_ticket_spin_mutex_lock(mp_ticket_spin_mutex* mutex)
|
||||
void oc_ticket_lock(oc_ticket* mutex)
|
||||
{
|
||||
u64 ticket = atomic_fetch_add(&mutex->nextTicket, 1ULL);
|
||||
while(ticket != mutex->serving); //spin
|
||||
}
|
||||
|
||||
void mp_ticket_spin_mutex_unlock(mp_ticket_spin_mutex* mutex)
|
||||
void oc_ticket_unlock(oc_ticket* mutex)
|
||||
{
|
||||
atomic_fetch_add(&mutex->serving, 1ULL);
|
||||
}
|
||||
|
||||
|
||||
struct mp_condition
|
||||
struct oc_condition
|
||||
{
|
||||
CONDITION_VARIABLE cond;
|
||||
};
|
||||
|
||||
mp_condition* mp_condition_create()
|
||||
oc_condition* oc_condition_create()
|
||||
{
|
||||
mp_condition* cond = (mp_condition*)malloc(sizeof(mp_condition));
|
||||
oc_condition* cond = (oc_condition*)malloc(sizeof(oc_condition));
|
||||
InitializeConditionVariable(&cond->cond);
|
||||
return cond;
|
||||
}
|
||||
|
||||
int mp_condition_destroy(mp_condition* cond)
|
||||
int oc_condition_destroy(oc_condition* cond)
|
||||
{
|
||||
free(cond);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int mp_condition_wait(mp_condition* cond, mp_mutex* mutex)
|
||||
int oc_condition_wait(oc_condition* cond, oc_mutex* mutex)
|
||||
{
|
||||
return mp_condition_timedwait(cond, mutex, INFINITY);
|
||||
return oc_condition_timedwait(cond, mutex, INFINITY);
|
||||
}
|
||||
|
||||
int mp_condition_timedwait(mp_condition* cond, mp_mutex* mutex, f64 seconds)
|
||||
int oc_condition_timedwait(oc_condition* cond, oc_mutex* mutex, f64 seconds)
|
||||
{
|
||||
const f32 ms = (seconds == INFINITY) ? INFINITE : seconds * 1000;
|
||||
if (!SleepConditionVariableSRW(&cond->cond, &mutex->lock, ms, 0))
|
||||
|
@ -216,13 +219,13 @@ int mp_condition_timedwait(mp_condition* cond, mp_mutex* mutex, f64 seconds)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int mp_condition_signal(mp_condition* cond)
|
||||
int oc_condition_signal(oc_condition* cond)
|
||||
{
|
||||
WakeConditionVariable(&cond->cond);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int mp_condition_broadcast(mp_condition* cond)
|
||||
int oc_condition_broadcast(oc_condition* cond)
|
||||
{
|
||||
WakeAllConditionVariable(&cond->cond);
|
||||
return(0);
|
||||
|
|
468
src/runtime.c
468
src/runtime.c
|
@ -9,7 +9,7 @@
|
|||
#include<errno.h>
|
||||
#include<math.h>
|
||||
|
||||
#define MG_INCLUDE_GL_API
|
||||
#define OC_INCLUDE_GL_API
|
||||
#include"orca.h"
|
||||
#include"graphics/graphics_common.h"
|
||||
|
||||
|
@ -17,57 +17,57 @@
|
|||
#include"runtime_memory.c"
|
||||
#include"runtime_io.c"
|
||||
|
||||
mg_font orca_font_create(const char* resourcePath)
|
||||
oc_font orca_font_create(const char* resourcePath)
|
||||
{
|
||||
//NOTE(martin): create default font
|
||||
str8 fontPath = path_executable_relative(mem_scratch(), STR8(resourcePath));
|
||||
oc_str8 fontPath = oc_path_executable_relative(oc_scratch(), OC_STR8(resourcePath));
|
||||
|
||||
FILE* fontFile = fopen(fontPath.ptr, "r");
|
||||
if(!fontFile)
|
||||
{
|
||||
log_error("Could not load font file '%s': %s\n", fontPath.ptr, strerror(errno));
|
||||
return(mg_font_nil());
|
||||
oc_log_error("Could not load font file '%s': %s\n", fontPath.ptr, strerror(errno));
|
||||
return(oc_font_nil());
|
||||
}
|
||||
unsigned char* fontData = 0;
|
||||
char* fontData = 0;
|
||||
fseek(fontFile, 0, SEEK_END);
|
||||
u32 fontDataSize = ftell(fontFile);
|
||||
rewind(fontFile);
|
||||
fontData = (unsigned char*)malloc(fontDataSize);
|
||||
fontData = malloc(fontDataSize);
|
||||
fread(fontData, 1, fontDataSize, fontFile);
|
||||
fclose(fontFile);
|
||||
|
||||
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
|
||||
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||
UNICODE_RANGE_LATIN_EXTENDED_A,
|
||||
UNICODE_RANGE_LATIN_EXTENDED_B,
|
||||
UNICODE_RANGE_SPECIALS};
|
||||
oc_unicode_range ranges[5] = {OC_UNICODE_BASIC_LATIN,
|
||||
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||
OC_UNICODE_LATIN_EXTENDED_A,
|
||||
OC_UNICODE_LATIN_EXTENDED_B,
|
||||
OC_UNICODE_SPECIALS};
|
||||
|
||||
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
|
||||
oc_font font = oc_font_create_from_memory(oc_str8_from_buffer(fontDataSize, fontData), 5, ranges);
|
||||
|
||||
free(fontData);
|
||||
|
||||
return(font);
|
||||
}
|
||||
|
||||
mg_font mg_font_create_default()
|
||||
oc_font oc_font_create_default()
|
||||
{
|
||||
return(orca_font_create("../resources/OpenSansLatinSubset.ttf"));
|
||||
}
|
||||
|
||||
|
||||
orca_app __orcaApp = {0};
|
||||
oc_runtime __orcaApp = {0};
|
||||
|
||||
orca_app* orca_app_get()
|
||||
oc_runtime* oc_runtime_get()
|
||||
{
|
||||
return(&__orcaApp);
|
||||
}
|
||||
|
||||
orca_runtime* orca_runtime_get()
|
||||
oc_runtime_env* oc_runtime_env_get()
|
||||
{
|
||||
return(&__orcaApp.runtime);
|
||||
}
|
||||
|
||||
void orca_log(log_level level,
|
||||
void oc_runtime_log(oc_log_level level,
|
||||
int fileLen,
|
||||
char* file,
|
||||
int functionLen,
|
||||
|
@ -76,16 +76,16 @@ void orca_log(log_level level,
|
|||
int msgLen,
|
||||
char* msg)
|
||||
{
|
||||
orca_debug_overlay* debug = &__orcaApp.debugOverlay;
|
||||
oc_debug_overlay* debug = &__orcaApp.debugOverlay;
|
||||
|
||||
//NOTE: recycle first entry if we exceeded the max entry count
|
||||
debug->entryCount++;
|
||||
if(debug->entryCount > debug->maxEntries)
|
||||
{
|
||||
log_entry* e = list_pop_entry(&debug->logEntries, log_entry, listElt);
|
||||
log_entry* e = oc_list_pop_entry(&debug->logEntries, log_entry, listElt);
|
||||
if(e)
|
||||
{
|
||||
list_push(&debug->logFreeList, &e->listElt);
|
||||
oc_list_push(&debug->logFreeList, &e->listElt);
|
||||
debug->entryCount--;
|
||||
}
|
||||
}
|
||||
|
@ -95,11 +95,11 @@ void orca_log(log_level level,
|
|||
//NOTE: allocate a new entry
|
||||
//TODO: should probably use a buddy allocator over the arena or something
|
||||
log_entry* entry = 0;
|
||||
for_list(&debug->logFreeList, elt, log_entry, listElt)
|
||||
oc_list_for(&debug->logFreeList, elt, log_entry, listElt)
|
||||
{
|
||||
if(elt->cap >= cap)
|
||||
{
|
||||
list_remove(&debug->logFreeList, &elt->listElt);
|
||||
oc_list_remove(&debug->logFreeList, &elt->listElt);
|
||||
entry = elt;
|
||||
break;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ void orca_log(log_level level,
|
|||
|
||||
if(!entry)
|
||||
{
|
||||
char* mem = mem_arena_alloc(&debug->logArena, cap);
|
||||
char* mem = oc_arena_push(&debug->logArena, cap);
|
||||
entry = (log_entry*)mem;
|
||||
entry->cap = cap;
|
||||
}
|
||||
|
@ -134,80 +134,80 @@ void orca_log(log_level level,
|
|||
entry->recordIndex = debug->logEntryTotalCount;
|
||||
debug->logEntryTotalCount++;
|
||||
|
||||
list_push_back(&debug->logEntries, &entry->listElt);
|
||||
oc_list_push_back(&debug->logEntries, &entry->listElt);
|
||||
|
||||
log_push(level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
"%.*s\n",
|
||||
msgLen,
|
||||
msg);
|
||||
oc_log_ext(level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
"%.*s\n",
|
||||
msgLen,
|
||||
msg);
|
||||
}
|
||||
|
||||
typedef struct orca_surface_create_data
|
||||
{
|
||||
mp_window window;
|
||||
mg_surface_api api;
|
||||
mg_surface surface;
|
||||
oc_window window;
|
||||
oc_surface_api api;
|
||||
oc_surface surface;
|
||||
|
||||
} orca_surface_create_data;
|
||||
|
||||
i32 orca_surface_callback(void* user)
|
||||
{
|
||||
orca_surface_create_data* data = (orca_surface_create_data*)user;
|
||||
data->surface = mg_surface_create_for_window(data->window, data->api);
|
||||
data->surface = oc_surface_create_for_window(data->window, data->api);
|
||||
|
||||
//NOTE: this will be called on main thread, so we need to deselect the surface here,
|
||||
// and reselect it on the orca thread
|
||||
mg_surface_deselect();
|
||||
oc_surface_deselect();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
mg_surface orca_surface_canvas(void)
|
||||
oc_surface orca_surface_canvas(void)
|
||||
{
|
||||
orca_surface_create_data data = {
|
||||
.surface = mg_surface_nil(),
|
||||
.surface = oc_surface_nil(),
|
||||
.window = __orcaApp.window,
|
||||
.api = MG_CANVAS
|
||||
.api = OC_CANVAS
|
||||
};
|
||||
|
||||
mp_dispatch_on_main_thread_sync(__orcaApp.window, orca_surface_callback, (void*)&data);
|
||||
mg_surface_prepare(data.surface);
|
||||
oc_dispatch_on_main_thread_sync(__orcaApp.window, orca_surface_callback, (void*)&data);
|
||||
oc_surface_select(data.surface);
|
||||
return(data.surface);
|
||||
}
|
||||
|
||||
mg_surface orca_surface_gles(void)
|
||||
oc_surface orca_surface_gles(void)
|
||||
{
|
||||
orca_surface_create_data data = {
|
||||
.surface = mg_surface_nil(),
|
||||
.surface = oc_surface_nil(),
|
||||
.window = __orcaApp.window,
|
||||
.api = MG_GLES
|
||||
.api = OC_GLES
|
||||
};
|
||||
|
||||
mp_dispatch_on_main_thread_sync(__orcaApp.window, orca_surface_callback, (void*)&data);
|
||||
mg_surface_prepare(data.surface);
|
||||
oc_dispatch_on_main_thread_sync(__orcaApp.window, orca_surface_callback, (void*)&data);
|
||||
oc_surface_select(data.surface);
|
||||
return(data.surface);
|
||||
}
|
||||
|
||||
void orca_surface_render_commands(mg_surface surface,
|
||||
mg_color clearColor,
|
||||
void orca_surface_render_commands(oc_surface surface,
|
||||
oc_color clearColor,
|
||||
u32 primitiveCount,
|
||||
mg_primitive* primitives,
|
||||
oc_primitive* primitives,
|
||||
u32 eltCount,
|
||||
mg_path_elt* elements)
|
||||
oc_path_elt* elements)
|
||||
{
|
||||
orca_app* app = &__orcaApp;
|
||||
oc_runtime* app = &__orcaApp;
|
||||
|
||||
char* memBase = app->runtime.wasmMemory.ptr;
|
||||
u32 memSize = app->runtime.wasmMemory.committed;
|
||||
if( ((char*)primitives > memBase)
|
||||
&&((char*)primitives + primitiveCount*sizeof(mg_primitive) - memBase <= memSize)
|
||||
&&((char*)primitives + primitiveCount*sizeof(oc_primitive) - memBase <= memSize)
|
||||
&&((char*)elements > memBase)
|
||||
&&((char*)elements + eltCount*sizeof(mg_path_elt) - memBase <= memSize))
|
||||
&&((char*)elements + eltCount*sizeof(oc_path_elt) - memBase <= memSize))
|
||||
{
|
||||
mg_surface_render_commands(surface,
|
||||
oc_surface_render_commands(surface,
|
||||
clearColor,
|
||||
primitiveCount,
|
||||
primitives,
|
||||
|
@ -216,10 +216,10 @@ void orca_surface_render_commands(mg_surface surface,
|
|||
}
|
||||
}
|
||||
|
||||
void debug_overlay_toggle(orca_debug_overlay* overlay)
|
||||
void debug_overlay_toggle(oc_debug_overlay* overlay)
|
||||
{
|
||||
overlay->show = !overlay->show;
|
||||
mg_surface_set_hidden(overlay->surface, !overlay->show);
|
||||
oc_surface_set_hidden(overlay->surface, !overlay->show);
|
||||
|
||||
if(overlay->show)
|
||||
{
|
||||
|
@ -228,57 +228,57 @@ void debug_overlay_toggle(orca_debug_overlay* overlay)
|
|||
}
|
||||
|
||||
|
||||
void log_entry_ui(orca_debug_overlay* overlay, log_entry* entry)
|
||||
void log_entry_ui(oc_debug_overlay* overlay, log_entry* entry)
|
||||
{
|
||||
static const char* levelNames[] = {"Error: ", "Warning: ", "Info: "};
|
||||
static const mg_color levelColors[] = {{0.8, 0, 0, 1},
|
||||
static const oc_color levelColors[] = {{0.8, 0, 0, 1},
|
||||
{1, 0.5, 0, 1},
|
||||
{0, 0.8, 0, 1}};
|
||||
|
||||
static const mg_color bgColors[3][2] = {//errors
|
||||
static const oc_color bgColors[3][2] = {//errors
|
||||
{{0.6, 0, 0, 0.5}, {0.8, 0, 0, 0.5}},
|
||||
//warning
|
||||
{{0.4, 0.4, 0.4, 0.5}, {0.5, 0.5, 0.5, 0.5}},
|
||||
//info
|
||||
{{0.4, 0.4, 0.4, 0.5}, {0.5, 0.5, 0.5, 0.5}}};
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_CHILDREN},
|
||||
.layout.axis = UI_AXIS_Y,
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_CHILDREN},
|
||||
.layout.axis = OC_UI_AXIS_Y,
|
||||
.layout.margin.x = 10,
|
||||
.layout.margin.y = 5,
|
||||
.bgColor = bgColors[entry->level][entry->recordIndex & 1]},
|
||||
UI_STYLE_SIZE
|
||||
|UI_STYLE_LAYOUT_AXIS
|
||||
|UI_STYLE_LAYOUT_MARGINS
|
||||
|UI_STYLE_BG_COLOR);
|
||||
OC_UI_STYLE_SIZE
|
||||
|OC_UI_STYLE_LAYOUT_AXIS
|
||||
|OC_UI_STYLE_LAYOUT_MARGINS
|
||||
|OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
str8 key = str8_pushf(mem_scratch(), "%ull", entry->recordIndex);
|
||||
oc_str8 key = oc_str8_pushf(oc_scratch(), "%ull", entry->recordIndex);
|
||||
|
||||
ui_container_str8(key, UI_FLAG_DRAW_BACKGROUND)
|
||||
oc_ui_container_str8(key, OC_UI_FLAG_DRAW_BACKGROUND)
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_CHILDREN},
|
||||
.layout.axis = UI_AXIS_X},
|
||||
UI_STYLE_SIZE
|
||||
|UI_STYLE_LAYOUT_AXIS);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_CHILDREN},
|
||||
.layout.axis = OC_UI_AXIS_X},
|
||||
OC_UI_STYLE_SIZE
|
||||
|OC_UI_STYLE_LAYOUT_AXIS);
|
||||
|
||||
ui_container("header", 0)
|
||||
oc_ui_container("header", 0)
|
||||
{
|
||||
ui_style_next(&(ui_style){.color = levelColors[entry->level],
|
||||
oc_ui_style_next(&(oc_ui_style){.color = levelColors[entry->level],
|
||||
.font = overlay->fontBold},
|
||||
UI_STYLE_COLOR
|
||||
|UI_STYLE_FONT);
|
||||
ui_label(levelNames[entry->level]);
|
||||
OC_UI_STYLE_COLOR
|
||||
|OC_UI_STYLE_FONT);
|
||||
oc_ui_label(levelNames[entry->level]);
|
||||
|
||||
str8 loc = str8_pushf(mem_scratch(),
|
||||
oc_str8 loc = oc_str8_pushf(oc_scratch(),
|
||||
"%.*s() in %.*s:%i:",
|
||||
str8_ip(entry->file),
|
||||
str8_ip(entry->function),
|
||||
oc_str8_ip(entry->file),
|
||||
oc_str8_ip(entry->function),
|
||||
entry->line);
|
||||
ui_label_str8(loc);
|
||||
oc_ui_label_str8(loc);
|
||||
}
|
||||
ui_label_str8(entry->msg);
|
||||
oc_ui_label_str8(entry->msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,13 +304,13 @@ char m3_type_to_tag(M3ValueType type)
|
|||
}
|
||||
}
|
||||
|
||||
void orca_runtime_init(orca_runtime* runtime)
|
||||
void oc_runtime_env_init(oc_runtime_env* runtime)
|
||||
{
|
||||
memset(runtime, 0, sizeof(orca_runtime));
|
||||
mem_base_allocator* allocator = mem_base_allocator_default();
|
||||
memset(runtime, 0, sizeof(oc_runtime_env));
|
||||
oc_base_allocator* allocator = oc_base_allocator_default();
|
||||
runtime->wasmMemory.committed = 0;
|
||||
runtime->wasmMemory.reserved = 4ULL<<30;
|
||||
runtime->wasmMemory.ptr = mem_base_reserve(allocator, runtime->wasmMemory.reserved);
|
||||
runtime->wasmMemory.ptr = oc_base_reserve(allocator, runtime->wasmMemory.reserved);
|
||||
}
|
||||
|
||||
#include"wasmbind/core_api_bind_gen.c"
|
||||
|
@ -327,11 +327,11 @@ void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const
|
|||
m3_GetErrorInfo(runtime, &errInfo);
|
||||
if(errInfo.message && res == errInfo.result)
|
||||
{
|
||||
orca_abort(file, function, line, "%s: %s (%s)", msg, res, errInfo.message);
|
||||
oc_abort_ext(file, function, line, "%s: %s (%s)", msg, res, errInfo.message);
|
||||
}
|
||||
else
|
||||
{
|
||||
orca_abort(file, function, line, "%s: %s", msg, res);
|
||||
oc_abort_ext(file, function, line, "%s: %s", msg, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,18 +339,18 @@ void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const
|
|||
|
||||
i32 orca_runloop(void* user)
|
||||
{
|
||||
orca_app* app = &__orcaApp;
|
||||
oc_runtime* app = &__orcaApp;
|
||||
|
||||
orca_runtime_init(&app->runtime);
|
||||
oc_runtime_env_init(&app->runtime);
|
||||
|
||||
//NOTE: loads wasm module
|
||||
const char* bundleNameCString = "module";
|
||||
str8 modulePath = path_executable_relative(mem_scratch(), STR8("../app/wasm/module.wasm"));
|
||||
oc_str8 modulePath = oc_path_executable_relative(oc_scratch(), OC_STR8("../app/wasm/module.wasm"));
|
||||
|
||||
FILE* file = fopen(modulePath.ptr, "rb");
|
||||
if(!file)
|
||||
{
|
||||
ORCA_ABORT("The application couldn't load: web assembly module not found");
|
||||
OC_ABORT("The application couldn't load: web assembly module not found");
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
|
@ -358,7 +358,7 @@ i32 orca_runloop(void* user)
|
|||
rewind(file);
|
||||
|
||||
app->runtime.wasmBytecode.len = wasmSize;
|
||||
app->runtime.wasmBytecode.ptr = malloc_array(char, wasmSize);
|
||||
app->runtime.wasmBytecode.ptr = oc_malloc_array(char, wasmSize);
|
||||
fread(app->runtime.wasmBytecode.ptr, 1, app->runtime.wasmBytecode.len, file);
|
||||
fclose(file);
|
||||
|
||||
|
@ -382,7 +382,7 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
m3_SetModuleName(app->runtime.m3Module, bundleNameCString);
|
||||
|
||||
mem_arena_clear(mem_scratch());
|
||||
oc_arena_clear(oc_scratch());
|
||||
|
||||
//NOTE: bind orca APIs
|
||||
{
|
||||
|
@ -396,7 +396,7 @@ i32 orca_runloop(void* user)
|
|||
|
||||
if(err)
|
||||
{
|
||||
ORCA_ABORT("The application couldn't link one or more functions to its web assembly module (see console log for more information)");
|
||||
OC_ABORT("The application couldn't link one or more functions to its web assembly module (see console log for more information)");
|
||||
}
|
||||
}
|
||||
//NOTE: compile
|
||||
|
@ -407,9 +407,9 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
|
||||
//NOTE: Find and type check event handlers.
|
||||
for(int i=0; i<G_EXPORT_COUNT; i++)
|
||||
for(int i=0; i<OC_EXPORT_COUNT; i++)
|
||||
{
|
||||
const g_export_desc* desc = &G_EXPORT_DESC[i];
|
||||
const oc_export_desc* desc = &OC_EXPORT_DESC[i];
|
||||
IM3Function handler = 0;
|
||||
m3_FindFunction(&handler, app->runtime.m3Runtime, desc->name.ptr);
|
||||
|
||||
|
@ -456,99 +456,99 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
else
|
||||
{
|
||||
log_error("type mismatch for event handler %.*s\n", (int)desc->name.len, desc->name.ptr);
|
||||
oc_log_error("type mismatch for event handler %.*s\n", (int)desc->name.len, desc->name.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: get location of the raw event slot
|
||||
IM3Global rawEventGlobal = m3_FindGlobal(app->runtime.m3Module, "_OrcaRawEvent");
|
||||
IM3Global rawEventGlobal = m3_FindGlobal(app->runtime.m3Module, "oc_rawEvent");
|
||||
app->runtime.rawEventOffset = (u32)rawEventGlobal->intValue;
|
||||
|
||||
//NOTE: preopen the app local root dir
|
||||
{
|
||||
str8 localRootPath = path_executable_relative(mem_scratch(), STR8("../app/data"));
|
||||
oc_str8 localRootPath = oc_path_executable_relative(oc_scratch(), OC_STR8("../app/data"));
|
||||
|
||||
io_req req = {.op = IO_OP_OPEN_AT,
|
||||
.open.rights = FILE_ACCESS_READ|FILE_ACCESS_WRITE,
|
||||
oc_io_req req = {.op = OC_IO_OPEN_AT,
|
||||
.open.rights = OC_FILE_ACCESS_READ|OC_FILE_ACCESS_WRITE,
|
||||
.size = localRootPath.len,
|
||||
.buffer = localRootPath.ptr};
|
||||
io_cmp cmp = io_wait_single_req_with_table(&req, &app->fileTable);
|
||||
oc_io_cmp cmp = oc_io_wait_single_req_with_table(&req, &app->fileTable);
|
||||
app->rootDir = cmp.handle;
|
||||
}
|
||||
|
||||
IM3Function* exports = app->runtime.exports;
|
||||
|
||||
//NOTE: call init handler
|
||||
if(exports[G_EXPORT_ON_INIT])
|
||||
if(exports[OC_EXPORT_ON_INIT])
|
||||
{
|
||||
M3Result res = m3_Call(exports[G_EXPORT_ON_INIT], 0, 0);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_ON_INIT], 0, 0);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
|
||||
if(exports[G_EXPORT_FRAME_RESIZE])
|
||||
if(exports[OC_EXPORT_FRAME_RESIZE])
|
||||
{
|
||||
mp_rect content = mp_window_get_content_rect(app->window);
|
||||
oc_rect content = oc_window_get_content_rect(app->window);
|
||||
u32 width = (u32)content.w;
|
||||
u32 height = (u32)content.h;
|
||||
const void* args[2] = {&width, &height};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_FRAME_RESIZE], 2, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
|
||||
ui_set_context(&app->debugOverlay.ui);
|
||||
oc_ui_set_context(&app->debugOverlay.ui);
|
||||
|
||||
while(!mp_should_quit())
|
||||
while(!oc_should_quit())
|
||||
{
|
||||
mp_event* event = 0;
|
||||
while((event = mp_next_event(mem_scratch())) != 0)
|
||||
oc_event* event = 0;
|
||||
while((event = oc_next_event(oc_scratch())) != 0)
|
||||
{
|
||||
|
||||
if(app->debugOverlay.show)
|
||||
{
|
||||
ui_process_event(event);
|
||||
oc_ui_process_event(event);
|
||||
}
|
||||
|
||||
if(exports[G_EXPORT_RAW_EVENT])
|
||||
if(exports[OC_EXPORT_RAW_EVENT])
|
||||
{
|
||||
#ifndef M3_BIG_ENDIAN
|
||||
mp_event* eventPtr = (mp_event*)wasm_memory_offset_to_ptr(&app->runtime.wasmMemory, app->runtime.rawEventOffset);
|
||||
oc_event* eventPtr = (oc_event*)wasm_memory_offset_to_ptr(&app->runtime.wasmMemory, app->runtime.rawEventOffset);
|
||||
memcpy(eventPtr, event, sizeof(*event));
|
||||
|
||||
const void* args[1] = {&app->runtime.rawEventOffset};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_RAW_EVENT], 1, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_RAW_EVENT], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
#else
|
||||
log_error("OnRawEvent() is not supported on big endian platforms");
|
||||
oc_log_error("oc_on_raw_event() is not supported on big endian platforms");
|
||||
#endif
|
||||
}
|
||||
|
||||
switch(event->type)
|
||||
{
|
||||
case MP_EVENT_WINDOW_CLOSE:
|
||||
case OC_EVENT_WINDOW_CLOSE:
|
||||
{
|
||||
mp_request_quit();
|
||||
oc_request_quit();
|
||||
} break;
|
||||
|
||||
case MP_EVENT_WINDOW_RESIZE:
|
||||
case OC_EVENT_WINDOW_RESIZE:
|
||||
{
|
||||
mp_rect frame = {0, 0, event->move.frame.w, event->move.frame.h};
|
||||
oc_rect frame = {0, 0, event->move.frame.w, event->move.frame.h};
|
||||
|
||||
if(exports[G_EXPORT_FRAME_RESIZE])
|
||||
if(exports[OC_EXPORT_FRAME_RESIZE])
|
||||
{
|
||||
u32 width = (u32)event->move.content.w;
|
||||
u32 height = (u32)event->move.content.h;
|
||||
const void* args[2] = {&width, &height};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_FRAME_RESIZE], 2, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
|
@ -556,15 +556,15 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
} break;
|
||||
|
||||
case MP_EVENT_MOUSE_BUTTON:
|
||||
case OC_EVENT_MOUSE_BUTTON:
|
||||
{
|
||||
if(event->key.action == MP_KEY_PRESS)
|
||||
if(event->key.action == OC_KEY_PRESS)
|
||||
{
|
||||
if(exports[G_EXPORT_MOUSE_DOWN])
|
||||
if(exports[OC_EXPORT_MOUSE_DOWN])
|
||||
{
|
||||
int key = event->key.code;
|
||||
const void* args[1] = {&key};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_MOUSE_DOWN], 1, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
|
@ -573,11 +573,11 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(exports[G_EXPORT_MOUSE_UP])
|
||||
if(exports[OC_EXPORT_MOUSE_UP])
|
||||
{
|
||||
int key = event->key.code;
|
||||
const void* args[1] = {&key};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_MOUSE_UP], 1, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
|
@ -586,12 +586,12 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
} break;
|
||||
|
||||
case MP_EVENT_MOUSE_MOVE:
|
||||
case OC_EVENT_MOUSE_MOVE:
|
||||
{
|
||||
if(exports[G_EXPORT_MOUSE_MOVE])
|
||||
if(exports[OC_EXPORT_MOUSE_MOVE])
|
||||
{
|
||||
const void* args[4] = {&event->mouse.x, &event->mouse.y, &event->mouse.deltaX, &event->mouse.deltaY};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_MOUSE_MOVE], 4, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_MOVE], 4, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
|
@ -599,33 +599,33 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
} break;
|
||||
|
||||
case MP_EVENT_KEYBOARD_KEY:
|
||||
case OC_EVENT_KEYBOARD_KEY:
|
||||
{
|
||||
if(event->key.action == MP_KEY_PRESS)
|
||||
if(event->key.action == OC_KEY_PRESS)
|
||||
{
|
||||
if(event->key.code == MP_KEY_D && (event->key.mods & (MP_KEYMOD_SHIFT | MP_KEYMOD_CMD)))
|
||||
if(event->key.code == OC_KEY_D && (event->key.mods & (OC_KEYMOD_SHIFT | OC_KEYMOD_CMD)))
|
||||
{
|
||||
#if 1 // EPILEPSY WARNING! on windows this has a bug which causes a pretty strong stroboscopic effect
|
||||
debug_overlay_toggle(&app->debugOverlay);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(exports[G_EXPORT_KEY_DOWN])
|
||||
if(exports[OC_EXPORT_KEY_DOWN])
|
||||
{
|
||||
const void* args[1] = {&event->key.code};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_KEY_DOWN], 1, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event->key.action == MP_KEY_RELEASE)
|
||||
else if(event->key.action == OC_KEY_RELEASE)
|
||||
{
|
||||
if(exports[G_EXPORT_KEY_UP])
|
||||
if(exports[OC_EXPORT_KEY_UP])
|
||||
{
|
||||
const void* args[1] = {&event->key.code};
|
||||
M3Result res = m3_Call(exports[G_EXPORT_KEY_UP], 1, args);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
|
@ -641,110 +641,110 @@ i32 orca_runloop(void* user)
|
|||
|
||||
if(app->debugOverlay.show)
|
||||
{
|
||||
ui_style debugUIDefaultStyle = {.bgColor = {0},
|
||||
oc_ui_style debugUIDefaultStyle = {.bgColor = {0},
|
||||
.color = {1, 1, 1, 1},
|
||||
.font = app->debugOverlay.fontReg,
|
||||
.fontSize = 16,
|
||||
.borderColor = {1, 0, 0, 1},
|
||||
.borderSize = 2};
|
||||
|
||||
ui_style_mask debugUIDefaultMask = UI_STYLE_BG_COLOR
|
||||
| UI_STYLE_COLOR
|
||||
| UI_STYLE_BORDER_COLOR
|
||||
| UI_STYLE_BORDER_SIZE
|
||||
| UI_STYLE_FONT
|
||||
| UI_STYLE_FONT_SIZE;
|
||||
oc_ui_style_mask debugUIDefaultMask = OC_UI_STYLE_BG_COLOR
|
||||
| OC_UI_STYLE_COLOR
|
||||
| OC_UI_STYLE_BORDER_COLOR
|
||||
| OC_UI_STYLE_BORDER_SIZE
|
||||
| OC_UI_STYLE_FONT
|
||||
| OC_UI_STYLE_FONT_SIZE;
|
||||
|
||||
vec2 frameSize = mg_surface_get_size(app->debugOverlay.surface);
|
||||
oc_vec2 frameSize = oc_surface_get_size(app->debugOverlay.surface);
|
||||
|
||||
ui_frame(frameSize, &debugUIDefaultStyle, debugUIDefaultMask)
|
||||
oc_ui_frame(frameSize, &debugUIDefaultStyle, debugUIDefaultMask)
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 1, 1}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1, 1}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
ui_container("overlay area", 0)
|
||||
oc_ui_container("overlay area", 0)
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 0.4},
|
||||
.layout.axis = UI_AXIS_Y,
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 0.4},
|
||||
.layout.axis = OC_UI_AXIS_Y,
|
||||
.bgColor = {0, 0, 0, 0.5}},
|
||||
UI_STYLE_SIZE
|
||||
|UI_STYLE_LAYOUT_AXIS
|
||||
|UI_STYLE_BG_COLOR);
|
||||
OC_UI_STYLE_SIZE
|
||||
|OC_UI_STYLE_LAYOUT_AXIS
|
||||
|OC_UI_STYLE_BG_COLOR);
|
||||
|
||||
ui_container("log console", UI_FLAG_DRAW_BACKGROUND)
|
||||
oc_ui_container("log console", OC_UI_FLAG_DRAW_BACKGROUND)
|
||||
{
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_CHILDREN},
|
||||
.layout.axis = UI_AXIS_X,
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_CHILDREN},
|
||||
.layout.axis = OC_UI_AXIS_X,
|
||||
.layout.spacing = 10,
|
||||
.layout.margin.x = 10,
|
||||
.layout.margin.y = 10},
|
||||
UI_STYLE_SIZE
|
||||
|UI_STYLE_LAYOUT);
|
||||
OC_UI_STYLE_SIZE
|
||||
|OC_UI_STYLE_LAYOUT);
|
||||
|
||||
ui_container("log toolbar", 0)
|
||||
oc_ui_container("log toolbar", 0)
|
||||
{
|
||||
ui_style buttonStyle = {.layout.margin.x = 4,
|
||||
oc_ui_style buttonStyle = {.layout.margin.x = 4,
|
||||
.layout.margin.y = 4,
|
||||
.roundness = 2,
|
||||
.bgColor = {0, 0, 0, 0.5},
|
||||
.color = {1, 1, 1, 1}};
|
||||
|
||||
ui_style_mask buttonStyleMask = UI_STYLE_LAYOUT_MARGINS
|
||||
| UI_STYLE_ROUNDNESS
|
||||
| UI_STYLE_BG_COLOR
|
||||
| UI_STYLE_COLOR;
|
||||
oc_ui_style_mask buttonStyleMask = OC_UI_STYLE_LAYOUT_MARGINS
|
||||
| OC_UI_STYLE_ROUNDNESS
|
||||
| OC_UI_STYLE_BG_COLOR
|
||||
| OC_UI_STYLE_COLOR;
|
||||
|
||||
ui_style_match_after(ui_pattern_all(), &buttonStyle, buttonStyleMask);
|
||||
if(ui_button("Clear").clicked)
|
||||
oc_ui_style_match_after(oc_ui_pattern_all(), &buttonStyle, buttonStyleMask);
|
||||
if(oc_ui_button("Clear").clicked)
|
||||
{
|
||||
for_list_safe(&app->debugOverlay.logEntries, entry, log_entry, listElt)
|
||||
oc_list_for_safe(&app->debugOverlay.logEntries, entry, log_entry, listElt)
|
||||
{
|
||||
list_remove(&app->debugOverlay.logEntries, &entry->listElt);
|
||||
list_push(&app->debugOverlay.logFreeList, &entry->listElt);
|
||||
oc_list_remove(&app->debugOverlay.logEntries, &entry->listElt);
|
||||
oc_list_push(&app->debugOverlay.logFreeList, &entry->listElt);
|
||||
app->debugOverlay.entryCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_PARENT, 1, 1}},
|
||||
UI_STYLE_SIZE);
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_PARENT, 1, 1}},
|
||||
OC_UI_STYLE_SIZE);
|
||||
|
||||
//TODO: this is annoying to have to do that. Basically there's another 'contents' box inside ui_panel,
|
||||
//TODO: this is annoying to have to do that. Basically there's another 'contents' box inside oc_ui_panel,
|
||||
// and we need to change that to size according to its parent (whereas the default is sizing according
|
||||
// to its children)
|
||||
ui_pattern pattern = {0};
|
||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_OWNER});
|
||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("contents")});
|
||||
ui_style_match_after(pattern, &(ui_style){.size.width = {UI_SIZE_PARENT, 1}}, UI_STYLE_SIZE_WIDTH);
|
||||
oc_ui_pattern pattern = {0};
|
||||
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_OWNER});
|
||||
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_TEXT, .text = OC_STR8("contents")});
|
||||
oc_ui_style_match_after(pattern, &(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}}, OC_UI_STYLE_SIZE_WIDTH);
|
||||
|
||||
ui_box* panel = ui_box_lookup("log view");
|
||||
oc_ui_box* panel = oc_ui_box_lookup("log view");
|
||||
f32 scrollY = 0;
|
||||
if(panel)
|
||||
{
|
||||
scrollY = panel->scroll.y;
|
||||
}
|
||||
|
||||
ui_panel("log view", UI_FLAG_SCROLL_WHEEL_Y)
|
||||
oc_ui_panel("log view", OC_UI_FLAG_SCROLL_WHEEL_Y)
|
||||
{
|
||||
panel = ui_box_top();
|
||||
panel = oc_ui_box_top();
|
||||
|
||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
||||
.size.height = {UI_SIZE_CHILDREN},
|
||||
.layout.axis = UI_AXIS_Y,
|
||||
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||
.size.height = {OC_UI_SIZE_CHILDREN},
|
||||
.layout.axis = OC_UI_AXIS_Y,
|
||||
.layout.margin.y = 5},
|
||||
UI_STYLE_SIZE
|
||||
|UI_STYLE_LAYOUT_AXIS);
|
||||
OC_UI_STYLE_SIZE
|
||||
|OC_UI_STYLE_LAYOUT_AXIS);
|
||||
|
||||
ui_container("contents", 0)
|
||||
oc_ui_container("contents", 0)
|
||||
{
|
||||
for_list(&app->debugOverlay.logEntries, entry, log_entry, listElt)
|
||||
oc_list_for(&app->debugOverlay.logEntries, entry, log_entry, listElt)
|
||||
{
|
||||
log_entry_ui(&app->debugOverlay, entry);
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ i32 orca_runloop(void* user)
|
|||
{
|
||||
if(panel->scroll.y >= scrollY)
|
||||
{
|
||||
panel->scroll.y = ClampLowBound(panel->childrenSum[1] - panel->rect.h, 0);
|
||||
panel->scroll.y = oc_clamp_low(panel->childrenSum[1] - panel->rect.h, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -768,16 +768,16 @@ i32 orca_runloop(void* user)
|
|||
}
|
||||
}
|
||||
|
||||
mg_surface_prepare(app->debugOverlay.surface);
|
||||
mg_canvas_set_current(app->debugOverlay.canvas);
|
||||
ui_draw();
|
||||
oc_surface_select(app->debugOverlay.surface);
|
||||
oc_canvas_set_current(app->debugOverlay.canvas);
|
||||
oc_ui_draw();
|
||||
|
||||
mg_render(app->debugOverlay.surface, app->debugOverlay.canvas);
|
||||
oc_render(app->debugOverlay.surface, app->debugOverlay.canvas);
|
||||
}
|
||||
|
||||
if(exports[G_EXPORT_FRAME_REFRESH])
|
||||
if(exports[OC_EXPORT_FRAME_REFRESH])
|
||||
{
|
||||
M3Result res = m3_Call(exports[G_EXPORT_FRAME_REFRESH], 0, 0);
|
||||
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_REFRESH], 0, 0);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
|
@ -786,11 +786,11 @@ i32 orca_runloop(void* user)
|
|||
|
||||
if(app->debugOverlay.show)
|
||||
{
|
||||
mg_surface_prepare(app->debugOverlay.surface);
|
||||
mg_surface_present(app->debugOverlay.surface);
|
||||
oc_surface_select(app->debugOverlay.surface);
|
||||
oc_surface_present(app->debugOverlay.surface);
|
||||
}
|
||||
|
||||
mem_arena_clear(mem_scratch());
|
||||
oc_arena_clear(oc_scratch());
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
@ -798,64 +798,64 @@ i32 orca_runloop(void* user)
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
log_set_level(LOG_LEVEL_INFO);
|
||||
oc_log_set_level(OC_LOG_LEVEL_INFO);
|
||||
|
||||
mp_init();
|
||||
mp_clock_init();
|
||||
oc_init();
|
||||
oc_clock_init();
|
||||
|
||||
orca_app* app = &__orcaApp;
|
||||
oc_runtime* app = &__orcaApp;
|
||||
|
||||
//NOTE: create window and surfaces
|
||||
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
|
||||
app->window = mp_window_create(windowRect, "orca", 0);
|
||||
oc_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
|
||||
app->window = oc_window_create(windowRect, OC_STR8("orca"), 0);
|
||||
|
||||
app->debugOverlay.show = false;
|
||||
app->debugOverlay.surface = mg_surface_create_for_window(app->window, MG_CANVAS);
|
||||
app->debugOverlay.canvas = mg_canvas_create();
|
||||
app->debugOverlay.surface = oc_surface_create_for_window(app->window, OC_CANVAS);
|
||||
app->debugOverlay.canvas = oc_canvas_create();
|
||||
app->debugOverlay.fontReg = orca_font_create("../resources/Menlo.ttf");
|
||||
app->debugOverlay.fontBold = orca_font_create("../resources/Menlo Bold.ttf");
|
||||
app->debugOverlay.maxEntries = 200;
|
||||
mem_arena_init(&app->debugOverlay.logArena);
|
||||
oc_arena_init(&app->debugOverlay.logArena);
|
||||
|
||||
mg_surface_swap_interval(app->debugOverlay.surface, 0);
|
||||
oc_surface_swap_interval(app->debugOverlay.surface, 0);
|
||||
|
||||
mg_surface_set_hidden(app->debugOverlay.surface, true);
|
||||
oc_surface_set_hidden(app->debugOverlay.surface, true);
|
||||
|
||||
mg_surface_deselect();
|
||||
oc_surface_deselect();
|
||||
|
||||
//WARN: this is a workaround to avoid stalling the first few times we acquire drawables from
|
||||
// the surfaces... This should probably be fixed in the implementation of mtl_surface!
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
mg_surface_prepare(app->debugOverlay.surface);
|
||||
mg_canvas_set_current(app->debugOverlay.canvas);
|
||||
mg_render(app->debugOverlay.surface, app->debugOverlay.canvas);
|
||||
mg_surface_present(app->debugOverlay.surface);
|
||||
oc_surface_select(app->debugOverlay.surface);
|
||||
oc_canvas_set_current(app->debugOverlay.canvas);
|
||||
oc_render(app->debugOverlay.surface, app->debugOverlay.canvas);
|
||||
oc_surface_present(app->debugOverlay.surface);
|
||||
}
|
||||
|
||||
ui_init(&app->debugOverlay.ui);
|
||||
oc_ui_init(&app->debugOverlay.ui);
|
||||
|
||||
//NOTE: show window and start runloop
|
||||
mp_window_bring_to_front(app->window);
|
||||
mp_window_focus(app->window);
|
||||
mp_window_center(app->window);
|
||||
oc_window_bring_to_front(app->window);
|
||||
oc_window_focus(app->window);
|
||||
oc_window_center(app->window);
|
||||
|
||||
mp_thread* runloopThread = mp_thread_create(orca_runloop, 0);
|
||||
oc_thread* runloopThread = oc_thread_create(orca_runloop, 0);
|
||||
|
||||
while(!mp_should_quit())
|
||||
while(!oc_should_quit())
|
||||
{
|
||||
mp_pump_events(-1);
|
||||
oc_pump_events(-1);
|
||||
//TODO: what to do with mem scratch here?
|
||||
}
|
||||
|
||||
mp_thread_join(runloopThread, NULL);
|
||||
oc_thread_join(runloopThread, NULL);
|
||||
|
||||
mg_canvas_destroy(app->debugOverlay.canvas);
|
||||
mg_surface_destroy(app->debugOverlay.surface);
|
||||
oc_canvas_destroy(app->debugOverlay.canvas);
|
||||
oc_surface_destroy(app->debugOverlay.surface);
|
||||
|
||||
mp_window_destroy(app->window);
|
||||
oc_window_destroy(app->window);
|
||||
|
||||
mp_terminate();
|
||||
oc_terminate();
|
||||
return(0);
|
||||
}
|
||||
|
|
109
src/runtime.h
109
src/runtime.h
|
@ -14,42 +14,41 @@
|
|||
#include"m3_env.h"
|
||||
#include"m3_compile.h"
|
||||
|
||||
#define G_EXPORTS(X) \
|
||||
X(G_EXPORT_ON_INIT, "OnInit", "", "") \
|
||||
X(G_EXPORT_MOUSE_DOWN, "OnMouseDown", "", "i") \
|
||||
X(G_EXPORT_MOUSE_UP, "OnMouseUp", "", "i") \
|
||||
X(G_EXPORT_MOUSE_ENTER, "OnMouseEnter", "", "") \
|
||||
X(G_EXPORT_MOUSE_LEAVE, "OnMouseLeave", "", "") \
|
||||
X(G_EXPORT_MOUSE_MOVE, "OnMouseMove", "", "ffff") \
|
||||
X(G_EXPORT_MOUSE_WHEEL, "OnMouseWheel", "", "ff") \
|
||||
X(G_EXPORT_KEY_DOWN, "OnKeyDown", "", "i") \
|
||||
X(G_EXPORT_KEY_UP, "OnKeyUp", "", "i") \
|
||||
X(G_EXPORT_FRAME_REFRESH, "OnFrameRefresh", "", "") \
|
||||
X(G_EXPORT_FRAME_RESIZE, "OnFrameResize", "", "ii") \
|
||||
X(G_EXPORT_RAW_EVENT, "OnRawEvent", "", "i") \
|
||||
#define OC_EXPORTS(X) \
|
||||
X(OC_EXPORT_ON_INIT, "oc_on_init", "", "") \
|
||||
X(OC_EXPORT_MOUSE_DOWN, "oc_on_mouse_down", "", "i") \
|
||||
X(OC_EXPORT_MOUSE_UP, "oc_on_mouse_up", "", "i") \
|
||||
X(OC_EXPORT_MOUSE_ENTER, "oc_on_mouse_enter", "", "") \
|
||||
X(OC_EXPORT_MOUSE_LEAVE, "oc_on_mouse_leave", "", "") \
|
||||
X(OC_EXPORT_MOUSE_MOVE, "oc_on_mouse_move", "", "ffff") \
|
||||
X(OC_EXPORT_MOUSE_WHEEL, "oc_on_mouse_wheel", "", "ff") \
|
||||
X(OC_EXPORT_KEY_DOWN, "oc_on_key_down", "", "i") \
|
||||
X(OC_EXPORT_KEY_UP, "oc_on_key_up", "", "i") \
|
||||
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") \
|
||||
|
||||
typedef enum {
|
||||
#define G_EXPORT_KIND(kind, ...) kind,
|
||||
G_EXPORTS(G_EXPORT_KIND)
|
||||
G_EXPORT_COUNT
|
||||
#define OC_EXPORT_KIND(kind, ...) kind,
|
||||
OC_EXPORTS(OC_EXPORT_KIND)
|
||||
OC_EXPORT_COUNT
|
||||
} guest_export_kind;
|
||||
|
||||
|
||||
typedef struct g_export_desc
|
||||
typedef struct oc_export_desc
|
||||
{
|
||||
str8 name;
|
||||
str8 retTags;
|
||||
str8 argTags;
|
||||
} g_export_desc;
|
||||
oc_str8 name;
|
||||
oc_str8 retTags;
|
||||
oc_str8 argTags;
|
||||
} oc_export_desc;
|
||||
|
||||
const g_export_desc G_EXPORT_DESC[] = {
|
||||
#define STR8LIT(s) {sizeof(s)-1, s} //NOTE: msvc doesn't accept STR8(s) as compile-time constant...
|
||||
#define G_EXPORT_DESC_ENTRY(kind, name, rets, args) {STR8LIT(name), STR8LIT(rets), STR8LIT(args)},
|
||||
const oc_export_desc OC_EXPORT_DESC[] = {
|
||||
#define OC_EXPORT_DESC_ENTRY(kind, name, rets, args) {OC_STR8_LIT(name), OC_STR8_LIT(rets), OC_STR8_LIT(args)},
|
||||
|
||||
G_EXPORTS(G_EXPORT_DESC_ENTRY)
|
||||
OC_EXPORTS(OC_EXPORT_DESC_ENTRY)
|
||||
|
||||
#undef G_EXPORT_DESC_ENTRY
|
||||
#undef STR8LIT
|
||||
#undef OC_EXPORT_DESC_ENTRY
|
||||
#undef OC_STR8_LIT
|
||||
};
|
||||
|
||||
typedef struct wasm_memory
|
||||
|
@ -60,69 +59,69 @@ typedef struct wasm_memory
|
|||
|
||||
} wasm_memory;
|
||||
|
||||
typedef struct orca_runtime
|
||||
typedef struct oc_runtime_env
|
||||
{
|
||||
str8 wasmBytecode;
|
||||
oc_str8 wasmBytecode;
|
||||
wasm_memory wasmMemory;
|
||||
|
||||
// wasm3 data
|
||||
IM3Environment m3Env;
|
||||
IM3Runtime m3Runtime;
|
||||
IM3Module m3Module;
|
||||
IM3Function exports[G_EXPORT_COUNT];
|
||||
IM3Function exports[OC_EXPORT_COUNT];
|
||||
u32 rawEventOffset;
|
||||
|
||||
} orca_runtime;
|
||||
} oc_runtime_env;
|
||||
|
||||
typedef struct log_entry
|
||||
{
|
||||
list_elt listElt;
|
||||
oc_list_elt listElt;
|
||||
u64 cap;
|
||||
|
||||
log_level level;
|
||||
str8 file;
|
||||
str8 function;
|
||||
oc_log_level level;
|
||||
oc_str8 file;
|
||||
oc_str8 function;
|
||||
int line;
|
||||
str8 msg;
|
||||
oc_str8 msg;
|
||||
|
||||
u64 recordIndex;
|
||||
|
||||
} log_entry;
|
||||
|
||||
typedef struct orca_debug_overlay
|
||||
typedef struct oc_debug_overlay
|
||||
{
|
||||
bool show;
|
||||
mg_surface surface;
|
||||
mg_canvas canvas;
|
||||
mg_font fontReg;
|
||||
mg_font fontBold;
|
||||
ui_context ui;
|
||||
oc_surface surface;
|
||||
oc_canvas canvas;
|
||||
oc_font fontReg;
|
||||
oc_font fontBold;
|
||||
oc_ui_context ui;
|
||||
|
||||
|
||||
mem_arena logArena;
|
||||
list_info logEntries;
|
||||
list_info logFreeList;
|
||||
oc_arena logArena;
|
||||
oc_list logEntries;
|
||||
oc_list logFreeList;
|
||||
u32 entryCount;
|
||||
u32 maxEntries;
|
||||
u64 logEntryTotalCount;
|
||||
bool logScrollToLast;
|
||||
|
||||
} orca_debug_overlay;
|
||||
} oc_debug_overlay;
|
||||
|
||||
typedef struct orca_app
|
||||
typedef struct oc_runtime
|
||||
{
|
||||
mp_window window;
|
||||
oc_window window;
|
||||
|
||||
file_table fileTable;
|
||||
file_handle rootDir;
|
||||
oc_file_table fileTable;
|
||||
oc_file rootDir;
|
||||
|
||||
orca_runtime runtime;
|
||||
oc_runtime_env runtime;
|
||||
|
||||
orca_debug_overlay debugOverlay;
|
||||
oc_debug_overlay debugOverlay;
|
||||
|
||||
} orca_app;
|
||||
} oc_runtime;
|
||||
|
||||
orca_app* orca_app_get();
|
||||
orca_runtime* orca_runtime_get();
|
||||
oc_runtime* oc_runtime_get();
|
||||
oc_runtime_env* oc_runtime_env_get();
|
||||
|
||||
#endif //__RUNTIME_H_
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
#include"platform/platform_io_internal.h"
|
||||
#include"runtime.h"
|
||||
|
||||
io_cmp orca_io_wait_single_req(io_req* wasmReq)
|
||||
oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq)
|
||||
{
|
||||
orca_app* orca = orca_app_get();
|
||||
mem_arena* scratch = mem_scratch();
|
||||
oc_runtime* orca = oc_runtime_get();
|
||||
oc_arena* scratch = oc_scratch();
|
||||
|
||||
io_cmp cmp = {0};
|
||||
io_req req = *wasmReq;
|
||||
oc_io_cmp cmp = {0};
|
||||
oc_io_req req = *wasmReq;
|
||||
//NOTE: convert the req->buffer wasm pointer to a native pointer
|
||||
// for some reason, wasm3 memory doesn't start at the beginning of the block we give it.
|
||||
u64 bufferIndex = (u64)req.buffer & 0xffffffff;
|
||||
|
@ -23,22 +23,22 @@ io_cmp orca_io_wait_single_req(io_req* wasmReq)
|
|||
|
||||
if(bufferIndex + req.size > memSize)
|
||||
{
|
||||
cmp.error = IO_ERR_ARG;
|
||||
cmp.error = OC_IO_ERR_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
req.buffer = memory + bufferIndex;
|
||||
|
||||
if(req.op == IO_OP_OPEN_AT)
|
||||
if(req.op == OC_IO_OPEN_AT)
|
||||
{
|
||||
if(req.handle.h == 0)
|
||||
{
|
||||
//NOTE: change root to app local folder
|
||||
req.handle = orca->rootDir;
|
||||
req.open.flags |= FILE_OPEN_RESTRICT;
|
||||
req.open.flags |= OC_FILE_OPEN_RESTRICT;
|
||||
}
|
||||
}
|
||||
cmp = io_wait_single_req_with_table(&req, &orca->fileTable);
|
||||
cmp = oc_io_wait_single_req_with_table(&req, &orca->fileTable);
|
||||
}
|
||||
return(cmp);
|
||||
}
|
||||
|
|
|
@ -20,14 +20,14 @@ void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
|
|||
{
|
||||
u32 commitSize = size - memory->committed;
|
||||
|
||||
mem_base_allocator* allocator = mem_base_allocator_default();
|
||||
mem_base_commit(allocator, memory->ptr + memory->committed, commitSize);
|
||||
oc_base_allocator* allocator = oc_base_allocator_default();
|
||||
oc_base_commit(allocator, memory->ptr + memory->committed, commitSize);
|
||||
memory->committed += commitSize;
|
||||
return(memory->ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_ASSERT(0, "Out of memory");
|
||||
OC_ABORT("Out of memory");
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
@ -36,17 +36,17 @@ void wasm_memory_free_callback(void* p, void* userData)
|
|||
{
|
||||
wasm_memory* memory = (wasm_memory*)userData;
|
||||
|
||||
mem_base_allocator* allocator = mem_base_allocator_default();
|
||||
mem_base_release(allocator, memory->ptr, memory->reserved);
|
||||
oc_base_allocator* allocator = oc_base_allocator_default();
|
||||
oc_base_release(allocator, memory->ptr, memory->reserved);
|
||||
memset(memory, 0, sizeof(wasm_memory));
|
||||
}
|
||||
|
||||
extern u32 orca_mem_grow(u64 size)
|
||||
extern u32 oc_mem_grow(u64 size)
|
||||
{
|
||||
orca_runtime* runtime = orca_runtime_get();
|
||||
oc_runtime_env* runtime = oc_runtime_env_get();
|
||||
wasm_memory* memory = &runtime->wasmMemory;
|
||||
|
||||
size = AlignUpOnPow2(size, d_m3MemPageSize);
|
||||
size = oc_align_up_pow2(size, d_m3MemPageSize);
|
||||
u64 totalSize = size + m3_GetMemorySize(runtime->m3Runtime);
|
||||
|
||||
u32 addr = memory->committed;
|
||||
|
@ -61,6 +61,6 @@ extern u32 orca_mem_grow(u64 size)
|
|||
void* wasm_memory_offset_to_ptr(wasm_memory* memory, u32 offset)
|
||||
{
|
||||
M3MemoryHeader* header = (M3MemoryHeader*)(memory->ptr);
|
||||
DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length")
|
||||
OC_DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length");
|
||||
return memory->ptr + sizeof(M3MemoryHeader) + offset;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// Input state updating
|
||||
//---------------------------------------------------------------
|
||||
|
||||
static void mp_update_key_state(mp_input_state* state, mp_key_state* key, mp_key_action action)
|
||||
static void oc_update_key_state(oc_input_state* state, oc_key_state* key, oc_key_action action)
|
||||
{
|
||||
u64 frameCounter = state->frameCounter;
|
||||
if(key->lastUpdate != frameCounter)
|
||||
|
@ -25,7 +25,7 @@ static void mp_update_key_state(mp_input_state* state, mp_key_state* key, mp_key
|
|||
|
||||
switch(action)
|
||||
{
|
||||
case MP_KEY_PRESS:
|
||||
case OC_KEY_PRESS:
|
||||
{
|
||||
if(!key->down)
|
||||
{
|
||||
|
@ -34,13 +34,13 @@ static void mp_update_key_state(mp_input_state* state, mp_key_state* key, mp_key
|
|||
key->down = true;
|
||||
} break;
|
||||
|
||||
case MP_KEY_REPEAT:
|
||||
case OC_KEY_REPEAT:
|
||||
{
|
||||
key->repeatCount++;
|
||||
key->down = true;
|
||||
} break;
|
||||
|
||||
case MP_KEY_RELEASE:
|
||||
case OC_KEY_RELEASE:
|
||||
{
|
||||
if(key->down)
|
||||
{
|
||||
|
@ -54,44 +54,44 @@ static void mp_update_key_state(mp_input_state* state, mp_key_state* key, mp_key
|
|||
}
|
||||
}
|
||||
|
||||
static void mp_update_key_mods(mp_input_state* state, mp_keymod_flags mods)
|
||||
static void oc_update_key_mods(oc_input_state* state, oc_keymod_flags mods)
|
||||
{
|
||||
state->keyboard.mods = mods;
|
||||
}
|
||||
|
||||
static void mp_update_mouse_move(mp_input_state* state, f32 x, f32 y, f32 deltaX, f32 deltaY)
|
||||
static void oc_update_mouse_move(oc_input_state* state, f32 x, f32 y, f32 deltaX, f32 deltaY)
|
||||
{
|
||||
u64 frameCounter = state->frameCounter;
|
||||
mp_mouse_state* mouse = &state->mouse;
|
||||
oc_mouse_state* mouse = &state->mouse;
|
||||
if(mouse->lastUpdate != frameCounter)
|
||||
{
|
||||
mouse->delta = (vec2){0, 0};
|
||||
mouse->wheel = (vec2){0, 0};
|
||||
mouse->delta = (oc_vec2){0, 0};
|
||||
mouse->wheel = (oc_vec2){0, 0};
|
||||
mouse->lastUpdate = frameCounter;
|
||||
}
|
||||
mouse->pos = (vec2){x, y};
|
||||
mouse->pos = (oc_vec2){x, y};
|
||||
mouse->delta.x += deltaX;
|
||||
mouse->delta.y += deltaY;
|
||||
}
|
||||
|
||||
static void mp_update_mouse_wheel(mp_input_state* state, f32 deltaX, f32 deltaY)
|
||||
static void oc_update_mouse_wheel(oc_input_state* state, f32 deltaX, f32 deltaY)
|
||||
{
|
||||
u64 frameCounter = state->frameCounter;
|
||||
mp_mouse_state* mouse = &state->mouse;
|
||||
oc_mouse_state* mouse = &state->mouse;
|
||||
if(mouse->lastUpdate != frameCounter)
|
||||
{
|
||||
mouse->delta = (vec2){0, 0};
|
||||
mouse->wheel = (vec2){0, 0};
|
||||
mouse->delta = (oc_vec2){0, 0};
|
||||
mouse->wheel = (oc_vec2){0, 0};
|
||||
mouse->lastUpdate = frameCounter;
|
||||
}
|
||||
mouse->wheel.x += deltaX;
|
||||
mouse->wheel.y += deltaY;
|
||||
}
|
||||
|
||||
static void mp_update_text(mp_input_state* state, utf32 codepoint)
|
||||
static void oc_update_text(oc_input_state* state, oc_utf32 codepoint)
|
||||
{
|
||||
u64 frameCounter = state->frameCounter;
|
||||
mp_text_state* text = &state->text;
|
||||
oc_text_state* text = &state->text;
|
||||
|
||||
if(text->lastUpdate != frameCounter)
|
||||
{
|
||||
|
@ -100,55 +100,55 @@ static void mp_update_text(mp_input_state* state, utf32 codepoint)
|
|||
}
|
||||
|
||||
text->codePoints.ptr = text->backing;
|
||||
if(text->codePoints.len < MP_INPUT_TEXT_BACKING_SIZE)
|
||||
if(text->codePoints.len < OC_INPUT_TEXT_BACKING_SIZE)
|
||||
{
|
||||
text->codePoints.ptr[text->codePoints.len] = codepoint;
|
||||
text->codePoints.len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_warning("too many input codepoints per frame, dropping input");
|
||||
oc_log_warning("too many input codepoints per frame, dropping input");
|
||||
}
|
||||
}
|
||||
|
||||
void mp_input_next_frame(mp_input_state* state)
|
||||
void oc_input_next_frame(oc_input_state* state)
|
||||
{
|
||||
state->frameCounter++;
|
||||
}
|
||||
|
||||
void mp_input_process_event(mp_input_state* state, mp_event* event)
|
||||
void oc_input_process_event(oc_input_state* state, oc_event* event)
|
||||
{
|
||||
switch(event->type)
|
||||
{
|
||||
case MP_EVENT_KEYBOARD_KEY:
|
||||
case OC_EVENT_KEYBOARD_KEY:
|
||||
{
|
||||
mp_key_state* key = &state->keyboard.keys[event->key.code];
|
||||
mp_update_key_state(state, key, event->key.action);
|
||||
mp_update_key_mods(state, event->key.mods);
|
||||
oc_key_state* key = &state->keyboard.keys[event->key.code];
|
||||
oc_update_key_state(state, key, event->key.action);
|
||||
oc_update_key_mods(state, event->key.mods);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_KEYBOARD_CHAR:
|
||||
mp_update_text(state, event->character.codepoint);
|
||||
case OC_EVENT_KEYBOARD_CHAR:
|
||||
oc_update_text(state, event->character.codepoint);
|
||||
break;
|
||||
|
||||
case MP_EVENT_KEYBOARD_MODS:
|
||||
mp_update_key_mods(state, event->key.mods);
|
||||
case OC_EVENT_KEYBOARD_MODS:
|
||||
oc_update_key_mods(state, event->key.mods);
|
||||
break;
|
||||
|
||||
case MP_EVENT_MOUSE_MOVE:
|
||||
mp_update_mouse_move(state, event->mouse.x, event->mouse.y, event->mouse.deltaX, event->mouse.deltaY);
|
||||
case OC_EVENT_MOUSE_MOVE:
|
||||
oc_update_mouse_move(state, event->mouse.x, event->mouse.y, event->mouse.deltaX, event->mouse.deltaY);
|
||||
break;
|
||||
|
||||
case MP_EVENT_MOUSE_WHEEL:
|
||||
mp_update_mouse_wheel(state, event->mouse.deltaX, event->mouse.deltaY);
|
||||
case OC_EVENT_MOUSE_WHEEL:
|
||||
oc_update_mouse_wheel(state, event->mouse.deltaX, event->mouse.deltaY);
|
||||
break;
|
||||
|
||||
case MP_EVENT_MOUSE_BUTTON:
|
||||
case OC_EVENT_MOUSE_BUTTON:
|
||||
{
|
||||
mp_key_state* key = &state->mouse.buttons[event->key.code];
|
||||
mp_update_key_state(state, key, event->key.action);
|
||||
oc_key_state* key = &state->mouse.buttons[event->key.code];
|
||||
oc_update_key_state(state, key, event->key.action);
|
||||
|
||||
if(event->key.action == MP_KEY_PRESS)
|
||||
if(event->key.action == OC_KEY_PRESS)
|
||||
{
|
||||
if(event->key.clickCount >= 1)
|
||||
{
|
||||
|
@ -160,7 +160,7 @@ void mp_input_process_event(mp_input_state* state, mp_event* event)
|
|||
}
|
||||
}
|
||||
|
||||
mp_update_key_mods(state, event->key.mods);
|
||||
oc_update_key_mods(state, event->key.mods);
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
@ -172,27 +172,27 @@ void mp_input_process_event(mp_input_state* state, mp_event* event)
|
|||
// Input state polling
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
mp_key_state mp_key_get_state(mp_input_state* input, mp_key_code key)
|
||||
oc_key_state oc_key_get_state(oc_input_state* input, oc_key_code key)
|
||||
{
|
||||
mp_key_state state = {0};
|
||||
if(key <= MP_KEY_COUNT)
|
||||
oc_key_state state = {0};
|
||||
if(key <= OC_KEY_COUNT)
|
||||
{
|
||||
state = input->keyboard.keys[key];
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
mp_key_state mp_mouse_button_get_state(mp_input_state* input, mp_mouse_button button)
|
||||
oc_key_state oc_mouse_button_get_state(oc_input_state* input, oc_mouse_button button)
|
||||
{
|
||||
mp_key_state state = {0};
|
||||
if(button <= MP_MOUSE_BUTTON_COUNT)
|
||||
oc_key_state state = {0};
|
||||
if(button <= OC_MOUSE_BUTTON_COUNT)
|
||||
{
|
||||
state = input->mouse.buttons[button];
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
int mp_key_state_press_count(mp_input_state* input, mp_key_state* key)
|
||||
int oc_key_state_press_count(oc_input_state* input, oc_key_state* key)
|
||||
{
|
||||
int count = 0;
|
||||
if(key->lastUpdate == input->frameCounter)
|
||||
|
@ -207,7 +207,7 @@ int mp_key_state_press_count(mp_input_state* input, mp_key_state* key)
|
|||
return(count);
|
||||
}
|
||||
|
||||
int mp_key_state_release_count(mp_input_state* input, mp_key_state* key)
|
||||
int oc_key_state_release_count(oc_input_state* input, oc_key_state* key)
|
||||
{
|
||||
int count = 0;
|
||||
if(key->lastUpdate == input->frameCounter)
|
||||
|
@ -222,7 +222,7 @@ int mp_key_state_release_count(mp_input_state* input, mp_key_state* key)
|
|||
return(count);
|
||||
}
|
||||
|
||||
int mp_key_state_repeat_count(mp_input_state* input, mp_key_state* key)
|
||||
int oc_key_state_repeat_count(oc_input_state* input, oc_key_state* key)
|
||||
{
|
||||
int count = 0;
|
||||
if(key->lastUpdate == input->frameCounter)
|
||||
|
@ -232,78 +232,78 @@ int mp_key_state_repeat_count(mp_input_state* input, mp_key_state* key)
|
|||
return(count);
|
||||
}
|
||||
|
||||
bool mp_key_down(mp_input_state* input, mp_key_code key)
|
||||
bool oc_key_down(oc_input_state* input, oc_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_key_get_state(input, key);
|
||||
oc_key_state state = oc_key_get_state(input, key);
|
||||
return(state.down);
|
||||
}
|
||||
|
||||
int mp_key_pressed(mp_input_state* input, mp_key_code key)
|
||||
int oc_key_pressed(oc_input_state* input, oc_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_key_get_state(input, key);
|
||||
int res = mp_key_state_press_count(input, &state);
|
||||
oc_key_state state = oc_key_get_state(input, key);
|
||||
int res = oc_key_state_press_count(input, &state);
|
||||
return(res);
|
||||
}
|
||||
|
||||
int mp_key_released(mp_input_state* input, mp_key_code key)
|
||||
int oc_key_released(oc_input_state* input, oc_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_key_get_state(input, key);
|
||||
int res = mp_key_state_release_count(input, &state);
|
||||
oc_key_state state = oc_key_get_state(input, key);
|
||||
int res = oc_key_state_release_count(input, &state);
|
||||
return(res);
|
||||
}
|
||||
|
||||
int mp_key_repeated(mp_input_state* input, mp_key_code key)
|
||||
int oc_key_repeated(oc_input_state* input, oc_key_code key)
|
||||
{
|
||||
mp_key_state state = mp_key_get_state(input, key);
|
||||
int res = mp_key_state_repeat_count(input, &state);
|
||||
oc_key_state state = oc_key_get_state(input, key);
|
||||
int res = oc_key_state_repeat_count(input, &state);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_mouse_down(mp_input_state* input, mp_mouse_button button)
|
||||
bool oc_mouse_down(oc_input_state* input, oc_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_mouse_button_get_state(input, button);
|
||||
oc_key_state state = oc_mouse_button_get_state(input, button);
|
||||
return(state.down);
|
||||
}
|
||||
|
||||
int mp_mouse_pressed(mp_input_state* input, mp_mouse_button button)
|
||||
int oc_mouse_pressed(oc_input_state* input, oc_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_mouse_button_get_state(input, button);
|
||||
int res = mp_key_state_press_count(input, &state);
|
||||
oc_key_state state = oc_mouse_button_get_state(input, button);
|
||||
int res = oc_key_state_press_count(input, &state);
|
||||
return(res);
|
||||
}
|
||||
|
||||
int mp_mouse_released(mp_input_state* input, mp_mouse_button button)
|
||||
int oc_mouse_released(oc_input_state* input, oc_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_mouse_button_get_state(input, button);
|
||||
int res = mp_key_state_release_count(input, &state);
|
||||
oc_key_state state = oc_mouse_button_get_state(input, button);
|
||||
int res = oc_key_state_release_count(input, &state);
|
||||
return(res);
|
||||
}
|
||||
|
||||
bool mp_mouse_clicked(mp_input_state* input, mp_mouse_button button)
|
||||
bool oc_mouse_clicked(oc_input_state* input, oc_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_mouse_button_get_state(input, button);
|
||||
oc_key_state state = oc_mouse_button_get_state(input, button);
|
||||
bool clicked = state.sysClicked && (state.lastUpdate == input->frameCounter);
|
||||
return(clicked);
|
||||
}
|
||||
|
||||
bool mp_mouse_double_clicked(mp_input_state* input, mp_mouse_button button)
|
||||
bool oc_mouse_double_clicked(oc_input_state* input, oc_mouse_button button)
|
||||
{
|
||||
mp_key_state state = mp_mouse_button_get_state(input, button);
|
||||
oc_key_state state = oc_mouse_button_get_state(input, button);
|
||||
bool doubleClicked = state.sysClicked && (state.lastUpdate == input->frameCounter);
|
||||
return(doubleClicked);
|
||||
}
|
||||
|
||||
mp_keymod_flags mp_key_mods(mp_input_state* input)
|
||||
oc_keymod_flags oc_key_mods(oc_input_state* input)
|
||||
{
|
||||
return(input->keyboard.mods);
|
||||
}
|
||||
|
||||
vec2 mp_mouse_position(mp_input_state* input)
|
||||
oc_vec2 oc_mouse_position(oc_input_state* input)
|
||||
{
|
||||
return(input->mouse.pos);
|
||||
}
|
||||
|
||||
vec2 mp_mouse_delta(mp_input_state* input)
|
||||
oc_vec2 oc_mouse_delta(oc_input_state* input)
|
||||
{
|
||||
if(input->mouse.lastUpdate == input->frameCounter)
|
||||
{
|
||||
|
@ -311,11 +311,11 @@ vec2 mp_mouse_delta(mp_input_state* input)
|
|||
}
|
||||
else
|
||||
{
|
||||
return((vec2){0, 0});
|
||||
return((oc_vec2){0, 0});
|
||||
}
|
||||
}
|
||||
|
||||
vec2 mp_mouse_wheel(mp_input_state* input)
|
||||
oc_vec2 oc_mouse_wheel(oc_input_state* input)
|
||||
{
|
||||
if(input->mouse.lastUpdate == input->frameCounter)
|
||||
{
|
||||
|
@ -323,26 +323,26 @@ vec2 mp_mouse_wheel(mp_input_state* input)
|
|||
}
|
||||
else
|
||||
{
|
||||
return((vec2){0, 0});
|
||||
return((oc_vec2){0, 0});
|
||||
}
|
||||
}
|
||||
|
||||
str32 mp_input_text_utf32(mp_input_state* input, mem_arena* arena)
|
||||
oc_str32 oc_input_text_utf32(oc_input_state* input, oc_arena* arena)
|
||||
{
|
||||
str32 res = {0};
|
||||
oc_str32 res = {0};
|
||||
if(input->text.lastUpdate == input->frameCounter)
|
||||
{
|
||||
res = str32_push_copy(arena, input->text.codePoints);
|
||||
res = oc_str32_push_copy(arena, input->text.codePoints);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
str8 mp_input_text_utf8(mp_input_state* input, mem_arena* arena)
|
||||
oc_str8 oc_input_text_utf8(oc_input_state* input, oc_arena* arena)
|
||||
{
|
||||
str8 res = {0};
|
||||
oc_str8 res = {0};
|
||||
if(input->text.lastUpdate == input->frameCounter)
|
||||
{
|
||||
res = utf8_push_from_codepoints(arena, input->text.codePoints);
|
||||
res = oc_utf8_push_from_codepoints(arena, input->text.codePoints);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue