Merge branch 'main' into clang-format
This commit is contained in:
commit
a931f08067
|
@ -28,7 +28,6 @@ src/orca_surface.c
|
||||||
src/graphics/orca_gl31.h
|
src/graphics/orca_gl31.h
|
||||||
*bind_gen.c
|
*bind_gen.c
|
||||||
*_stubs.c
|
*_stubs.c
|
||||||
gles_gen.log
|
|
||||||
|
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
|
|
45
orca
45
orca
|
@ -7,24 +7,45 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
root = True
|
if __name__ != "__main__":
|
||||||
try:
|
print("why are you importing the orca command-line tool as a Python module, you absolute goofball")
|
||||||
os.stat(".orcaroot")
|
exit(1)
|
||||||
except FileNotFoundError:
|
|
||||||
root = False
|
|
||||||
|
|
||||||
if root:
|
|
||||||
# Running from Orca source checkout; use local source's scripts.
|
|
||||||
|
|
||||||
scriptdir = os.path.dirname(os.path.abspath(__file__))
|
# If you modify this, be sure to modify the version in scripts/dev.py as well.
|
||||||
if scriptdir != os.getcwd():
|
def check_if_source():
|
||||||
# Only print this warning if running the system-installed Orca.
|
def path_is_in_orca_source(path):
|
||||||
# It's annoying to see this if you run ./orca from the source.
|
dir = path
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
os.stat(os.path.join(dir, ".orcaroot"))
|
||||||
|
return (True, dir)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
newdir = os.path.dirname(dir)
|
||||||
|
if newdir == dir:
|
||||||
|
return (False, None)
|
||||||
|
dir = newdir
|
||||||
|
|
||||||
|
in_source, current_source_dir = path_is_in_orca_source(os.getcwd())
|
||||||
|
script_is_source, script_source_dir = path_is_in_orca_source(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
use_source = in_source or script_is_source
|
||||||
|
source_dir = current_source_dir or script_source_dir
|
||||||
|
return (use_source, source_dir, script_is_source)
|
||||||
|
|
||||||
|
|
||||||
|
use_source, source_dir, is_source = check_if_source()
|
||||||
|
if use_source:
|
||||||
|
# Use the source checkout's scripts instead of the system-installed scripts.
|
||||||
|
|
||||||
|
if not is_source:
|
||||||
print("The Orca tool is running from a local source checkout and will")
|
print("The Orca tool is running from a local source checkout and will")
|
||||||
print("use that instead of the system Orca installation.")
|
print("use that instead of the system Orca installation.")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
sys.path.append(os.getcwd())
|
sys.path.append(source_dir)
|
||||||
import scripts.orca
|
import scripts.orca
|
||||||
else:
|
else:
|
||||||
# Running from outside Orca source checkout; use system Orca install.
|
# Running from outside Orca source checkout; use system Orca install.
|
||||||
|
|
|
@ -162,23 +162,23 @@ GLuint compile_shader(const char* vs, const char* fs)
|
||||||
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
||||||
if(status != GL_TRUE)
|
if(status != GL_TRUE)
|
||||||
{
|
{
|
||||||
log_error("program failed to link: ");
|
oc_log_error("program failed to link: ");
|
||||||
int logSize = 0;
|
int logSize = 0;
|
||||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logSize);
|
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logSize);
|
||||||
|
|
||||||
mem_arena_scope scratch = mem_scratch_begin();
|
oc_arena_scope scratch = oc_scratch_begin();
|
||||||
char* log = mem_arena_alloc(scratch.arena, logSize);
|
char* log = oc_arena_push(scratch.arena, logSize);
|
||||||
|
|
||||||
glGetProgramInfoLog(prog, logSize, 0, log);
|
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();
|
int err = glGetError();
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
log_error("gl error %i\n", err);
|
oc_log_error("gl error %i\n", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(prog);
|
return(prog);
|
||||||
|
@ -186,7 +186,7 @@ GLuint compile_shader(const char* vs, const char* fs)
|
||||||
|
|
||||||
void init_advect(advect_program* program)
|
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->prog = compile_shader(glsl_common_vertex, glsl_advect);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->src = glGetUniformLocation(program->prog, "src");
|
program->src = glGetUniformLocation(program->prog, "src");
|
||||||
|
@ -197,7 +197,7 @@ void init_advect(advect_program* program)
|
||||||
|
|
||||||
void init_div(div_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->prog = compile_shader(glsl_common_vertex, glsl_divergence);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->src = glGetUniformLocation(program->prog, "src");
|
program->src = glGetUniformLocation(program->prog, "src");
|
||||||
|
@ -205,7 +205,7 @@ void init_div(div_program* program)
|
||||||
|
|
||||||
void init_jacobi(jacobi_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->prog = compile_shader(glsl_common_vertex, glsl_jacobi_step);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->xTex = glGetUniformLocation(program->prog, "xTex");
|
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)
|
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->prog = compile_shader(glsl_common_vertex, glsl_multigrid_restrict_residual);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->xTex = glGetUniformLocation(program->prog, "xTex");
|
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)
|
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->prog = compile_shader(glsl_common_vertex, glsl_multigrid_correct);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->src = glGetUniformLocation(program->prog, "src");
|
program->src = glGetUniformLocation(program->prog, "src");
|
||||||
|
@ -233,7 +233,7 @@ void init_multigrid_correct(multigrid_correct_program* program)
|
||||||
|
|
||||||
void init_subtract(subtract_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->prog = compile_shader(glsl_common_vertex, glsl_subtract_pressure);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->src = glGetUniformLocation(program->prog, "src");
|
program->src = glGetUniformLocation(program->prog, "src");
|
||||||
|
@ -243,7 +243,7 @@ void init_subtract(subtract_program* program)
|
||||||
|
|
||||||
void init_splat(splat_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->prog = compile_shader(glsl_common_vertex, glsl_splat);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->src = glGetUniformLocation(program->prog, "src");
|
program->src = glGetUniformLocation(program->prog, "src");
|
||||||
|
@ -257,7 +257,7 @@ void init_splat(splat_program* program)
|
||||||
|
|
||||||
void init_blit(blit_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->prog = compile_shader(glsl_blit_vertex, glsl_blit_fragment);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||||
|
@ -267,7 +267,7 @@ void init_blit(blit_program* program)
|
||||||
|
|
||||||
void init_blit_div(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->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_div_fragment);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
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)
|
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->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_residue_fragment);
|
||||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||||
|
@ -325,7 +325,7 @@ void init_frame_buffer(frame_buffer* framebuffer,
|
||||||
GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if(err != GL_FRAMEBUFFER_COMPLETE)
|
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()
|
void reset()
|
||||||
{
|
{
|
||||||
// resetCmd = true;
|
// resetCmd = true;
|
||||||
log_info("reset");
|
oc_log_info("reset");
|
||||||
|
|
||||||
reset_texture(colorBuffer.textures[0], texWidth, texHeight, (char*)colorInitData);
|
reset_texture(colorBuffer.textures[0], texWidth, texHeight, (char*)colorInitData);
|
||||||
reset_texture(colorBuffer.textures[1], texWidth, texHeight, (char*)colorInitData);
|
reset_texture(colorBuffer.textures[1], texWidth, texHeight, (char*)colorInitData);
|
||||||
|
@ -407,17 +407,17 @@ int frameWidth = 800;
|
||||||
int frameHeight = 600;
|
int frameHeight = 600;
|
||||||
|
|
||||||
|
|
||||||
ORCA_EXPORT void OnMouseDown(int button)
|
ORCA_EXPORT void oc_on_mouse_down(int button)
|
||||||
{
|
{
|
||||||
mouseInput.down = true;
|
mouseInput.down = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ORCA_EXPORT void OnMouseUp(int button)
|
ORCA_EXPORT void oc_on_mouse_up(int button)
|
||||||
{
|
{
|
||||||
mouseInput.down = false;
|
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.x = x * 2;
|
||||||
mouseInput.y = y * 2;
|
mouseInput.y = y * 2;
|
||||||
|
@ -611,14 +611,14 @@ void input_splat(float t)
|
||||||
|
|
||||||
float testDiv[texWidth/2][texWidth/2][4];
|
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();
|
surface = oc_surface_gles();
|
||||||
mg_surface_prepare(surface);
|
oc_surface_select(surface);
|
||||||
|
|
||||||
// init_color_checker();
|
// init_color_checker();
|
||||||
// init_velocity_vortex();
|
// init_velocity_vortex();
|
||||||
|
@ -637,17 +637,17 @@ ORCA_EXPORT void OnInit()
|
||||||
init_blit_div(&blitDivProgram);
|
init_blit_div(&blitDivProgram);
|
||||||
|
|
||||||
// init frame buffers
|
// 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);
|
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);
|
init_frame_buffer(&velocityBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)velocityInitData);
|
||||||
|
|
||||||
int gridFactor = 1;
|
int gridFactor = 1;
|
||||||
for(int i=0; i<MULTIGRID_COUNT; i++)
|
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);
|
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);
|
init_frame_buffer(&pressureBuffer[i], texWidth/gridFactor, texHeight/gridFactor, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
|
||||||
gridFactor *= 2;
|
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;
|
frameWidth = width*2;
|
||||||
frameHeight = height*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?
|
float aspectRatio = texWidth/texHeight; //TODO replace with actual aspect ratio?
|
||||||
|
|
||||||
static float t = 0;
|
static float t = 0;
|
||||||
t += 1./60.;
|
t += 1./60.;
|
||||||
|
|
||||||
mg_surface_prepare(surface);
|
oc_surface_select(surface);
|
||||||
|
|
||||||
glViewport(0, 0, texWidth, texHeight);
|
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>
|
#include <orca.h>
|
||||||
|
|
||||||
vec2 frameSize = {100, 100};
|
oc_vec2 frameSize = {100, 100};
|
||||||
|
|
||||||
mg_surface surface;
|
oc_surface surface;
|
||||||
|
|
||||||
unsigned int program;
|
unsigned int program;
|
||||||
|
|
||||||
|
@ -31,26 +31,24 @@ void compile_shader(GLuint shader, const char* source)
|
||||||
int err = glGetError();
|
int err = glGetError();
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
log_info("gl error");
|
oc_log_info("gl error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ORCA_IMPORT(orca_mem_grow)(u64 size);
|
ORCA_EXPORT void oc_on_init(void)
|
||||||
|
|
||||||
ORCA_EXPORT void OnInit(void)
|
|
||||||
{
|
{
|
||||||
surface = mg_surface_gles();
|
surface = oc_surface_gles();
|
||||||
mg_surface_prepare(surface);
|
oc_surface_select(surface);
|
||||||
|
|
||||||
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
|
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;
|
int extensionCount = 0;
|
||||||
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
|
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
|
||||||
for(int i=0; i<extensionCount; i++)
|
for(int i=0; i<extensionCount; i++)
|
||||||
{
|
{
|
||||||
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, 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);
|
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
@ -78,18 +76,18 @@ ORCA_EXPORT void OnInit(void)
|
||||||
glEnableVertexAttribArray(0);
|
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.x = width;
|
||||||
frameSize.y = height;
|
frameSize.y = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
ORCA_EXPORT void OnFrameRefresh(void)
|
ORCA_EXPORT void oc_on_frame_refresh(void)
|
||||||
{
|
{
|
||||||
f32 aspect = frameSize.x/frameSize.y;
|
f32 aspect = frameSize.x/frameSize.y;
|
||||||
|
|
||||||
mg_surface_prepare(surface);
|
oc_surface_select(surface);
|
||||||
|
|
||||||
glClearColor(0, 1, 1, 1);
|
glClearColor(0, 1, 1, 1);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
@ -108,5 +106,5 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
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
|
#define PADDLE_MAX_LAUNCH_ANGLE 0.7f
|
||||||
|
|
||||||
const mg_color paddleColor = { 1, 0, 0, 1 };
|
const oc_color paddleColor = { 1, 0, 0, 1 };
|
||||||
mp_rect paddle = { 300, 50, 200, 24 };
|
oc_rect paddle = { 300, 50, 200, 24 };
|
||||||
|
|
||||||
const mg_color ballColor = { 1, 1, 0, 1 };
|
const oc_color ballColor = { 1, 1, 0, 1 };
|
||||||
mp_rect ball = { 200, 200, 20, 20 };
|
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.
|
// This is upside down from how it will actually be drawn.
|
||||||
int blockHealth[NUM_BLOCKS] = {
|
int blockHealth[NUM_BLOCKS] = {
|
||||||
|
@ -31,128 +31,128 @@ int blockHealth[NUM_BLOCKS] = {
|
||||||
3, 3, 3, 3, 3, 3, 3
|
3, 3, 3, 3, 3, 3, 3
|
||||||
};
|
};
|
||||||
|
|
||||||
vec2 frameSize = { 100, 100 };
|
oc_vec2 frameSize = { 100, 100 };
|
||||||
|
|
||||||
bool leftDown = false;
|
bool leftDown = false;
|
||||||
bool rightDown = false;
|
bool rightDown = false;
|
||||||
|
|
||||||
mg_surface surface;
|
oc_surface surface;
|
||||||
mg_canvas canvas;
|
oc_canvas canvas;
|
||||||
mg_image waterImage;
|
oc_image waterImage;
|
||||||
mg_image ballImage;
|
oc_image ballImage;
|
||||||
mg_image paddleImage;
|
oc_image paddleImage;
|
||||||
mg_font pongFont;
|
oc_font pongFont;
|
||||||
|
|
||||||
f32 lerp(f32 a, f32 b, f32 t);
|
f32 lerp(f32 a, f32 b, f32 t);
|
||||||
mp_rect blockRect(int i);
|
oc_rect blockRect(int i);
|
||||||
int checkCollision(mp_rect block);
|
int checkCollision(oc_rect block);
|
||||||
mg_mat2x3 flipY(mp_rect r);
|
oc_mat2x3 flipY(oc_rect r);
|
||||||
mg_mat2x3 flipYAt(vec2 pos);
|
oc_mat2x3 flipYAt(oc_vec2 pos);
|
||||||
|
|
||||||
str8 loadFile(mem_arena* arena, str8 filename)
|
oc_str8 loadFile(oc_arena* arena, oc_str8 filename)
|
||||||
{
|
{
|
||||||
file_handle file = file_open(filename, FILE_ACCESS_READ, 0);
|
oc_file file = oc_file_open(filename, OC_FILE_ACCESS_READ, 0);
|
||||||
if(file_last_error(file) != IO_OK)
|
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);
|
u64 size = oc_file_size(file);
|
||||||
char* buffer = mem_arena_alloc(arena, size);
|
char* buffer = oc_arena_push(arena, size);
|
||||||
file_read(file, size, buffer);
|
oc_file_read(file, size, buffer);
|
||||||
file_close(file);
|
oc_file_close(file);
|
||||||
return str8_from_buffer(size, buffer);
|
return oc_str8_from_buffer(size, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ORCA_EXPORT void OnInit(void)
|
ORCA_EXPORT void oc_on_init(void)
|
||||||
{
|
{
|
||||||
surface = mg_surface_canvas();
|
surface = oc_surface_canvas();
|
||||||
canvas = mg_canvas_create();
|
canvas = oc_canvas_create();
|
||||||
|
|
||||||
waterImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/underwater.jpg")), false);
|
waterImage = oc_image_create_from_memory(surface, loadFile(oc_scratch(), OC_STR8("/underwater.jpg")), false);
|
||||||
ballImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/ball.png")), false);
|
ballImage = oc_image_create_from_memory(surface, loadFile(oc_scratch(), OC_STR8("/ball.png")), false);
|
||||||
paddleImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/wall.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"));
|
oc_str8 fontStr = loadFile(oc_scratch(), OC_STR8("/Literata-SemiBoldItalic.ttf"));
|
||||||
unicode_range ranges[5] = { UNICODE_RANGE_BASIC_LATIN,
|
oc_unicode_range ranges[5] = { OC_UNICODE_BASIC_LATIN,
|
||||||
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||||
UNICODE_RANGE_LATIN_EXTENDED_A,
|
OC_UNICODE_LATIN_EXTENDED_A,
|
||||||
UNICODE_RANGE_LATIN_EXTENDED_B,
|
OC_UNICODE_LATIN_EXTENDED_B,
|
||||||
UNICODE_RANGE_SPECIALS };
|
OC_UNICODE_SPECIALS };
|
||||||
//NOTE(ben): Weird that images are "create from data" but fonts are "create from memory"
|
// 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
|
// 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.x = width;
|
||||||
frameSize.y = height;
|
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;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("key down: %i", key);
|
oc_log_info("key down: %i", key);
|
||||||
if(key == MP_KEY_LEFT)
|
if(key == OC_KEY_LEFT)
|
||||||
{
|
{
|
||||||
leftDown = true;
|
leftDown = true;
|
||||||
}
|
}
|
||||||
if(key == MP_KEY_RIGHT)
|
if(key == OC_KEY_RIGHT)
|
||||||
{
|
{
|
||||||
rightDown = true;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("key up: %i", key);
|
oc_log_info("key up: %i", key);
|
||||||
if(key == MP_KEY_LEFT)
|
if(key == OC_KEY_LEFT)
|
||||||
{
|
{
|
||||||
leftDown = false;
|
leftDown = false;
|
||||||
}
|
}
|
||||||
if(key == MP_KEY_RIGHT)
|
if(key == OC_KEY_RIGHT)
|
||||||
{
|
{
|
||||||
rightDown = false;
|
rightDown = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ORCA_EXPORT void OnFrameRefresh(void)
|
ORCA_EXPORT void oc_on_frame_refresh(void)
|
||||||
{
|
{
|
||||||
f32 aspect = frameSize.x / frameSize.y;
|
f32 aspect = frameSize.x / frameSize.y;
|
||||||
|
|
||||||
|
@ -164,12 +164,12 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
||||||
{
|
{
|
||||||
paddle.x += 10;
|
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.x += velocity.x;
|
||||||
ball.y += velocity.y;
|
ball.y += velocity.y;
|
||||||
ball.x = Clamp(ball.x, 0, frameSize.x - ball.w);
|
ball.x = oc_clamp(ball.x, 0, frameSize.x - ball.w);
|
||||||
ball.y = Clamp(ball.y, 0, frameSize.y - ball.h);
|
ball.y = oc_clamp(ball.y, 0, frameSize.y - ball.h);
|
||||||
|
|
||||||
if(ball.x + ball.w >= frameSize.x)
|
if(ball.x + ball.w >= frameSize.x)
|
||||||
{
|
{
|
||||||
|
@ -190,13 +190,13 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
||||||
f32 t = ((ball.x + ball.w / 2) - paddle.x) / paddle.w;
|
f32 t = ((ball.x + ball.w / 2) - paddle.x) / paddle.w;
|
||||||
f32 launchAngle = lerp(-PADDLE_MAX_LAUNCH_ANGLE, PADDLE_MAX_LAUNCH_ANGLE, t);
|
f32 launchAngle = lerp(-PADDLE_MAX_LAUNCH_ANGLE, PADDLE_MAX_LAUNCH_ANGLE, t);
|
||||||
f32 speed = sqrtf(velocity.x * velocity.x + velocity.y * velocity.y);
|
f32 speed = sqrtf(velocity.x * velocity.x + velocity.y * velocity.y);
|
||||||
velocity = (vec2){
|
velocity = (oc_vec2){
|
||||||
sinf(launchAngle) * speed,
|
sinf(launchAngle) * speed,
|
||||||
cosf(launchAngle) * speed,
|
cosf(launchAngle) * speed,
|
||||||
};
|
};
|
||||||
ball.y = paddle.y + paddle.h;
|
ball.y = paddle.y + paddle.h;
|
||||||
|
|
||||||
log_info("PONG!");
|
oc_log_info("PONG!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ball.y <= 0)
|
if(ball.y <= 0)
|
||||||
|
@ -212,11 +212,11 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_rect r = blockRect(i);
|
oc_rect r = blockRect(i);
|
||||||
int result = checkCollision(r);
|
int result = checkCollision(r);
|
||||||
if(result)
|
if(result)
|
||||||
{
|
{
|
||||||
log_info("Collision! direction=%d", result);
|
oc_log_info("Collision! direction=%d", result);
|
||||||
blockHealth[i] -= 1;
|
blockHealth[i] -= 1;
|
||||||
|
|
||||||
f32 vx = velocity.x;
|
f32 vx = velocity.x;
|
||||||
|
@ -246,19 +246,19 @@ 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);
|
oc_set_color_rgba(10.0f / 255.0f, 31.0f / 255.0f, 72.0f / 255.0f, 1);
|
||||||
mg_clear();
|
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,
|
1, 0, 0,
|
||||||
0, -1, frameSize.y
|
0, -1, frameSize.y
|
||||||
};
|
};
|
||||||
|
|
||||||
mg_matrix_push(yUp);
|
oc_matrix_push(yUp);
|
||||||
{
|
{
|
||||||
for(int i = 0; i < NUM_BLOCKS; i++)
|
for(int i = 0; i < NUM_BLOCKS; i++)
|
||||||
{
|
{
|
||||||
|
@ -267,55 +267,55 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_rect r = blockRect(i);
|
oc_rect r = blockRect(i);
|
||||||
mg_set_color_rgba(0, 0, 0, 0.2);
|
oc_set_color_rgba(0, 0, 0, 0.2);
|
||||||
mg_rounded_rectangle_fill(r.x, r.y - 2, r.w, r.h, 4);
|
oc_rounded_rectangle_fill(r.x, r.y - 2, r.w, r.h, 4);
|
||||||
mg_set_color_rgba(0.9, 0.9, 0.9, 1);
|
oc_set_color_rgba(0.9, 0.9, 0.9, 1);
|
||||||
mg_rounded_rectangle_fill(r.x, r.y, r.w, r.h, 4);
|
oc_rounded_rectangle_fill(r.x, r.y, r.w, r.h, 4);
|
||||||
|
|
||||||
int fontSize = 18;
|
int fontSize = 18;
|
||||||
str8 text = str8_pushf(mem_scratch(),
|
oc_str8 text = oc_str8_pushf(oc_scratch(),
|
||||||
"%d", blockHealth[i]);
|
"%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.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);
|
oc_set_color_rgba(0, 0, 0, 1);
|
||||||
mg_set_font(pongFont);
|
oc_set_font(pongFont);
|
||||||
mg_set_font_size(18);
|
oc_set_font_size(18);
|
||||||
mg_move_to(textPos.x, textPos.y);
|
oc_move_to(textPos.x, textPos.y);
|
||||||
mg_matrix_push(flipYAt(textPos));
|
oc_matrix_push(flipYAt(textPos));
|
||||||
{
|
{
|
||||||
mg_text_outlines(text);
|
oc_text_outlines(text);
|
||||||
mg_fill();
|
oc_fill();
|
||||||
}
|
}
|
||||||
mg_matrix_pop();
|
oc_matrix_pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_set_color_rgba(0.9, 0.9, 0.9, 1);
|
oc_set_color_rgba(0.9, 0.9, 0.9, 1);
|
||||||
mg_rounded_rectangle_fill(paddle.x, paddle.y, paddle.w, paddle.h, 4);
|
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);
|
oc_surface_select(surface);
|
||||||
mg_render(surface, canvas);
|
oc_render(surface, canvas);
|
||||||
mg_surface_present(surface);
|
oc_surface_present(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_rect blockRect(int i)
|
oc_rect blockRect(int i)
|
||||||
{
|
{
|
||||||
int row = i / NUM_BLOCKS_PER_ROW;
|
int row = i / NUM_BLOCKS_PER_ROW;
|
||||||
int col = 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_PADDING + (BLOCKS_PADDING + BLOCK_WIDTH) * col,
|
||||||
BLOCKS_BOTTOM + (BLOCKS_PADDING + BLOCK_HEIGHT) * row,
|
BLOCKS_BOTTOM + (BLOCKS_PADDING + BLOCK_HEIGHT) * row,
|
||||||
BLOCK_WIDTH,
|
BLOCK_WIDTH,
|
||||||
|
@ -325,7 +325,7 @@ mp_rect blockRect(int i)
|
||||||
|
|
||||||
// Returns a cardinal direction 1-8 for the collision with the block, or zero
|
// 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.
|
// 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.
|
// Note that all the logic for this game has the origin in the bottom left.
|
||||||
|
|
||||||
|
@ -358,8 +358,8 @@ int checkCollision(mp_rect block)
|
||||||
//
|
//
|
||||||
// We assume significant tunneling can't happen.
|
// We assume significant tunneling can't happen.
|
||||||
|
|
||||||
vec2 ballCenter = (vec2){ ball.x + ball.w / 2, ball.y + ball.h / 2 };
|
oc_vec2 ballCenter = (oc_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 blockCenter = (oc_vec2){ block.x + block.w / 2, block.y + block.h / 2 };
|
||||||
|
|
||||||
// Moving right
|
// Moving right
|
||||||
if(velocity.x > 0)
|
if(velocity.x > 0)
|
||||||
|
@ -457,17 +457,17 @@ f32 lerp(f32 a, f32 b, f32 t)
|
||||||
return (1 - t) * a + t * b;
|
return (1 - t) * a + t * b;
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_mat2x3 flipY(mp_rect r)
|
oc_mat2x3 flipY(oc_rect r)
|
||||||
{
|
{
|
||||||
return (mg_mat2x3){
|
return (oc_mat2x3){
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, -1, 2 * r.y + r.h
|
0, -1, 2 * r.y + r.h
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_mat2x3 flipYAt(vec2 pos)
|
oc_mat2x3 flipYAt(oc_vec2 pos)
|
||||||
{
|
{
|
||||||
return (mg_mat2x3){
|
return (oc_mat2x3){
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, -1, 2 * pos.y
|
0, -1, 2 * pos.y
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,230 +1,229 @@
|
||||||
#include"orca.h"
|
#include"orca.h"
|
||||||
|
|
||||||
vec2 frameSize = {100, 100};
|
oc_vec2 frameSize = {100, 100};
|
||||||
|
|
||||||
mg_surface surface;
|
oc_surface surface;
|
||||||
mg_canvas canvas;
|
oc_canvas canvas;
|
||||||
mg_font font;
|
oc_font font;
|
||||||
ui_context ui;
|
oc_ui_context ui;
|
||||||
mem_arena textArena = {0};
|
oc_arena textArena = {0};
|
||||||
|
|
||||||
ORCA_EXPORT void OnInit(void)
|
ORCA_EXPORT void oc_on_init(void)
|
||||||
{
|
{
|
||||||
//TODO create surface for main window
|
surface = oc_surface_canvas();
|
||||||
surface = mg_surface_canvas();
|
canvas = oc_canvas_create();
|
||||||
canvas = mg_canvas_create();
|
oc_ui_init(&ui);
|
||||||
ui_init(&ui);
|
|
||||||
|
|
||||||
//NOTE: load font
|
//NOTE: load font
|
||||||
{
|
{
|
||||||
file_handle file = file_open(STR8("/OpenSansLatinSubset.ttf"), FILE_ACCESS_READ, 0);
|
oc_file file = oc_file_open(OC_STR8("/OpenSansLatinSubset.ttf"), OC_FILE_ACCESS_READ, 0);
|
||||||
if(file_last_error(file) != IO_OK)
|
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);
|
u64 size = oc_file_size(file);
|
||||||
char* buffer = mem_arena_alloc(mem_scratch(), size);
|
char* buffer = oc_arena_push(oc_scratch(), size);
|
||||||
file_read(file, size, buffer);
|
oc_file_read(file, size, buffer);
|
||||||
file_close(file);
|
oc_file_close(file);
|
||||||
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
|
oc_unicode_range ranges[5] = {OC_UNICODE_BASIC_LATIN,
|
||||||
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
|
||||||
UNICODE_RANGE_LATIN_EXTENDED_A,
|
OC_UNICODE_LATIN_EXTENDED_A,
|
||||||
UNICODE_RANGE_LATIN_EXTENDED_B,
|
OC_UNICODE_LATIN_EXTENDED_B,
|
||||||
UNICODE_RANGE_SPECIALS};
|
OC_UNICODE_SPECIALS};
|
||||||
// TODO: Decide whether we're using strings or explicit pointer + length
|
// 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());
|
oc_arena_clear(oc_scratch());
|
||||||
mem_arena_init(&textArena);
|
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.x = width;
|
||||||
frameSize.y = height;
|
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)
|
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.spacing = 10,
|
||||||
.layout.margin.x = 10,
|
.layout.margin.x = 10,
|
||||||
.layout.margin.y = 10,
|
.layout.margin.y = 10,
|
||||||
.layout.align.x = UI_ALIGN_CENTER,
|
.layout.align.x = OC_UI_ALIGN_CENTER,
|
||||||
.layout.align.y = UI_ALIGN_START},
|
.layout.align.y = OC_UI_ALIGN_START},
|
||||||
UI_STYLE_LAYOUT);
|
OC_UI_STYLE_LAYOUT);
|
||||||
|
|
||||||
ui_box_begin(str, UI_FLAG_DRAW_BORDER);
|
oc_ui_box_begin(str, OC_UI_FLAG_DRAW_BORDER);
|
||||||
ui_label(str);
|
oc_ui_label(str);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void widget_end_view(void)
|
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},
|
.color = {1, 1, 1, 1},
|
||||||
.font = font,
|
.font = font,
|
||||||
.fontSize = 16,
|
.fontSize = 16,
|
||||||
.borderColor = {0.278, 0.333, 0.412, 1},
|
.borderColor = {0.278, 0.333, 0.412, 1},
|
||||||
.borderSize = 2};
|
.borderSize = 2};
|
||||||
|
|
||||||
ui_style_mask defaultMask = UI_STYLE_BG_COLOR
|
oc_ui_style_mask defaultMask = OC_UI_STYLE_BG_COLOR
|
||||||
| UI_STYLE_COLOR
|
| OC_UI_STYLE_COLOR
|
||||||
| UI_STYLE_BORDER_COLOR
|
| OC_UI_STYLE_BORDER_COLOR
|
||||||
| UI_STYLE_BORDER_SIZE
|
| OC_UI_STYLE_BORDER_SIZE
|
||||||
| UI_STYLE_FONT
|
| OC_UI_STYLE_FONT
|
||||||
| UI_STYLE_FONT_SIZE;
|
| 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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 1},
|
.size.height = {OC_UI_SIZE_PARENT, 1},
|
||||||
.layout.axis = UI_AXIS_Y,
|
.layout.axis = OC_UI_AXIS_Y,
|
||||||
.layout.align.x = UI_ALIGN_CENTER,
|
.layout.align.x = OC_UI_ALIGN_CENTER,
|
||||||
.layout.align.y = UI_ALIGN_START,
|
.layout.align.y = OC_UI_ALIGN_START,
|
||||||
.layout.spacing = 10,
|
.layout.spacing = 10,
|
||||||
.layout.margin.x = 10,
|
.layout.margin.x = 10,
|
||||||
.layout.margin.y = 10,
|
.layout.margin.y = 10,
|
||||||
.bgColor = {0.11, 0.11, 0.11, 1}},
|
.bgColor = {0.11, 0.11, 0.11, 1}},
|
||||||
UI_STYLE_SIZE
|
OC_UI_STYLE_SIZE
|
||||||
| UI_STYLE_LAYOUT
|
| OC_UI_STYLE_LAYOUT
|
||||||
| UI_STYLE_BG_COLOR);
|
| 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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_CHILDREN},
|
.size.height = {OC_UI_SIZE_CHILDREN},
|
||||||
.layout.align.x = UI_ALIGN_CENTER},
|
.layout.align.x = OC_UI_ALIGN_CENTER},
|
||||||
UI_STYLE_SIZE
|
OC_UI_STYLE_SIZE
|
||||||
|UI_STYLE_LAYOUT_ALIGN_X);
|
|OC_UI_STYLE_LAYOUT_ALIGN_X);
|
||||||
ui_container("title", 0)
|
oc_ui_container("title", 0)
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.fontSize = 26}, UI_STYLE_FONT_SIZE);
|
oc_ui_style_next(&(oc_ui_style){.fontSize = 26}, OC_UI_STYLE_FONT_SIZE);
|
||||||
ui_label("Orca UI Demo");
|
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}},
|
oc_ui_style_next(&(oc_ui_style){.bgColor = {1, 0.99, 0.82, 1}},
|
||||||
UI_STYLE_BG_COLOR);
|
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}},
|
oc_ui_style_next(&(oc_ui_style){.color = {0, 0, 0, 1}},
|
||||||
UI_STYLE_COLOR);
|
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");
|
oc_ui_menu_button("Option 1.2");
|
||||||
ui_menu_button("Option 1.3");
|
oc_ui_menu_button("Option 1.3");
|
||||||
ui_menu_button("Option 1.4");
|
oc_ui_menu_button("Option 1.4");
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_menu("Menu 2")
|
oc_ui_menu("Menu 2")
|
||||||
{
|
{
|
||||||
ui_menu_button("Option 2.1");
|
oc_ui_menu_button("Option 2.1");
|
||||||
ui_menu_button("Option 2.2");
|
oc_ui_menu_button("Option 2.2");
|
||||||
ui_menu_button("Option 2.3");
|
oc_ui_menu_button("Option 2.3");
|
||||||
ui_menu_button("Option 2.4");
|
oc_ui_menu_button("Option 2.4");
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_menu("Menu 3")
|
oc_ui_menu("Menu 3")
|
||||||
{
|
{
|
||||||
ui_menu_button("Option 3.1");
|
oc_ui_menu_button("Option 3.1");
|
||||||
ui_menu_button("Option 3.2");
|
oc_ui_menu_button("Option 3.2");
|
||||||
ui_menu_button("Option 3.3");
|
oc_ui_menu_button("Option 3.3");
|
||||||
ui_menu_button("Option 3.4");
|
oc_ui_menu_button("Option 3.4");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 1, 1}},
|
.size.height = {OC_UI_SIZE_PARENT, 1, 1}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X}, UI_STYLE_LAYOUT_AXIS);
|
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X}, OC_UI_STYLE_LAYOUT_AXIS);
|
||||||
ui_container("contents", 0)
|
oc_ui_container("contents", 0)
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||||
.size.height = {UI_SIZE_PARENT, 1}},
|
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||||
UI_STYLE_SIZE);
|
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.spacing = 10,
|
||||||
.layout.margin.x = 10,
|
.layout.margin.x = 10,
|
||||||
.layout.margin.y = 10,
|
.layout.margin.y = 10,
|
||||||
.size.width = {UI_SIZE_PARENT, 1},
|
.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.5}},
|
.size.height = {OC_UI_SIZE_PARENT, 0.5}},
|
||||||
UI_STYLE_LAYOUT_AXIS
|
OC_UI_STYLE_LAYOUT_AXIS
|
||||||
|UI_STYLE_LAYOUT_SPACING
|
|OC_UI_STYLE_LAYOUT_SPACING
|
||||||
|UI_STYLE_LAYOUT_MARGIN_X
|
|OC_UI_STYLE_LAYOUT_MARGIN_X
|
||||||
|UI_STYLE_LAYOUT_MARGIN_Y
|
|OC_UI_STYLE_LAYOUT_MARGIN_Y
|
||||||
|UI_STYLE_SIZE);
|
|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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||||
.size.height = {UI_SIZE_PARENT, 1}},
|
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
widget_view("Buttons")
|
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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||||
.size.height = {UI_SIZE_PARENT, 1}},
|
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
|
|
||||||
|
|
||||||
ui_pattern pattern = {0};
|
oc_ui_pattern pattern = {0};
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("checkbox")});
|
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_TAG, .tag = oc_ui_tag_make("checkbox")});
|
||||||
ui_style_match_after(pattern,
|
oc_ui_style_match_after(pattern,
|
||||||
&(ui_style){.bgColor = {0, 1, 0, 1},
|
&(oc_ui_style){.bgColor = {0, 1, 0, 1},
|
||||||
.color = {1, 1, 1, 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")
|
widget_view("checkboxes")
|
||||||
{
|
{
|
||||||
|
@ -232,156 +231,156 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
||||||
static bool check2 = false;
|
static bool check2 = false;
|
||||||
static bool check3 = false;
|
static bool check3 = false;
|
||||||
|
|
||||||
ui_checkbox("check1", &check1);
|
oc_ui_checkbox("check1", &check1);
|
||||||
ui_checkbox("check2", &check2);
|
oc_ui_checkbox("check2", &check2);
|
||||||
ui_checkbox("check3", &check3);
|
oc_ui_checkbox("check3", &check3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.layout.axis = UI_AXIS_X,
|
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X,
|
||||||
.size.width = {UI_SIZE_PARENT, 1},
|
.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.5}},
|
.size.height = {OC_UI_SIZE_PARENT, 0.5}},
|
||||||
UI_STYLE_LAYOUT_AXIS
|
OC_UI_STYLE_LAYOUT_AXIS
|
||||||
|UI_STYLE_SIZE);
|
|OC_UI_STYLE_SIZE);
|
||||||
|
|
||||||
ui_container("down", 0)
|
oc_ui_container("down", 0)
|
||||||
{
|
{
|
||||||
widget_view("Vertical Sliders")
|
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},
|
.layout.spacing = 10},
|
||||||
UI_STYLE_LAYOUT_AXIS
|
OC_UI_STYLE_LAYOUT_AXIS
|
||||||
|UI_STYLE_LAYOUT_SPACING);
|
|OC_UI_STYLE_LAYOUT_SPACING);
|
||||||
ui_container("contents", 0)
|
oc_ui_container("contents", 0)
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 20},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20},
|
||||||
.size.height = {UI_SIZE_PIXELS, 200}},
|
.size.height = {OC_UI_SIZE_PIXELS, 200}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
static f32 slider1 = 0;
|
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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20},
|
||||||
.size.height = {UI_SIZE_PIXELS, 200}},
|
.size.height = {OC_UI_SIZE_PIXELS, 200}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
static f32 slider2 = 0;
|
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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20},
|
||||||
.size.height = {UI_SIZE_PIXELS, 200}},
|
.size.height = {OC_UI_SIZE_PIXELS, 200}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
static f32 slider3 = 0;
|
static f32 slider3 = 0;
|
||||||
ui_slider("slider3", 0.2, &slider3);
|
oc_ui_slider("slider3", 0.2, &slider3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
widget_view("Horizontal Sliders")
|
widget_view("Horizontal Sliders")
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 200},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200},
|
||||||
.size.height = {UI_SIZE_PIXELS, 20}},
|
.size.height = {OC_UI_SIZE_PIXELS, 20}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
static f32 slider1 = 0;
|
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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200},
|
||||||
.size.height = {UI_SIZE_PIXELS, 20}},
|
.size.height = {OC_UI_SIZE_PIXELS, 20}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
static f32 slider2 = 0;
|
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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200},
|
||||||
.size.height = {UI_SIZE_PIXELS, 20}},
|
.size.height = {OC_UI_SIZE_PIXELS, 20}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
static f32 slider3 = 0;
|
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},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5},
|
||||||
.size.height = {UI_SIZE_PARENT, 1}},
|
.size.height = {OC_UI_SIZE_PARENT, 1}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
|
|
||||||
ui_container("right", 0)
|
oc_ui_container("right", 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.33}},
|
.size.height = {OC_UI_SIZE_PARENT, 0.33}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
widget_view("Text box")
|
widget_view("Text box")
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, 300},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 300},
|
||||||
.size.height = {UI_SIZE_TEXT}},
|
.size.height = {OC_UI_SIZE_TEXT}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
static str8 text = {0};
|
static oc_str8 text = {0};
|
||||||
ui_text_box_result res = ui_text_box("textbox", mem_scratch(), text);
|
oc_ui_text_box_result res = oc_ui_text_box("textbox", oc_scratch(), text);
|
||||||
if(res.changed)
|
if(res.changed)
|
||||||
{
|
{
|
||||||
mem_arena_clear(&textArena);
|
oc_arena_clear(&textArena);
|
||||||
text = str8_push_copy(&textArena, res.text);
|
text = oc_str8_push_copy(&textArena, res.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.33}},
|
.size.height = {OC_UI_SIZE_PARENT, 0.33}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
widget_view("Test")
|
widget_view("Test")
|
||||||
{
|
{
|
||||||
ui_pattern pattern = {0};
|
oc_ui_pattern pattern = {0};
|
||||||
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("panel")});
|
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_TEXT, .text = OC_STR8("panel")});
|
||||||
ui_style_match_after(pattern, &(ui_style){.bgColor = {0.3, 0.3, 1, 1}}, UI_STYLE_BG_COLOR);
|
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;
|
static int selected = 0;
|
||||||
str8 options[] = {STR8("option 1"),
|
oc_str8 options[] = {OC_STR8("option 1"),
|
||||||
STR8("option 2"),
|
OC_STR8("option 2"),
|
||||||
STR8("long option 3"),
|
OC_STR8("long option 3"),
|
||||||
STR8("option 4"),
|
OC_STR8("option 4"),
|
||||||
STR8("option 5")};
|
OC_STR8("option 5")};
|
||||||
ui_select_popup_info info = {.selectedIndex = selected,
|
oc_ui_select_popup_info info = {.selectedIndex = selected,
|
||||||
.optionCount = 5,
|
.optionCount = 5,
|
||||||
.options = options};
|
.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;
|
selected = result.selectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.33}},
|
.size.height = {OC_UI_SIZE_PARENT, 0.33}},
|
||||||
UI_STYLE_SIZE);
|
OC_UI_STYLE_SIZE);
|
||||||
widget_view("Color")
|
widget_view("Color")
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
|
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1},
|
||||||
.size.height = {UI_SIZE_PARENT, 0.7},
|
.size.height = {OC_UI_SIZE_PARENT, 0.7},
|
||||||
.layout.axis = UI_AXIS_X},
|
.layout.axis = OC_UI_AXIS_X},
|
||||||
UI_STYLE_SIZE
|
OC_UI_STYLE_SIZE
|
||||||
|UI_STYLE_LAYOUT_AXIS);
|
|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},
|
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X},
|
||||||
UI_STYLE_LAYOUT_AXIS);
|
OC_UI_STYLE_LAYOUT_AXIS);
|
||||||
ui_container("contents", 0)
|
oc_ui_container("contents", 0)
|
||||||
{
|
{
|
||||||
ui_style_next(&(ui_style){.layout.spacing = 20},
|
oc_ui_style_next(&(oc_ui_style){.layout.spacing = 20},
|
||||||
UI_STYLE_LAYOUT_SPACING);
|
OC_UI_STYLE_LAYOUT_SPACING);
|
||||||
ui_container("buttons", 0)
|
oc_ui_container("buttons", 0)
|
||||||
{
|
{
|
||||||
ui_button("Button A");
|
oc_ui_button("Button A");
|
||||||
ui_button("Button B");
|
oc_ui_button("Button B");
|
||||||
ui_button("Button C");
|
oc_ui_button("Button C");
|
||||||
ui_button("Button D");
|
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},
|
.layout.spacing = 20},
|
||||||
UI_STYLE_LAYOUT_SPACING
|
OC_UI_STYLE_LAYOUT_SPACING
|
||||||
|UI_STYLE_LAYOUT_AXIS);
|
|OC_UI_STYLE_LAYOUT_AXIS);
|
||||||
|
|
||||||
ui_container("buttons2", 0)
|
oc_ui_container("buttons2", 0)
|
||||||
{
|
{
|
||||||
ui_button("Button A");
|
oc_ui_button("Button A");
|
||||||
ui_button("Button B");
|
oc_ui_button("Button B");
|
||||||
ui_button("Button C");
|
oc_ui_button("Button C");
|
||||||
ui_button("Button D");
|
oc_ui_button("Button D");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,9 +392,9 @@ ORCA_EXPORT void OnFrameRefresh(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mg_canvas_set_current(canvas);
|
oc_canvas_set_current(canvas);
|
||||||
mg_surface_prepare(surface);
|
oc_surface_select(surface);
|
||||||
ui_draw();
|
oc_ui_draw();
|
||||||
mg_render(surface, canvas);
|
oc_render(surface, canvas);
|
||||||
mg_surface_present(surface);
|
oc_surface_present(surface);
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,8 +155,8 @@ def bindgen(apiName, spec, **kwargs):
|
||||||
if argTag == 'p' and argLen != None:
|
if argTag == 'p' and argLen != None:
|
||||||
|
|
||||||
s += '\t{\n'
|
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\tOC_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 + ' + '
|
||||||
|
|
||||||
proc = argLen.get('proc')
|
proc = argLen.get('proc')
|
||||||
if proc != None:
|
if proc != None:
|
||||||
|
@ -245,7 +245,7 @@ def bindgen(apiName, spec, **kwargs):
|
||||||
s += ' res = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3Sig + '", ' + cname + '_stub);\n'
|
s += ' res = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3Sig + '", ' + cname + '_stub);\n'
|
||||||
s += ' if(res != m3Err_none && res != m3Err_functionLookupFailed)\n'
|
s += ' if(res != m3Err_none && res != m3Err_functionLookupFailed)\n'
|
||||||
s += ' {\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 += ' ret = -1;\n'
|
||||||
s += ' }\n\n'
|
s += ' }\n\n'
|
||||||
|
|
||||||
|
|
100
scripts/dev.py
100
scripts/dev.py
|
@ -1,4 +1,3 @@
|
||||||
import argparse
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
@ -20,9 +19,9 @@ ANGLE_VERSION = "2023-07-05"
|
||||||
|
|
||||||
def attach_dev_commands(subparsers):
|
def attach_dev_commands(subparsers):
|
||||||
dev_cmd = subparsers.add_parser("dev", help="Commands for building Orca itself. Must be run from the root of an Orca source checkout.")
|
dev_cmd = subparsers.add_parser("dev", help="Commands for building Orca itself. Must be run from the root of an Orca source checkout.")
|
||||||
dev_cmd.set_defaults(func=orca_root_only)
|
dev_cmd.set_defaults(func=orca_source_only)
|
||||||
|
|
||||||
dev_sub = dev_cmd.add_subparsers(required=is_orca_root(), title='commands')
|
dev_sub = dev_cmd.add_subparsers(required=is_orca_source(), title='commands')
|
||||||
|
|
||||||
build_cmd = dev_sub.add_parser("build-runtime", help="Build the Orca runtime from source.")
|
build_cmd = dev_sub.add_parser("build-runtime", help="Build the Orca runtime from source.")
|
||||||
build_cmd.add_argument("--release", action="store_true", help="compile Orca in release mode (default is debug)")
|
build_cmd.add_argument("--release", action="store_true", help="compile Orca in release mode (default is debug)")
|
||||||
|
@ -36,15 +35,39 @@ def attach_dev_commands(subparsers):
|
||||||
install_cmd.set_defaults(func=dev_shellish(install))
|
install_cmd.set_defaults(func=dev_shellish(install))
|
||||||
|
|
||||||
|
|
||||||
def is_orca_root():
|
# Checks if the Orca tool should use a source checkout of Orca instead of a system install.
|
||||||
|
# This is copy-pasted to the command-line tool so it can work before loading anything.
|
||||||
|
#
|
||||||
|
# Returns: (use source, source directory, is actually the source's tool)
|
||||||
|
def check_if_source():
|
||||||
|
def path_is_in_orca_source(path):
|
||||||
|
dir = path
|
||||||
|
while True:
|
||||||
try:
|
try:
|
||||||
os.stat(".orcaroot")
|
os.stat(os.path.join(dir, ".orcaroot"))
|
||||||
return True
|
return (True, dir)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return False
|
pass
|
||||||
|
|
||||||
|
newdir = os.path.dirname(dir)
|
||||||
|
if newdir == dir: # TODO: Verify on Windows (it will probably not work)
|
||||||
|
return (False, None)
|
||||||
|
dir = newdir
|
||||||
|
|
||||||
|
in_source, current_source_dir = path_is_in_orca_source(os.getcwd())
|
||||||
|
script_is_source, script_source_dir = path_is_in_orca_source(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
use_source = in_source or script_is_source
|
||||||
|
source_dir = current_source_dir or script_source_dir
|
||||||
|
return (use_source, source_dir, script_is_source)
|
||||||
|
|
||||||
|
|
||||||
def orca_root_only(args):
|
def is_orca_source():
|
||||||
|
use_source, _, _ = check_if_source()
|
||||||
|
return use_source
|
||||||
|
|
||||||
|
|
||||||
|
def orca_source_only(args):
|
||||||
print("The Orca dev commands can only be run from an Orca source checkout.")
|
print("The Orca dev commands can only be run from an Orca source checkout.")
|
||||||
print()
|
print()
|
||||||
print("If you want to build Orca yourself, download the source here:")
|
print("If you want to build Orca yourself, download the source here:")
|
||||||
|
@ -53,7 +76,14 @@ def orca_root_only(args):
|
||||||
|
|
||||||
|
|
||||||
def dev_shellish(func):
|
def dev_shellish(func):
|
||||||
return shellish(func) if is_orca_root() else orca_root_only
|
use_source, source_dir, _ = check_if_source()
|
||||||
|
if not use_source:
|
||||||
|
return orca_source_only
|
||||||
|
|
||||||
|
def func_from_source(args):
|
||||||
|
os.chdir(source_dir)
|
||||||
|
func(args)
|
||||||
|
return shellish(func_from_source)
|
||||||
|
|
||||||
|
|
||||||
def build_runtime(args):
|
def build_runtime(args):
|
||||||
|
@ -137,7 +167,7 @@ def build_platform_layer_lib_win(release):
|
||||||
subprocess.run([
|
subprocess.run([
|
||||||
"cl", "/nologo",
|
"cl", "/nologo",
|
||||||
"/we4013", "/Zi", "/Zc:preprocessor",
|
"/we4013", "/Zi", "/Zc:preprocessor",
|
||||||
"/DMP_BUILD_DLL",
|
"/DOC_BUILD_DLL",
|
||||||
"/std:c11", "/experimental:c11atomics",
|
"/std:c11", "/experimental:c11atomics",
|
||||||
*includes,
|
*includes,
|
||||||
"src/orca.c", "/Fo:build/bin/orca.o",
|
"src/orca.c", "/Fo:build/bin/orca.o",
|
||||||
|
@ -154,7 +184,7 @@ def build_platform_layer_lib_mac(release):
|
||||||
|
|
||||||
flags = ["-mmacos-version-min=10.15.4", "-maes"]
|
flags = ["-mmacos-version-min=10.15.4", "-maes"]
|
||||||
cflags = ["-std=c11"]
|
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/"]
|
ldflags = [f"-L{sdk_dir}/usr/lib", f"-F{sdk_dir}/System/Library/Frameworks/"]
|
||||||
includes = ["-Isrc", "-Isrc/util", "-Isrc/platform", "-Iext", "-Iext/angle/include"]
|
includes = ["-Isrc", "-Isrc/util", "-Isrc/platform", "-Iext", "-Iext/angle/include"]
|
||||||
|
|
||||||
|
@ -327,7 +357,7 @@ def build_orca_mac(release):
|
||||||
"-Iext/wasm3/source"
|
"-Iext/wasm3/source"
|
||||||
]
|
]
|
||||||
libs = ["-Lbuild/bin", "-Lbuild/lib", "-lorca", "-lwasm3"]
|
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 = [
|
flags = [
|
||||||
*debug_flags,
|
*debug_flags,
|
||||||
"-mmacos-version-min=10.15.4",
|
"-mmacos-version-min=10.15.4",
|
||||||
|
@ -485,6 +515,17 @@ def yeet(path):
|
||||||
shutil.rmtree(path)
|
shutil.rmtree(path)
|
||||||
|
|
||||||
|
|
||||||
|
def prompt(msg):
|
||||||
|
while True:
|
||||||
|
answer = input(f"{msg} (y/n)> ")
|
||||||
|
if answer.lower() in ["y", "yes"]:
|
||||||
|
return True
|
||||||
|
elif answer.lower() in ["n", "no"]:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("Please enter \"yes\" or \"no\" and press return.")
|
||||||
|
|
||||||
|
|
||||||
def install(args):
|
def install(args):
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
dest = os.path.join(os.getenv("LOCALAPPDATA"), "orca")
|
dest = os.path.join(os.getenv("LOCALAPPDATA"), "orca")
|
||||||
|
@ -495,31 +536,42 @@ def install(args):
|
||||||
print("The Orca command-line tools will be installed to:")
|
print("The Orca command-line tools will be installed to:")
|
||||||
print(dest)
|
print(dest)
|
||||||
print()
|
print()
|
||||||
while True:
|
if not prompt("Proceed with the installation?"):
|
||||||
answer = input("Proceed with the installation? (y/n) >")
|
|
||||||
if answer.lower() in ["y", "yes"]:
|
|
||||||
break
|
|
||||||
elif answer.lower() in ["n", "no"]:
|
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
print("Please enter \"yes\" or \"no\" and press return.")
|
|
||||||
|
|
||||||
bin_dir = os.path.join(dest, "bin")
|
bin_dir = os.path.join(dest, "bin")
|
||||||
yeet(bin_dir)
|
yeet(bin_dir)
|
||||||
|
|
||||||
|
# The MS Store version of Python does some really stupid stuff with AppData:
|
||||||
|
# https://git.handmade.network/hmn/orca/issues/32
|
||||||
|
#
|
||||||
|
# Any new files and folders created in AppData actually get created in a special
|
||||||
|
# folder specific to the Python version. However, if the files or folders already
|
||||||
|
# exist, the redirect does not happen. So, if we first use the shell to create the
|
||||||
|
# paths we need, the following scripts work regardless of Python install.
|
||||||
|
#
|
||||||
|
# Also apparently you can't just do mkdir in a subprocess call here, hence the
|
||||||
|
# trivial batch script.
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
subprocess.run(["scripts\\mkdir.bat", bin_dir], check=True)
|
||||||
|
|
||||||
shutil.copytree("scripts", os.path.join(bin_dir, "sys_scripts"))
|
shutil.copytree("scripts", os.path.join(bin_dir, "sys_scripts"))
|
||||||
shutil.copy("orca", bin_dir)
|
shutil.copy("orca", bin_dir)
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
shutil.copy("orca.bat", bin_dir)
|
shutil.copy("orca.bat", bin_dir)
|
||||||
|
|
||||||
# TODO: Customize these instructions for Windows
|
|
||||||
print()
|
print()
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
print("The Orca tools have been installed. Make sure the Orca tools are on your PATH by")
|
print("The Orca tools have been installed to the following directory:")
|
||||||
print("adding the following path to your system PATH variable:")
|
|
||||||
print()
|
|
||||||
print(bin_dir)
|
print(bin_dir)
|
||||||
print()
|
print()
|
||||||
print("You can do this in the Windows settings by searching for \"environment variables\".")
|
print("The tools will need to be on your PATH in order to actually use them.")
|
||||||
|
if prompt("Would you like to automatically add Orca to your PATH?"):
|
||||||
|
subprocess.run(["powershell", "scripts\\updatepath.ps1", bin_dir], check=True)
|
||||||
|
print("Orca has been added to your PATH. Restart any open terminals to use it.")
|
||||||
|
else:
|
||||||
|
print("No worries. You can manually add Orca to your PATH in the Windows settings")
|
||||||
|
print("this in the Windows settings by searching for \"environment variables\".")
|
||||||
else:
|
else:
|
||||||
print("The Orca tools have been installed. Make sure the Orca tools are on your PATH by")
|
print("The Orca tools have been installed. Make sure the Orca tools are on your PATH by")
|
||||||
print("adding the following to your shell config:")
|
print("adding the following to your shell config:")
|
||||||
|
|
|
@ -99,21 +99,21 @@ f.write('#include"GL/glcorearb.h"\n')
|
||||||
f.write('#include"GLES3/gl32.h"\n\n')
|
f.write('#include"GLES3/gl32.h"\n\n')
|
||||||
|
|
||||||
# generate interface struct
|
# 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')
|
f.write(' const char* name;\n')
|
||||||
|
|
||||||
for func in glall:
|
for func in glall:
|
||||||
f.write('\t' + 'PFN' + func.upper() + 'PROC ' + remove_prefix(func, 'gl') + ';\n')
|
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
|
# generate interface macros
|
||||||
# TODO guard for different api/versions and only #define functions present in desired version
|
# 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:
|
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)
|
emit_end_guard(f, apiName)
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -129,15 +129,15 @@ emit_begin_guard(f, loaderName)
|
||||||
|
|
||||||
f.write('#include"gl_api.h"\n\n')
|
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 oc_gl_load_gl41(oc_gl_api* api, oc_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 oc_gl_load_gl43(oc_gl_api* api, oc_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 oc_gl_load_gl44(oc_gl_api* api, oc_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 oc_gl_load_gles30(oc_gl_api* api, oc_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_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)
|
emit_end_guard(f, loaderName)
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -146,7 +146,7 @@ f.close()
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
|
|
||||||
def emit_loader(f, name, procs):
|
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("{\n")
|
||||||
f.write(' api->name = "'+ name +'";\n')
|
f.write(' api->name = "'+ name +'";\n')
|
||||||
|
|
||||||
|
@ -154,14 +154,14 @@ def emit_loader(f, name, procs):
|
||||||
if proc in procs:
|
if proc in procs:
|
||||||
f.write(' api->' + remove_prefix(proc, 'gl') + ' = loadProc("' + proc + '");\n')
|
f.write(' api->' + remove_prefix(proc, 'gl') + ' = loadProc("' + proc + '");\n')
|
||||||
else:
|
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")
|
f.write("}\n\n")
|
||||||
|
|
||||||
|
|
||||||
def emit_null_api(f, procs):
|
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:
|
for name in procs:
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ def emit_null_api(f, procs):
|
||||||
|
|
||||||
retType = retType.strip()
|
retType = retType.strip()
|
||||||
|
|
||||||
f.write(retType + ' mg_' + name + '_noimpl(')
|
f.write(retType + ' oc_' + name + '_noimpl(')
|
||||||
|
|
||||||
params = command.findall('param')
|
params = command.findall('param')
|
||||||
|
|
||||||
|
@ -217,21 +217,21 @@ def emit_null_api(f, procs):
|
||||||
|
|
||||||
f.write(')\n')
|
f.write(')\n')
|
||||||
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(' {\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(' }\n')
|
||||||
f.write(' else\n')
|
f.write(' else\n')
|
||||||
f.write(' {\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')
|
f.write(' }\n')
|
||||||
if retType != 'void':
|
if retType != 'void':
|
||||||
f.write(' return(('+ retType +')0);\n')
|
f.write(' return(('+ retType +')0);\n')
|
||||||
f.write('}\n')
|
f.write('}\n')
|
||||||
|
|
||||||
f.write('mg_gl_api __mgGLNoAPI = {\n')
|
f.write('oc_gl_api oc_glNoAPI = {\n')
|
||||||
for proc in procs:
|
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.write("};\n\n")
|
||||||
|
|
||||||
f = open(loaderCPath, 'w')
|
f = open(loaderCPath, 'w')
|
||||||
|
@ -241,7 +241,7 @@ emit_doc(f, loaderName, '.c')
|
||||||
f.write('#include"' + loaderName + '.h"\n')
|
f.write('#include"' + loaderName + '.h"\n')
|
||||||
f.write('#include"platform/platform.h"\n\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_null_api(f, glall)
|
||||||
emit_loader(f, 'gl41', gl41)
|
emit_loader(f, 'gl41', gl41)
|
||||||
|
@ -250,8 +250,8 @@ emit_loader(f, 'gl44', gl44)
|
||||||
emit_loader(f, 'gles31', gles31)
|
emit_loader(f, 'gles31', gles31)
|
||||||
emit_loader(f, 'gles32', gles32)
|
emit_loader(f, 'gles32', gles32)
|
||||||
|
|
||||||
f.write("void mg_gl_select_api(mg_gl_api* api){ __mgGLAPI = api; }\n")
|
f.write("void oc_gl_select_api(oc_gl_api* api){ oc_glAPI = api; }\n")
|
||||||
f.write("void mg_gl_deselect_api(){ __mgGLAPI = &__mgGLNoAPI; }\n")
|
f.write("void oc_gl_deselect_api(){ oc_glAPI = &oc_glNoAPI; }\n")
|
||||||
f.write("mg_gl_api* mg_gl_get_api(void) { return(__mgGLAPI); }\n\n")
|
f.write("oc_gl_api* oc_gl_get_api(void) { return(oc_glAPI); }\n\n")
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
|
@ -32,7 +32,7 @@ def gen_gles_header(spec, filename):
|
||||||
tree = et.parse(spec)
|
tree = et.parse(spec)
|
||||||
reg.loadElementTree(tree)
|
reg.loadElementTree(tree)
|
||||||
|
|
||||||
logFile = open('./gles_gen.log', 'w')
|
logFile = open('./build/gles_gen.log', 'w')
|
||||||
gen = COutputGenerator(diagFile=logFile)
|
gen = COutputGenerator(diagFile=logFile)
|
||||||
reg.setGenerator(gen)
|
reg.setGenerator(gen)
|
||||||
reg.apiGen(genOpts)
|
reg.apiGen(genOpts)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
@echo off
|
||||||
|
mkdir %1
|
||||||
|
exit /b %errorlevel%
|
|
@ -0,0 +1,11 @@
|
||||||
|
param (
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$orcaPath
|
||||||
|
)
|
||||||
|
|
||||||
|
$arrPath = [System.Environment]::GetEnvironmentVariable('PATH', 'User') -split ';'
|
||||||
|
$arrPath = $arrPath | Where-Object { $_ -ne $orcaPath } | Where-Object { $_ -ne '' }
|
||||||
|
$newPath = ($arrPath + $orcaPath) -join ';'
|
||||||
|
|
||||||
|
[System.Environment]::SetEnvironmentVariable('PATH', $newPath, 'User')
|
||||||
|
# echo $newPath
|
|
@ -6,7 +6,7 @@ SRCDIR=../../src
|
||||||
|
|
||||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_atlas main.c
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ EXTDIR=../../ext
|
||||||
|
|
||||||
INCLUDES="-I$SRCDIR -I$EXTDIR"
|
INCLUDES="-I$SRCDIR -I$EXTDIR"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_surface_sharing main.c
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ EXTDIR=../../ext
|
||||||
|
|
||||||
INCLUDES="-I$SRCDIR -I$EXTDIR"
|
INCLUDES="-I$SRCDIR -I$EXTDIR"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost -framework Foundation -framework Metal"
|
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 metal -c -o shader.air shader.metal
|
||||||
xcrun -sdk macosx metallib -o shader.metallib shader.air
|
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"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
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
|
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
|
* @author: Martin Fouilleul
|
||||||
* @date: 23/12/2022
|
* @date: 23/12/2022
|
||||||
* @revision:
|
* @revision:
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
#ifndef __MP_APP_INTERNAL_H_
|
#ifndef __APP_INTERNAL_H_
|
||||||
#define __MP_APP_INTERNAL_H_
|
#define __APP_INTERNAL_H_
|
||||||
|
|
||||||
#include"mp_app.h"
|
#include"app.h"
|
||||||
|
|
||||||
#include"platform/platform.h"
|
#include"platform/platform.h"
|
||||||
#include"util/ringbuffer.h"
|
#include"util/ringbuffer.h"
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if OC_PLATFORM_WINDOWS
|
||||||
#include"win32_app.h"
|
#include"win32_app.h"
|
||||||
#elif PLATFORM_MACOS
|
#elif OC_PLATFORM_MACOS
|
||||||
#include"osx_app.h"
|
#include"osx_app.h"
|
||||||
#else
|
#else
|
||||||
#error "platform not supported yet"
|
#error "platform not supported yet"
|
||||||
|
@ -26,66 +26,66 @@
|
||||||
// Window structure
|
// Window structure
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct mp_frame_stats
|
typedef struct oc_frame_stats
|
||||||
{
|
{
|
||||||
f64 start;
|
f64 start;
|
||||||
f64 workTime;
|
f64 workTime;
|
||||||
f64 remainingTime;
|
f64 remainingTime;
|
||||||
f64 targetFramePeriod;
|
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;
|
u32 generation;
|
||||||
|
|
||||||
mp_window_style style;
|
oc_window_style style;
|
||||||
|
|
||||||
bool shouldClose; //TODO could be in status flags
|
bool shouldClose; //TODO could be in status flags
|
||||||
bool hidden;
|
bool hidden;
|
||||||
bool minimized;
|
bool minimized;
|
||||||
|
|
||||||
MP_PLATFORM_WINDOW_DATA
|
OC_PLATFORM_WINDOW_DATA
|
||||||
} mp_window_data;
|
} oc_window_data;
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Global App State
|
// Global App State
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct mp_key_utf8
|
typedef struct oc_key_utf8
|
||||||
{
|
{
|
||||||
u8 labelLen;
|
u8 labelLen;
|
||||||
char label[8];
|
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 init;
|
||||||
bool shouldQuit;
|
bool shouldQuit;
|
||||||
bool minimized;
|
bool minimized;
|
||||||
|
|
||||||
str8 pendingPathDrop;
|
oc_str8 pendingPathDrop;
|
||||||
mem_arena eventArena;
|
oc_arena eventArena;
|
||||||
|
|
||||||
ringbuffer eventQueue;
|
oc_ringbuffer eventQueue;
|
||||||
|
|
||||||
mp_frame_stats frameStats;
|
oc_frame_stats frameStats;
|
||||||
|
|
||||||
mp_window_data windowPool[MP_APP_MAX_WINDOWS];
|
oc_window_data windowPool[OC_APP_MAX_WINDOWS];
|
||||||
list_info windowFreeList;
|
oc_list windowFreeList;
|
||||||
|
|
||||||
mp_live_resize_callback liveResizeCallback;
|
oc_live_resize_callback liveResizeCallback;
|
||||||
void* liveResizeData;
|
void* liveResizeData;
|
||||||
|
|
||||||
mp_key_utf8 keyLabels[512];
|
oc_key_utf8 keyLabels[512];
|
||||||
int keyCodes[512];
|
int keyCodes[512];
|
||||||
int nativeKeys[MP_KEY_COUNT];
|
int nativeKeys[OC_KEY_COUNT];
|
||||||
|
|
||||||
MP_PLATFORM_APP_DATA
|
OC_PLATFORM_APP_DATA
|
||||||
} mp_app;
|
} 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"
|
#include"orca.h"
|
||||||
|
|
||||||
//This is used to pass raw events from the runtime
|
//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_
|
#ifndef __OSX_APP_H_
|
||||||
#define __OSX_APP_H_
|
#define __OSX_APP_H_
|
||||||
|
|
||||||
#include"mp_app.h"
|
#include"app.h"
|
||||||
#include"graphics/graphics.h"
|
#include"graphics/graphics.h"
|
||||||
|
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
|
@ -26,19 +26,19 @@
|
||||||
|
|
||||||
#include<Carbon/Carbon.h>
|
#include<Carbon/Carbon.h>
|
||||||
|
|
||||||
typedef struct osx_window_data
|
typedef struct oc_osx_window_data
|
||||||
{
|
{
|
||||||
NSWindow* nsWindow;
|
NSWindow* nsWindow;
|
||||||
NSView* nsView;
|
NSView* nsView;
|
||||||
NSObject* nsWindowDelegate;
|
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;
|
NSTimer* frameTimer;
|
||||||
NSCursor* cursor;
|
NSCursor* cursor;
|
||||||
|
@ -47,9 +47,9 @@ typedef struct osx_app_data
|
||||||
void* kbLayoutUnicodeData;
|
void* kbLayoutUnicodeData;
|
||||||
id kbLayoutListener;
|
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
|
// Surface layer
|
||||||
|
@ -76,11 +76,11 @@ typedef struct osx_app_data
|
||||||
@end
|
@end
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct mp_layer
|
typedef struct oc_layer
|
||||||
{
|
{
|
||||||
CALayer* caLayer;
|
CALayer* caLayer;
|
||||||
CAContext* caContext;
|
CAContext* caContext;
|
||||||
} mp_layer;
|
} oc_layer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1125
src/app/osx_app.m
1125
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_
|
#ifndef __WIN32_APP_H_
|
||||||
#define __WIN32_APP_H_
|
#define __WIN32_APP_H_
|
||||||
|
|
||||||
#include"mp_app.h"
|
#include"app.h"
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#include<windows.h>
|
#include<windows.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct win32_window_data
|
typedef struct oc_win32_window_data
|
||||||
{
|
{
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
list_info layers;
|
oc_list layers;
|
||||||
} win32_window_data;
|
} oc_win32_window_data;
|
||||||
|
|
||||||
typedef struct mp_window_data mp_window_data;
|
typedef struct oc_window_data oc_window_data;
|
||||||
typedef struct mp_layer
|
typedef struct oc_layer
|
||||||
{
|
{
|
||||||
mp_window_data* parent;
|
oc_window_data* parent;
|
||||||
list_elt listElt;
|
oc_list_elt listElt;
|
||||||
HWND hWnd;
|
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;
|
u32 savedConsoleCodePage;
|
||||||
|
|
||||||
int mouseCaptureMask;
|
int mouseCaptureMask;
|
||||||
bool mouseTracked;
|
bool mouseTracked;
|
||||||
vec2 lastMousePos;
|
oc_vec2 lastMousePos;
|
||||||
u32 wheelScrollLines;
|
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_
|
#endif __WIN32_APP_H_
|
||||||
|
|
|
@ -10,47 +10,47 @@
|
||||||
#define EGL_EGLEXT_PROTOTYPES
|
#define EGL_EGLEXT_PROTOTYPES
|
||||||
#include<EGL/egl.h>
|
#include<EGL/egl.h>
|
||||||
#include<EGL/eglext.h>
|
#include<EGL/eglext.h>
|
||||||
#include"app/mp_app_internal.h"
|
#include"app/app_internal.h"
|
||||||
#include"graphics_surface.h"
|
#include"graphics_surface.h"
|
||||||
#include"gl_loader.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
|
//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
|
//NOTE: hardcode GLES versions for now
|
||||||
//TODO: use version hints, once we have all api versions correctly categorized by glapi.py
|
//TODO: use version hints, once we have all api versions correctly categorized by glapi.py
|
||||||
#define MG_GLES_VERSION_MAJOR 3
|
#define OC_GLES_VERSION_MAJOR 3
|
||||||
#define MG_GLES_VERSION_MINOR 0
|
#define OC_GLES_VERSION_MINOR 0
|
||||||
#define mg_gl_load_gles mg_gl_load_gles31
|
#define oc_gl_load_gles oc_gl_load_gles31
|
||||||
#else
|
#else
|
||||||
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
#define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
||||||
#define MG_GLES_VERSION_MAJOR 3
|
#define OC_GLES_VERSION_MAJOR 3
|
||||||
#define MG_GLES_VERSION_MINOR 1
|
#define OC_GLES_VERSION_MINOR 1
|
||||||
#define mg_gl_load_gles mg_gl_load_gles32
|
#define oc_gl_load_gles oc_gl_load_gles32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct mg_egl_surface
|
typedef struct oc_egl_surface
|
||||||
{
|
{
|
||||||
mg_surface_data interface;
|
oc_surface_data interface;
|
||||||
|
|
||||||
EGLDisplay eglDisplay;
|
EGLDisplay eglDisplay;
|
||||||
EGLConfig eglConfig;
|
EGLConfig eglConfig;
|
||||||
EGLContext eglContext;
|
EGLContext eglContext;
|
||||||
EGLSurface eglSurface;
|
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)
|
if(eglGetCurrentContext() == surface->eglContext)
|
||||||
{
|
{
|
||||||
|
@ -59,50 +59,50 @@ void mg_egl_surface_destroy(mg_surface_data* interface)
|
||||||
eglDestroyContext(surface->eglDisplay, surface->eglContext);
|
eglDestroyContext(surface->eglDisplay, surface->eglContext);
|
||||||
eglDestroySurface(surface->eglDisplay, surface->eglSurface);
|
eglDestroySurface(surface->eglDisplay, surface->eglSurface);
|
||||||
|
|
||||||
mg_surface_cleanup((mg_surface_data*)surface);
|
oc_surface_cleanup((oc_surface_data*)surface);
|
||||||
free(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);
|
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);
|
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);
|
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);
|
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.destroy = oc_egl_surface_destroy;
|
||||||
surface->interface.prepare = mg_egl_surface_prepare;
|
surface->interface.prepare = oc_egl_surface_prepare;
|
||||||
surface->interface.present = mg_egl_surface_present;
|
surface->interface.present = oc_egl_surface_present;
|
||||||
surface->interface.deselect = mg_egl_surface_deselect;
|
surface->interface.deselect = oc_egl_surface_deselect;
|
||||||
surface->interface.swapInterval = mg_egl_surface_swap_interval;
|
surface->interface.swapInterval = oc_egl_surface_swap_interval;
|
||||||
|
|
||||||
EGLAttrib displayAttribs[] = {
|
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_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
|
||||||
EGL_NONE};
|
EGL_NONE};
|
||||||
|
|
||||||
|
@ -133,8 +133,8 @@ void mg_egl_surface_init(mg_egl_surface* surface)
|
||||||
|
|
||||||
eglBindAPI(EGL_OPENGL_ES_API);
|
eglBindAPI(EGL_OPENGL_ES_API);
|
||||||
EGLint contextAttributes[] = {
|
EGLint contextAttributes[] = {
|
||||||
EGL_CONTEXT_MAJOR_VERSION_KHR, MG_GLES_VERSION_MAJOR,
|
EGL_CONTEXT_MAJOR_VERSION_KHR, OC_GLES_VERSION_MAJOR,
|
||||||
EGL_CONTEXT_MINOR_VERSION_KHR, MG_GLES_VERSION_MINOR,
|
EGL_CONTEXT_MINOR_VERSION_KHR, OC_GLES_VERSION_MINOR,
|
||||||
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE,
|
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE,
|
||||||
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE,
|
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE,
|
||||||
EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE,
|
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);
|
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
|
||||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
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);
|
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)
|
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);
|
oc_surface_init_remote((oc_surface_data*)surface, width, height);
|
||||||
mg_egl_surface_init(surface);
|
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;
|
oc_egl_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)
|
if(windowData)
|
||||||
{
|
{
|
||||||
surface = malloc_type(mg_egl_surface);
|
surface = oc_malloc_type(oc_egl_surface);
|
||||||
if(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);
|
oc_surface_init_for_window((oc_surface_data*)surface, windowData);
|
||||||
mg_egl_surface_init(surface);
|
oc_egl_surface_init(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return((mg_surface_data*)surface);
|
return((oc_surface_data*)surface);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
#define __EGL_SURFACE_H_
|
#define __EGL_SURFACE_H_
|
||||||
|
|
||||||
#include"graphics_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);
|
oc_surface_data* oc_egl_surface_create_for_window(oc_window window);
|
||||||
mg_surface_data* mg_egl_surface_create_remote(u32 width, u32 height);
|
oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height);
|
||||||
|
|
||||||
#endif // __EGL_SURFACE_H_
|
#endif // __EGL_SURFACE_H_
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
15432
src/graphics/gl_loader.c
15432
src/graphics/gl_loader.c
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* @file: gl_loader.h
|
* @file: gl_loader.h
|
||||||
* @note: auto-generated by glapi.py from gl.xml
|
* @note: auto-generated by glapi.py from gl.xml
|
||||||
* @date: 11/082023
|
* @date: 15/082023
|
||||||
*
|
*
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
#ifndef __GL_LOADER_H__
|
#ifndef __GL_LOADER_H__
|
||||||
|
@ -10,14 +10,14 @@
|
||||||
|
|
||||||
#include"gl_api.h"
|
#include"gl_api.h"
|
||||||
|
|
||||||
typedef void*(*mg_gl_load_proc)(const char* name);
|
typedef void*(*oc_gl_load_proc)(const char* name);
|
||||||
|
|
||||||
void mg_gl_load_gl41(mg_gl_api* api, mg_gl_load_proc loadProc);
|
void oc_gl_load_gl41(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||||
void mg_gl_load_gl43(mg_gl_api* api, mg_gl_load_proc loadProc);
|
void oc_gl_load_gl43(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||||
void mg_gl_load_gl44(mg_gl_api* api, mg_gl_load_proc loadProc);
|
void oc_gl_load_gl44(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||||
void mg_gl_load_gles30(mg_gl_api* api, mg_gl_load_proc loadProc);
|
void oc_gl_load_gles30(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||||
void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);
|
void oc_gl_load_gles31(oc_gl_api* api, oc_gl_load_proc loadProc);
|
||||||
|
|
||||||
void mg_gl_select_api(mg_gl_api* api);
|
void oc_gl_select_api(oc_gl_api* api);
|
||||||
|
|
||||||
#endif // __GL_LOADER_H__
|
#endif // __GL_LOADER_H__
|
||||||
|
|
|
@ -6,12 +6,12 @@ layout(std430) buffer;
|
||||||
|
|
||||||
layout(binding = 0) restrict readonly buffer pathQueueBufferSSBO
|
layout(binding = 0) restrict readonly buffer pathQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path_queue elements[];
|
oc_gl_path_queue elements[];
|
||||||
} pathQueueBuffer;
|
} pathQueueBuffer;
|
||||||
|
|
||||||
layout(binding = 1) restrict buffer tileQueueBufferSSBO
|
layout(binding = 1) restrict buffer tileQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_tile_queue elements[];
|
oc_gl_tile_queue elements[];
|
||||||
} tileQueueBuffer;
|
} tileQueueBuffer;
|
||||||
|
|
||||||
layout(location = 0) uniform int pathQueueBufferStart;
|
layout(location = 0) uniform int pathQueueBufferStart;
|
||||||
|
@ -30,7 +30,7 @@ void main()
|
||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
int rowIndex = 0;
|
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 tileQueueBase = pathQueue.tileQueues;
|
||||||
int rowSize = pathQueue.area.z;
|
int rowSize = pathQueue.area.z;
|
||||||
int rowCount = pathQueue.area.w;
|
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
|
layout(binding = 1) coherent restrict writeonly buffer dispatchBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_dispatch_indirect_command elements[];
|
oc_gl_dispatch_indirect_command elements[];
|
||||||
} dispatchBuffer;
|
} dispatchBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,32 +2,32 @@
|
||||||
layout(std430) buffer;
|
layout(std430) buffer;
|
||||||
|
|
||||||
// command
|
// command
|
||||||
#define MG_GL_FILL 0
|
#define OC_GL_FILL 0
|
||||||
#define MG_GL_STROKE 1
|
#define OC_GL_STROKE 1
|
||||||
|
|
||||||
// element kind
|
// element kind
|
||||||
#define MG_GL_LINE 1
|
#define OC_GL_LINE 1
|
||||||
#define MG_GL_QUADRATIC 2
|
#define OC_GL_QUADRATIC 2
|
||||||
#define MG_GL_CUBIC 3
|
#define OC_GL_CUBIC 3
|
||||||
|
|
||||||
// curve config
|
// curve config
|
||||||
#define MG_GL_BL 1 /* curve on bottom left */
|
#define OC_GL_BL 1 /* curve on bottom left */
|
||||||
#define MG_GL_BR 2 /* curve on bottom right */
|
#define OC_GL_BR 2 /* curve on bottom right */
|
||||||
#define MG_GL_TL 3 /* curve on top left */
|
#define OC_GL_TL 3 /* curve on top left */
|
||||||
#define MG_GL_TR 4 /* curve on top right */
|
#define OC_GL_TR 4 /* curve on top right */
|
||||||
|
|
||||||
// Operations
|
// Operations
|
||||||
#define MG_GL_OP_FILL 0
|
#define OC_GL_OP_FILL 0
|
||||||
#define MG_GL_OP_CLIP_FILL 1
|
#define OC_GL_OP_CLIP_FILL 1
|
||||||
#define MG_GL_OP_START 2
|
#define OC_GL_OP_START 2
|
||||||
#define MG_GL_OP_END 3
|
#define OC_GL_OP_END 3
|
||||||
#define MG_GL_OP_SEGMENT 4
|
#define OC_GL_OP_SEGMENT 4
|
||||||
|
|
||||||
// MSAA
|
// MSAA
|
||||||
#define MG_GL_MAX_SAMPLE_COUNT 8
|
#define OC_GL_MAX_SAMPLE_COUNT 8
|
||||||
#define MG_GL_MAX_SRC_SAMPLE_COUNT 4
|
#define OC_GL_MAX_SRC_SAMPLE_COUNT 4
|
||||||
|
|
||||||
struct mg_gl_path
|
struct oc_gl_path
|
||||||
{
|
{
|
||||||
mat3 uvTransform;
|
mat3 uvTransform;
|
||||||
vec4 color;
|
vec4 color;
|
||||||
|
@ -37,14 +37,14 @@ struct mg_gl_path
|
||||||
int textureID;
|
int textureID;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_path_elt
|
struct oc_gl_path_elt
|
||||||
{
|
{
|
||||||
vec2 p[4];
|
vec2 p[4];
|
||||||
int pathIndex;
|
int pathIndex;
|
||||||
int kind;
|
int kind;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_segment
|
struct oc_gl_segment
|
||||||
{
|
{
|
||||||
int kind;
|
int kind;
|
||||||
int pathIndex;
|
int pathIndex;
|
||||||
|
@ -56,13 +56,13 @@ struct mg_gl_segment
|
||||||
float sign;
|
float sign;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_path_queue
|
struct oc_gl_path_queue
|
||||||
{
|
{
|
||||||
ivec4 area;
|
ivec4 area;
|
||||||
int tileQueues;
|
int tileQueues;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_tile_op
|
struct oc_gl_tile_op
|
||||||
{
|
{
|
||||||
int kind;
|
int kind;
|
||||||
int next;
|
int next;
|
||||||
|
@ -70,20 +70,20 @@ struct mg_gl_tile_op
|
||||||
int windingOffsetOrCrossRight;
|
int windingOffsetOrCrossRight;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_tile_queue
|
struct oc_gl_tile_queue
|
||||||
{
|
{
|
||||||
int windingOffset;
|
int windingOffset;
|
||||||
int first;
|
int first;
|
||||||
int last;
|
int last;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_screen_tile
|
struct oc_gl_screen_tile
|
||||||
{
|
{
|
||||||
uvec2 tileCoord;
|
uvec2 tileCoord;
|
||||||
int first;
|
int first;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_gl_dispatch_indirect_command
|
struct oc_gl_dispatch_indirect_command
|
||||||
{
|
{
|
||||||
uint num_groups_x;
|
uint num_groups_x;
|
||||||
uint num_groups_y;
|
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));
|
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;
|
int side = 0;
|
||||||
if(p.y > seg.box.w || p.y <= seg.box.y)
|
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)
|
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
|
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;
|
vec2 a, b, c;
|
||||||
switch(seg.config)
|
switch(seg.config)
|
||||||
{
|
{
|
||||||
case MG_GL_TL:
|
case OC_GL_TL:
|
||||||
a = seg.box.xy;
|
a = seg.box.xy;
|
||||||
b = seg.box.zw;
|
b = seg.box.zw;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_GL_BR:
|
case OC_GL_BR:
|
||||||
a = seg.box.zw;
|
a = seg.box.zw;
|
||||||
b = seg.box.xy;
|
b = seg.box.xy;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_GL_TR:
|
case OC_GL_TR:
|
||||||
a = seg.box.xw;
|
a = seg.box.xw;
|
||||||
b = seg.box.zy;
|
b = seg.box.zy;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_GL_BL:
|
case OC_GL_BL:
|
||||||
a = seg.box.zy;
|
a = seg.box.zy;
|
||||||
b = seg.box.xw;
|
b = seg.box.xw;
|
||||||
break;
|
break;
|
||||||
|
@ -150,30 +150,30 @@ int side_of_segment(vec2 p, mg_gl_segment seg)
|
||||||
if(ccw(a, b, p) < 0)
|
if(ccw(a, b, p) < 0)
|
||||||
{
|
{
|
||||||
// other side of the diagonal
|
// 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)
|
else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0)
|
||||||
{
|
{
|
||||||
// same side of the diagonal, but outside curve hull
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// inside curve hull
|
// inside curve hull
|
||||||
switch(seg.kind)
|
switch(seg.kind)
|
||||||
{
|
{
|
||||||
case MG_GL_LINE:
|
case OC_GL_LINE:
|
||||||
side = 1;
|
side = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_GL_QUADRATIC:
|
case OC_GL_QUADRATIC:
|
||||||
{
|
{
|
||||||
vec3 ph = {p.x, p.y, 1};
|
vec3 ph = {p.x, p.y, 1};
|
||||||
vec3 klm = seg.implicitMatrix * ph;
|
vec3 klm = seg.implicitMatrix * ph;
|
||||||
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
|
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MG_GL_CUBIC:
|
case OC_GL_CUBIC:
|
||||||
{
|
{
|
||||||
vec3 ph = {p.x, p.y, 1};
|
vec3 ph = {p.x, p.y, 1};
|
||||||
vec3 klm = seg.implicitMatrix * ph;
|
vec3 klm = seg.implicitMatrix * ph;
|
||||||
|
|
|
@ -6,17 +6,17 @@ layout(std430) buffer;
|
||||||
|
|
||||||
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path elements[];
|
oc_gl_path elements[];
|
||||||
} pathBuffer;
|
} pathBuffer;
|
||||||
|
|
||||||
layout(binding = 1) restrict readonly buffer pathQueueBufferSSBO
|
layout(binding = 1) restrict readonly buffer pathQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path_queue elements[];
|
oc_gl_path_queue elements[];
|
||||||
} pathQueueBuffer;
|
} pathQueueBuffer;
|
||||||
|
|
||||||
layout(binding = 2) restrict readonly buffer tileQueueBufferSSBO
|
layout(binding = 2) restrict readonly buffer tileQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_tile_queue elements[];
|
oc_gl_tile_queue elements[];
|
||||||
} tileQueueBuffer;
|
} tileQueueBuffer;
|
||||||
|
|
||||||
layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO
|
layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO
|
||||||
|
@ -26,12 +26,12 @@ layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO
|
||||||
|
|
||||||
layout(binding = 4) restrict buffer tileOpBufferSSBO
|
layout(binding = 4) restrict buffer tileOpBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_tile_op elements[];
|
oc_gl_tile_op elements[];
|
||||||
} tileOpBuffer;
|
} tileOpBuffer;
|
||||||
|
|
||||||
layout(binding = 5) restrict writeonly buffer screenTilesBufferSSBO
|
layout(binding = 5) restrict writeonly buffer screenTilesBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_screen_tile elements[];
|
oc_gl_screen_tile elements[];
|
||||||
} screenTilesBuffer;
|
} screenTilesBuffer;
|
||||||
|
|
||||||
layout(binding = 6) coherent restrict buffer screenTilesCountBufferSSBO
|
layout(binding = 6) coherent restrict buffer screenTilesCountBufferSSBO
|
||||||
|
@ -54,7 +54,7 @@ void main()
|
||||||
|
|
||||||
for(int pathIndex = 0; pathIndex < pathCount; pathIndex++)
|
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;
|
ivec2 pathTileCoord = tileCoord - pathQueue.area.xy;
|
||||||
|
|
||||||
vec4 pathBox = pathBuffer.elements[pathBufferStart + pathIndex].box;
|
vec4 pathBox = pathBuffer.elements[pathBufferStart + pathIndex].box;
|
||||||
|
@ -77,7 +77,7 @@ void main()
|
||||||
}
|
}
|
||||||
|
|
||||||
int pathTileIndex = pathQueue.tileQueues + pathTileCoord.y * pathQueue.area.z + pathTileCoord.x;
|
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 windingOffset = tileQueue.windingOffset;
|
||||||
int firstOpIndex = tileQueue.first;
|
int firstOpIndex = tileQueue.first;
|
||||||
|
@ -107,7 +107,7 @@ void main()
|
||||||
return;
|
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].next = -1;
|
||||||
tileOpBuffer.elements[pathOpIndex].index = pathIndex;
|
tileOpBuffer.elements[pathOpIndex].index = pathIndex;
|
||||||
tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
|
tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||||
|
@ -126,7 +126,7 @@ void main()
|
||||||
&& tileBox.y >= clip.y
|
&& tileBox.y >= clip.y
|
||||||
&& tileBox.w < clip.w)
|
&& 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
|
if( pathBuffer.elements[pathBufferStart + pathIndex].color.a == 1
|
||||||
&& pathBuffer.elements[pathBufferStart + pathIndex].textureID < 0)
|
&& pathBuffer.elements[pathBufferStart + pathIndex].textureID < 0)
|
||||||
|
@ -147,7 +147,7 @@ void main()
|
||||||
return;
|
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].next = -1;
|
||||||
tileOpBuffer.elements[startOpIndex].index = pathIndex;
|
tileOpBuffer.elements[startOpIndex].index = pathIndex;
|
||||||
tileOpBuffer.elements[startOpIndex].windingOffsetOrCrossRight = windingOffset;
|
tileOpBuffer.elements[startOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||||
|
@ -173,7 +173,7 @@ void main()
|
||||||
return;
|
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].next = -1;
|
||||||
tileOpBuffer.elements[endOpIndex].index = pathIndex;
|
tileOpBuffer.elements[endOpIndex].index = pathIndex;
|
||||||
tileOpBuffer.elements[endOpIndex].windingOffsetOrCrossRight = windingOffset;
|
tileOpBuffer.elements[endOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||||
|
|
|
@ -6,12 +6,12 @@ layout(std430) buffer;
|
||||||
|
|
||||||
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path elements[];
|
oc_gl_path elements[];
|
||||||
} pathBuffer;
|
} pathBuffer;
|
||||||
|
|
||||||
layout(binding = 1) restrict writeonly buffer pathQueueBufferSSBO
|
layout(binding = 1) restrict writeonly buffer pathQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path_queue elements[];
|
oc_gl_path_queue elements[];
|
||||||
} pathQueueBuffer;
|
} pathQueueBuffer;
|
||||||
|
|
||||||
layout(binding = 2) coherent restrict buffer tileQueueCountBufferSSBO
|
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
|
layout(binding = 3) restrict writeonly buffer tileQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_tile_queue elements[];
|
oc_gl_tile_queue elements[];
|
||||||
} tileQueueBuffer;
|
} tileQueueBuffer;
|
||||||
|
|
||||||
layout(location = 0) uniform int tileSize;
|
layout(location = 0) uniform int tileSize;
|
||||||
|
@ -32,7 +32,7 @@ layout(location = 3) uniform int pathQueueBufferStart;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
uint pathIndex = gl_WorkGroupID.x;
|
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
|
//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.
|
// the prefix sum of winding increments in the backprop pass.
|
||||||
|
|
|
@ -6,22 +6,22 @@ layout(std430) buffer;
|
||||||
|
|
||||||
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
layout(binding = 0) restrict readonly buffer pathBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path elements[];
|
oc_gl_path elements[];
|
||||||
} pathBuffer;
|
} pathBuffer;
|
||||||
|
|
||||||
layout(binding = 1) restrict readonly buffer segmentBufferSSBO
|
layout(binding = 1) restrict readonly buffer segmentBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_segment elements[];
|
oc_gl_segment elements[];
|
||||||
} segmentBuffer;
|
} segmentBuffer;
|
||||||
|
|
||||||
layout(binding = 2) restrict readonly buffer tileOpBufferSSBO
|
layout(binding = 2) restrict readonly buffer tileOpBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_tile_op elements[];
|
oc_gl_tile_op elements[];
|
||||||
} tileOpBuffer;
|
} tileOpBuffer;
|
||||||
|
|
||||||
layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO
|
layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_screen_tile elements[];
|
oc_gl_screen_tile elements[];
|
||||||
} screenTilesBuffer;
|
} screenTilesBuffer;
|
||||||
|
|
||||||
layout(binding = 4) restrict readonly buffer screenTilesCountBufferSSBO
|
layout(binding = 4) restrict readonly buffer screenTilesCountBufferSSBO
|
||||||
|
@ -67,7 +67,7 @@ void main()
|
||||||
return;
|
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(-1, -3)/16,
|
centerCoord + vec2(-1, -3)/16,
|
||||||
centerCoord + vec2(5, -1)/16,
|
centerCoord + vec2(5, -1)/16,
|
||||||
|
@ -87,14 +87,14 @@ void main()
|
||||||
|
|
||||||
const int srcSampleCount = 2;
|
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),
|
||||||
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);
|
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++)
|
for(int i=0; i<sampleCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -106,19 +106,19 @@ void main()
|
||||||
|
|
||||||
while(opIndex >= 0)
|
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++)
|
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++)
|
||||||
{
|
{
|
||||||
winding[sampleIndex] = op.windingOffsetOrCrossRight;
|
winding[sampleIndex] = op.windingOffsetOrCrossRight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(op.kind == MG_GL_OP_SEGMENT)
|
else if(op.kind == OC_GL_OP_SEGMENT)
|
||||||
{
|
{
|
||||||
int segIndex = op.index;
|
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++)
|
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++)
|
||||||
{
|
{
|
||||||
|
@ -133,12 +133,12 @@ void main()
|
||||||
|
|
||||||
if(op.windingOffsetOrCrossRight != 0)
|
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))
|
&&(sampleCoord.y > seg.box.w))
|
||||||
{
|
{
|
||||||
winding[sampleIndex] += seg.windingIncrement;
|
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))
|
&&(sampleCoord.y > seg.box.y))
|
||||||
{
|
{
|
||||||
winding[sampleIndex] -= seg.windingIncrement;
|
winding[sampleIndex] -= seg.windingIncrement;
|
||||||
|
@ -202,7 +202,7 @@ void main()
|
||||||
nextColor *= texColor;
|
nextColor *= texColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(op.kind == MG_GL_OP_FILL)
|
if(op.kind == OC_GL_OP_FILL)
|
||||||
{
|
{
|
||||||
color = color*(1-nextColor.a) + nextColor;
|
color = color*(1-nextColor.a) + nextColor;
|
||||||
}
|
}
|
||||||
|
@ -220,10 +220,10 @@ void main()
|
||||||
&& sampleCoord.y >= clip.y
|
&& sampleCoord.y >= clip.y
|
||||||
&& sampleCoord.y < clip.w)
|
&& sampleCoord.y < clip.w)
|
||||||
{
|
{
|
||||||
bool filled = op.kind == MG_GL_OP_CLIP_FILL
|
bool filled = op.kind == OC_GL_OP_CLIP_FILL
|
||||||
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == MG_GL_FILL
|
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_FILL
|
||||||
&& ((winding[sampleIndex] & 1) != 0))
|
&& ((winding[sampleIndex] & 1) != 0))
|
||||||
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == MG_GL_STROKE
|
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_STROKE
|
||||||
&& (winding[sampleIndex] != 0));
|
&& (winding[sampleIndex] != 0));
|
||||||
if(filled)
|
if(filled)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@ layout(std430) buffer;
|
||||||
|
|
||||||
layout(binding = 0) restrict readonly buffer elementBufferSSBO
|
layout(binding = 0) restrict readonly buffer elementBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path_elt elements[];
|
oc_gl_path_elt elements[];
|
||||||
} elementBuffer;
|
} elementBuffer;
|
||||||
|
|
||||||
layout(binding = 1) coherent restrict buffer segmentCountBufferSSBO
|
layout(binding = 1) coherent restrict buffer segmentCountBufferSSBO
|
||||||
|
@ -16,17 +16,17 @@ layout(binding = 1) coherent restrict buffer segmentCountBufferSSBO
|
||||||
|
|
||||||
layout(binding = 2) restrict buffer segmentBufferSSBO
|
layout(binding = 2) restrict buffer segmentBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_segment elements[];
|
oc_gl_segment elements[];
|
||||||
} segmentBuffer;
|
} segmentBuffer;
|
||||||
|
|
||||||
layout(binding = 3) restrict buffer pathQueueBufferSSBO
|
layout(binding = 3) restrict buffer pathQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_path_queue elements[];
|
oc_gl_path_queue elements[];
|
||||||
} pathQueueBuffer;
|
} pathQueueBuffer;
|
||||||
|
|
||||||
layout(binding = 4) coherent restrict buffer tileQueueBufferSSBO
|
layout(binding = 4) coherent restrict buffer tileQueueBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_tile_queue elements[];
|
oc_gl_tile_queue elements[];
|
||||||
} tileQueueBuffer;
|
} tileQueueBuffer;
|
||||||
|
|
||||||
layout(binding = 5) coherent restrict buffer tileOpCountBufferSSBO
|
layout(binding = 5) coherent restrict buffer tileOpCountBufferSSBO
|
||||||
|
@ -36,7 +36,7 @@ layout(binding = 5) coherent restrict buffer tileOpCountBufferSSBO
|
||||||
|
|
||||||
layout(binding = 6) restrict buffer tileOpBufferSSBO
|
layout(binding = 6) restrict buffer tileOpBufferSSBO
|
||||||
{
|
{
|
||||||
mg_gl_tile_op elements[];
|
oc_gl_tile_op elements[];
|
||||||
} tileOpBuffer;
|
} tileOpBuffer;
|
||||||
|
|
||||||
layout(location = 0) uniform float scale;
|
layout(location = 0) uniform float scale;
|
||||||
|
@ -46,8 +46,8 @@ layout(location = 2) uniform int elementBufferStart;
|
||||||
void bin_to_tiles(int segIndex)
|
void bin_to_tiles(int segIndex)
|
||||||
{
|
{
|
||||||
//NOTE: add segment index to the queues of tiles it overlaps with
|
//NOTE: add segment index to the queues of tiles it overlaps with
|
||||||
const mg_gl_segment seg = segmentBuffer.elements[segIndex];
|
const oc_gl_segment seg = segmentBuffer.elements[segIndex];
|
||||||
const mg_gl_path_queue pathQueue = pathQueueBuffer.elements[seg.pathIndex];
|
const oc_gl_path_queue pathQueue = pathQueueBuffer.elements[seg.pathIndex];
|
||||||
|
|
||||||
ivec4 pathArea = pathQueue.area;
|
ivec4 pathArea = pathQueue.area;
|
||||||
ivec4 coveredTiles = ivec4(seg.box)/int(tileSize);
|
ivec4 coveredTiles = ivec4(seg.box)/int(tileSize);
|
||||||
|
@ -81,7 +81,7 @@ void bin_to_tiles(int segIndex)
|
||||||
bool crossB = (sbl*sbr < 0);
|
bool crossB = (sbl*sbr < 0);
|
||||||
|
|
||||||
vec2 s0, s1;
|
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;
|
s0 = seg.box.xy;
|
||||||
s1 = seg.box.zw;
|
s1 = seg.box.zw;
|
||||||
|
@ -107,7 +107,7 @@ void bin_to_tiles(int segIndex)
|
||||||
|
|
||||||
if(tileOpIndex < tileOpBuffer.elements.length())
|
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].index = segIndex;
|
||||||
tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 0;
|
tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 0;
|
||||||
tileOpBuffer.elements[tileOpIndex].next = -1;
|
tileOpBuffer.elements[tileOpIndex].next = -1;
|
||||||
|
@ -148,19 +148,19 @@ int push_segment(in vec2 p[4], int kind, int pathIndex)
|
||||||
|
|
||||||
switch(kind)
|
switch(kind)
|
||||||
{
|
{
|
||||||
case MG_GL_LINE:
|
case OC_GL_LINE:
|
||||||
s = p[0];
|
s = p[0];
|
||||||
c = p[0];
|
c = p[0];
|
||||||
e = p[1];
|
e = p[1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_GL_QUADRATIC:
|
case OC_GL_QUADRATIC:
|
||||||
s = p[0];
|
s = p[0];
|
||||||
c = p[1];
|
c = p[1];
|
||||||
e = p[2];
|
e = p[2];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_GL_CUBIC:
|
case OC_GL_CUBIC:
|
||||||
{
|
{
|
||||||
s = p[0];
|
s = p[0];
|
||||||
float sqrNorm0 = dot(p[1]-p[0], p[1]-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(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)
|
else if(dy > alpha*dx)
|
||||||
{
|
{
|
||||||
segmentBuffer.elements[segIndex].config = MG_GL_TL;
|
segmentBuffer.elements[segIndex].config = OC_GL_TL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
segmentBuffer.elements[segIndex].config = MG_GL_BR;
|
segmentBuffer.elements[segIndex].config = OC_GL_BR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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)
|
else if(dy < ofs - alpha*dx)
|
||||||
{
|
{
|
||||||
segmentBuffer.elements[segIndex].config = MG_GL_BL;
|
segmentBuffer.elements[segIndex].config = OC_GL_BL;
|
||||||
}
|
}
|
||||||
else
|
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)
|
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())
|
if(segIndex < segmentBuffer.elements.length())
|
||||||
{
|
{
|
||||||
segmentBuffer.elements[segIndex].hullVertex = p[0];
|
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)
|
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())
|
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 e = p[1].x - p[0].x;
|
||||||
float f = p[0].x*p[1].y - p[1].x*p[0].y;
|
float f = p[0].x*p[1].y - p[1].x*p[0].y;
|
||||||
|
|
||||||
float flip = ( segmentBuffer.elements[segIndex].config == MG_GL_TL
|
float flip = ( segmentBuffer.elements[segIndex].config == OC_GL_TL
|
||||||
|| segmentBuffer.elements[segIndex].config == MG_GL_BL)? -1 : 1;
|
|| 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));
|
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)
|
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())
|
if(segIndex < segmentBuffer.elements.length())
|
||||||
{
|
{
|
||||||
|
@ -839,23 +839,23 @@ void main()
|
||||||
{
|
{
|
||||||
int eltIndex = int(gl_WorkGroupID.x);
|
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)
|
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)};
|
vec2 p[4] = {elt.p[0]*scale, elt.p[1]*scale, vec2(0), vec2(0)};
|
||||||
line_setup(p, elt.pathIndex);
|
line_setup(p, elt.pathIndex);
|
||||||
} break;
|
} 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)};
|
vec2 p[4] = {elt.p[0]*scale, elt.p[1]*scale, elt.p[2]*scale, vec2(0)};
|
||||||
quadratic_setup(p, elt.pathIndex);
|
quadratic_setup(p, elt.pathIndex);
|
||||||
} break;
|
} 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};
|
vec2 p[4] = {elt.p[0]*scale, elt.p[1]*scale, elt.p[2]*scale, elt.p[3]*scale};
|
||||||
cubic_setup(p, elt.pathIndex);
|
cubic_setup(p, elt.pathIndex);
|
||||||
|
|
|
@ -11,126 +11,121 @@
|
||||||
|
|
||||||
#include"util/typedefs.h"
|
#include"util/typedefs.h"
|
||||||
#include"platform/platform.h"
|
#include"platform/platform.h"
|
||||||
#include"app/mp_app.h"
|
#include"app/app.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): backends selection
|
//NOTE(martin): backends selection
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MG_NONE,
|
OC_NONE,
|
||||||
MG_METAL,
|
OC_METAL,
|
||||||
MG_GL,
|
OC_GL,
|
||||||
MG_GLES,
|
OC_GLES,
|
||||||
MG_CANVAS,
|
OC_CANVAS,
|
||||||
MG_HOST } mg_surface_api;
|
OC_HOST } oc_surface_api;
|
||||||
|
|
||||||
//NOTE: these macros are used to select which backend to include when building milepost
|
//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
|
// they can be overridden by passing them to the compiler command line
|
||||||
#if PLATFORM_MACOS
|
#if OC_PLATFORM_MACOS
|
||||||
#ifndef MG_COMPILE_METAL
|
#ifndef OC_COMPILE_METAL
|
||||||
#define MG_COMPILE_METAL 1
|
#define OC_COMPILE_METAL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_GLES
|
#ifndef OC_COMPILE_GLES
|
||||||
#define MG_COMPILE_GLES 1
|
#define OC_COMPILE_GLES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_CANVAS
|
#ifndef OC_COMPILE_CANVAS
|
||||||
#if !MG_COMPILE_METAL
|
#if !OC_COMPILE_METAL
|
||||||
#error "Canvas surface requires a Metal backend on macOS. Make sure you define MG_COMPILE_METAL to 1."
|
#error "Canvas surface requires a Metal backend on macOS. Make sure you define OC_COMPILE_METAL to 1."
|
||||||
#endif
|
#endif
|
||||||
#define MG_COMPILE_CANVAS 1
|
#define OC_COMPILE_CANVAS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MG_COMPILE_GL 0
|
#define OC_COMPILE_GL 0
|
||||||
|
|
||||||
#elif PLATFORM_WINDOWS
|
#elif OC_PLATFORM_WINDOWS
|
||||||
#ifndef MG_COMPILE_GL
|
#ifndef OC_COMPILE_GL
|
||||||
#define MG_COMPILE_GL 1
|
#define OC_COMPILE_GL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_GLES
|
#ifndef OC_COMPILE_GLES
|
||||||
#define MG_COMPILE_GLES 1
|
#define OC_COMPILE_GLES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_CANVAS
|
#ifndef OC_COMPILE_CANVAS
|
||||||
#if !MG_COMPILE_GL
|
#if !OC_COMPILE_GL
|
||||||
#error "Canvas surface requires an OpenGL backend on Windows. Make sure you define MG_COMPILE_GL to 1."
|
#error "Canvas surface requires an OpenGL backend on Windows. Make sure you define OC_COMPILE_GL to 1."
|
||||||
#endif
|
#endif
|
||||||
#define MG_COMPILE_CANVAS 1
|
#define OC_COMPILE_CANVAS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif PLATFORM_LINUX
|
#elif PLATFORM_LINUX
|
||||||
#ifndef MG_COMPILE_GL
|
#ifndef OC_COMPILE_GL
|
||||||
#define MG_COMPILE_GL 1
|
#define OC_COMPILE_GL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_CANVAS
|
#ifndef OC_COMPILE_CANVAS
|
||||||
#if !MG_COMPILE_GL
|
#if !OC_COMPILE_GL
|
||||||
#error "Canvas surface requires an OpenGL backend on Linux. Make sure you define MG_COMPILE_GL to 1."
|
#error "Canvas surface requires an OpenGL backend on Linux. Make sure you define OC_COMPILE_GL to 1."
|
||||||
#endif
|
#endif
|
||||||
#define MG_COMPILE_CANVAS 1
|
#define OC_COMPILE_CANVAS 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//NOTE: these macros are used to select backend-specific APIs to include when using milepost
|
//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"
|
#include"mtl_surface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MG_EXPOSE_SURFACE_WGL
|
#ifdef OC_EXPOSE_SURFACE_WGL
|
||||||
#include"wgl_surface.h"
|
#include"wgl_surface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//TODO: expose nsgl surface when supported, expose egl surface, etc...
|
//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
|
//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);
|
ORCA_API oc_surface oc_surface_nil(void);
|
||||||
MP_API bool mg_surface_is_nil(mg_surface surface);
|
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);
|
ORCA_API oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api);
|
||||||
MP_API void mg_surface_destroy(mg_surface surface);
|
ORCA_API void oc_surface_destroy(oc_surface surface);
|
||||||
|
|
||||||
MP_API void mg_surface_prepare(mg_surface surface);
|
ORCA_API void oc_surface_select(oc_surface surface);
|
||||||
MP_API void mg_surface_present(mg_surface surface);
|
ORCA_API void oc_surface_present(oc_surface surface);
|
||||||
MP_API void mg_surface_deselect(void);
|
ORCA_API void oc_surface_deselect(void);
|
||||||
|
|
||||||
MP_API void mg_surface_swap_interval(mg_surface surface, int swap);
|
ORCA_API void oc_surface_swap_interval(oc_surface surface, int swap);
|
||||||
MP_API vec2 mg_surface_get_size(mg_surface surface);
|
ORCA_API oc_vec2 oc_surface_get_size(oc_surface surface);
|
||||||
MP_API vec2 mg_surface_contents_scaling(mg_surface surface);
|
ORCA_API oc_vec2 oc_surface_contents_scaling(oc_surface surface);
|
||||||
MP_API bool mg_surface_get_hidden(mg_surface surface);
|
ORCA_API bool oc_surface_get_hidden(oc_surface surface);
|
||||||
MP_API void mg_surface_set_hidden(mg_surface surface, bool hidden);
|
ORCA_API void oc_surface_set_hidden(oc_surface surface, bool hidden);
|
||||||
|
|
||||||
//NOTE(martin): surface sharing
|
//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);
|
ORCA_API oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api);
|
||||||
MP_API mg_surface mg_surface_create_host(mp_window window);
|
ORCA_API oc_surface oc_surface_create_host(oc_window window);
|
||||||
MP_API mg_surface_id mg_surface_remote_id(mg_surface surface);
|
ORCA_API oc_surface_id oc_surface_remote_id(oc_surface surface);
|
||||||
MP_API void mg_surface_host_connect(mg_surface surface, mg_surface_id remoteId);
|
ORCA_API void oc_surface_host_connect(oc_surface surface, oc_surface_id remoteId);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): graphics canvas structs
|
//NOTE(martin): graphics canvas structs
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
typedef struct mg_canvas { u64 h; } mg_canvas;
|
typedef struct oc_canvas { u64 h; } oc_canvas;
|
||||||
typedef struct mg_font { u64 h; } mg_font;
|
typedef struct oc_font { u64 h; } oc_font;
|
||||||
typedef struct mg_image { u64 h; } mg_image;
|
typedef struct oc_image { u64 h; } oc_image;
|
||||||
|
|
||||||
typedef struct mg_mat2x3
|
typedef struct oc_color
|
||||||
{
|
|
||||||
f32 m[6];
|
|
||||||
} mg_mat2x3;
|
|
||||||
|
|
||||||
typedef struct mg_color
|
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -143,16 +138,16 @@ typedef struct mg_color
|
||||||
};
|
};
|
||||||
f32 c[4];
|
f32 c[4];
|
||||||
};
|
};
|
||||||
} mg_color;
|
} oc_color;
|
||||||
|
|
||||||
typedef enum {MG_JOINT_MITER = 0,
|
typedef enum {OC_JOINT_MITER = 0,
|
||||||
MG_JOINT_BEVEL,
|
OC_JOINT_BEVEL,
|
||||||
MG_JOINT_NONE } mg_joint_type;
|
OC_JOINT_NONE } oc_joint_type;
|
||||||
|
|
||||||
typedef enum {MG_CAP_NONE = 0,
|
typedef enum {OC_CAP_NONE = 0,
|
||||||
MG_CAP_SQUARE } mg_cap_type;
|
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 ascent; // the extent above the baseline (by convention a positive value extends above the baseline)
|
||||||
f32 descent; // the extent below the baseline (by convention, positive value extends below the baseline)
|
f32 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 capHeight; // height of the upper case letter 'M'
|
||||||
f32 width; // maximum width of the font
|
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 xBearing;
|
||||||
f32 yBearing;
|
f32 yBearing;
|
||||||
|
@ -172,159 +167,159 @@ typedef struct mg_text_extents
|
||||||
f32 xAdvance;
|
f32 xAdvance;
|
||||||
f32 yAdvance;
|
f32 yAdvance;
|
||||||
|
|
||||||
} mg_text_extents;
|
} oc_text_extents;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): graphics canvas
|
//NOTE(martin): graphics canvas
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API mg_canvas mg_canvas_nil(void);
|
ORCA_API oc_canvas oc_canvas_nil(void);
|
||||||
MP_API bool mg_canvas_is_nil(mg_canvas canvas);
|
ORCA_API bool oc_canvas_is_nil(oc_canvas canvas);
|
||||||
|
|
||||||
MP_API mg_canvas mg_canvas_create(void);
|
ORCA_API oc_canvas oc_canvas_create(void);
|
||||||
MP_API void mg_canvas_destroy(mg_canvas canvas);
|
ORCA_API void oc_canvas_destroy(oc_canvas canvas);
|
||||||
MP_API mg_canvas mg_canvas_set_current(mg_canvas canvas);
|
ORCA_API oc_canvas oc_canvas_set_current(oc_canvas canvas);
|
||||||
MP_API void mg_render(mg_surface surface, mg_canvas canvas);
|
ORCA_API void oc_render(oc_surface surface, oc_canvas canvas);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): fonts
|
//NOTE(martin): fonts
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API mg_font mg_font_nil(void);
|
ORCA_API oc_font oc_font_nil(void);
|
||||||
MP_API mg_font mg_font_create_from_memory(u32 size, byte* buffer, u32 rangeCount, unicode_range* ranges);
|
ORCA_API oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges);
|
||||||
MP_API void mg_font_destroy(mg_font font);
|
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//
|
//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
|
//TODO(martin): add enum error codes
|
||||||
|
|
||||||
MP_API mg_font_extents mg_font_get_extents(mg_font font);
|
ORCA_API oc_font_extents oc_font_get_extents(oc_font font);
|
||||||
MP_API mg_font_extents mg_font_get_scaled_extents(mg_font font, f32 emSize);
|
ORCA_API oc_font_extents oc_font_get_scaled_extents(oc_font font, f32 emSize);
|
||||||
MP_API f32 mg_font_get_scale_for_em_pixels(mg_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
|
//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.
|
// 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);
|
ORCA_API oc_str32 oc_font_get_glyph_indices(oc_font font, oc_str32 codePoints, oc_str32 backing);
|
||||||
MP_API str32 mg_font_push_glyph_indices(mg_font font, mem_arena* arena, str32 codePoints);
|
ORCA_API oc_str32 oc_font_push_glyph_indices(oc_font font, oc_arena* arena, oc_str32 codePoints);
|
||||||
MP_API u32 mg_font_get_glyph_index(mg_font font, utf32 codePoint);
|
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);
|
ORCA_API oc_rect oc_text_bounding_box_utf32(oc_font font, f32 fontSize, oc_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(oc_font font, f32 fontSize, oc_str8 text);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): images
|
//NOTE(martin): images
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API mg_image mg_image_nil(void);
|
ORCA_API oc_image oc_image_nil(void);
|
||||||
MP_API bool mg_image_is_nil(mg_image a);
|
ORCA_API bool oc_image_is_nil(oc_image a);
|
||||||
|
|
||||||
MP_API mg_image mg_image_create(mg_surface surface, u32 width, u32 height);
|
ORCA_API oc_image oc_image_create(oc_surface surface, u32 width, u32 height);
|
||||||
MP_API mg_image mg_image_create_from_rgba8(mg_surface surface, u32 width, u32 height, u8* pixels);
|
ORCA_API oc_image oc_image_create_from_rgba8(oc_surface surface, u32 width, u32 height, u8* pixels);
|
||||||
MP_API mg_image mg_image_create_from_data(mg_surface surface, str8 data, bool flip);
|
ORCA_API oc_image oc_image_create_from_memory(oc_surface surface, oc_str8 mem, 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_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);
|
ORCA_API void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels);
|
||||||
MP_API vec2 mg_image_size(mg_image image);
|
ORCA_API oc_vec2 oc_image_size(oc_image image);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): atlasing
|
//NOTE(martin): atlasing
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
//NOTE: rectangle allocator
|
//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);
|
ORCA_API oc_rect_atlas* oc_rect_atlas_create(oc_arena* arena, i32 width, i32 height);
|
||||||
MP_API mp_rect mg_rect_atlas_alloc(mg_rect_atlas* atlas, i32 width, i32 height);
|
ORCA_API oc_rect oc_rect_atlas_alloc(oc_rect_atlas* atlas, i32 width, i32 height);
|
||||||
MP_API void mg_rect_atlas_recycle(mg_rect_atlas* atlas, mp_rect rect);
|
ORCA_API void oc_rect_atlas_recycle(oc_rect_atlas* atlas, oc_rect rect);
|
||||||
|
|
||||||
//NOTE: image atlas helpers
|
//NOTE: image atlas helpers
|
||||||
typedef struct mg_image_region
|
typedef struct oc_image_region
|
||||||
{
|
{
|
||||||
mg_image image;
|
oc_image image;
|
||||||
mp_rect rect;
|
oc_rect rect;
|
||||||
} mg_image_region;
|
} 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);
|
ORCA_API oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_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);
|
ORCA_API oc_image_region oc_image_atlas_alloc_from_data(oc_rect_atlas* atlas, oc_image backingImage, oc_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);
|
ORCA_API oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 path, bool flip);
|
||||||
MP_API void mg_image_atlas_recycle(mg_rect_atlas* atlas, mg_image_region imageRgn);
|
ORCA_API void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): transform, viewport and clipping
|
//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);
|
ORCA_API void oc_matrix_push(oc_mat2x3 matrix);
|
||||||
MP_API void mg_matrix_pop(void);
|
ORCA_API void oc_matrix_pop(void);
|
||||||
|
|
||||||
MP_API void mg_clip_push(f32 x, f32 y, f32 w, f32 h);
|
ORCA_API void oc_clip_push(f32 x, f32 y, f32 w, f32 h);
|
||||||
MP_API void mg_clip_pop(void);
|
ORCA_API void oc_clip_pop(void);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): graphics attributes setting/getting
|
//NOTE(martin): graphics attributes setting/getting
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API void mg_set_color(mg_color color);
|
ORCA_API void oc_set_color(oc_color color);
|
||||||
MP_API void mg_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
|
ORCA_API void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
|
||||||
MP_API void mg_set_width(f32 width);
|
ORCA_API void oc_set_width(f32 width);
|
||||||
MP_API void mg_set_tolerance(f32 tolerance);
|
ORCA_API void oc_set_tolerance(f32 tolerance);
|
||||||
MP_API void mg_set_joint(mg_joint_type joint);
|
ORCA_API void oc_set_joint(oc_joint_type joint);
|
||||||
MP_API void mg_set_max_joint_excursion(f32 maxJointExcursion);
|
ORCA_API void oc_set_max_joint_excursion(f32 maxJointExcursion);
|
||||||
MP_API void mg_set_cap(mg_cap_type cap);
|
ORCA_API void oc_set_cap(oc_cap_type cap);
|
||||||
MP_API void mg_set_font(mg_font font);
|
ORCA_API void oc_set_font(oc_font font);
|
||||||
MP_API void mg_set_font_size(f32 size);
|
ORCA_API void oc_set_font_size(f32 size);
|
||||||
MP_API void mg_set_text_flip(bool flip);
|
ORCA_API void oc_set_text_flip(bool flip);
|
||||||
MP_API void mg_set_image(mg_image image);
|
ORCA_API void oc_set_image(oc_image image);
|
||||||
MP_API void mg_set_image_source_region(mp_rect region);
|
ORCA_API void oc_set_image_source_region(oc_rect region);
|
||||||
|
|
||||||
MP_API mg_color mg_get_color(void);
|
ORCA_API oc_color oc_get_color(void);
|
||||||
MP_API f32 mg_get_width(void);
|
ORCA_API f32 oc_get_width(void);
|
||||||
MP_API f32 mg_get_tolerance(void);
|
ORCA_API f32 oc_get_tolerance(void);
|
||||||
MP_API mg_joint_type mg_get_joint(void);
|
ORCA_API oc_joint_type oc_get_joint(void);
|
||||||
MP_API f32 mg_get_max_joint_excursion(void);
|
ORCA_API f32 oc_get_max_joint_excursion(void);
|
||||||
MP_API mg_cap_type mg_get_cap(void);
|
ORCA_API oc_cap_type oc_get_cap(void);
|
||||||
MP_API mg_font mg_get_font(void);
|
ORCA_API oc_font oc_get_font(void);
|
||||||
MP_API f32 mg_get_font_size(void);
|
ORCA_API f32 oc_get_font_size(void);
|
||||||
MP_API bool mg_get_text_flip(void);
|
ORCA_API bool oc_get_text_flip(void);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): path construction
|
//NOTE(martin): path construction
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API vec2 mg_get_position(void);
|
ORCA_API oc_vec2 oc_get_position(void);
|
||||||
MP_API void mg_move_to(f32 x, f32 y);
|
ORCA_API void oc_move_to(f32 x, f32 y);
|
||||||
MP_API void mg_line_to(f32 x, f32 y);
|
ORCA_API void oc_line_to(f32 x, f32 y);
|
||||||
MP_API void mg_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
|
ORCA_API void oc_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);
|
ORCA_API void oc_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
|
||||||
MP_API void mg_close_path(void);
|
ORCA_API void oc_close_path(void);
|
||||||
|
|
||||||
MP_API mp_rect mg_glyph_outlines(str32 glyphIndices);
|
ORCA_API oc_rect oc_glyph_outlines(oc_str32 glyphIndices);
|
||||||
MP_API void mg_codepoints_outlines(str32 string);
|
ORCA_API void oc_codepoints_outlines(oc_str32 string);
|
||||||
MP_API void mg_text_outlines(str8 string);
|
ORCA_API void oc_text_outlines(oc_str8 string);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): clear/fill/stroke
|
//NOTE(martin): clear/fill/stroke
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API void mg_clear(void);
|
ORCA_API void oc_clear(void);
|
||||||
MP_API void mg_fill(void);
|
ORCA_API void oc_fill(void);
|
||||||
MP_API void mg_stroke(void);
|
ORCA_API void oc_stroke(void);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): 'fast' shapes primitives
|
//NOTE(martin): 'fast' shapes primitives
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API void mg_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
|
ORCA_API void oc_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
|
||||||
MP_API void mg_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
|
ORCA_API void oc_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);
|
ORCA_API void oc_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);
|
ORCA_API void oc_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);
|
ORCA_API void oc_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
|
||||||
MP_API void mg_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
|
ORCA_API void oc_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
|
||||||
MP_API void mg_circle_fill(f32 x, f32 y, f32 r);
|
ORCA_API void oc_circle_fill(f32 x, f32 y, f32 r);
|
||||||
MP_API void mg_circle_stroke(f32 x, f32 y, f32 r);
|
ORCA_API void oc_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_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
|
||||||
|
|
||||||
//NOTE: image helpers
|
//NOTE: image helpers
|
||||||
MP_API void mg_image_draw(mg_image image, mp_rect rect);
|
ORCA_API void oc_image_draw(oc_image image, oc_rect rect);
|
||||||
MP_API void mg_image_draw_region(mg_image image, mp_rect srcRegion, mp_rect dstRegion);
|
ORCA_API void oc_image_draw_region(oc_image image, oc_rect srcRegion, oc_rect dstRegion);
|
||||||
|
|
||||||
#endif //__GRAPHICS_H_
|
#endif //__GRAPHICS_H_
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,70 +13,70 @@
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// canvas structs
|
// canvas structs
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
typedef enum { MG_PATH_MOVE,
|
typedef enum { OC_PATH_MOVE,
|
||||||
MG_PATH_LINE,
|
OC_PATH_LINE,
|
||||||
MG_PATH_QUADRATIC,
|
OC_PATH_QUADRATIC,
|
||||||
MG_PATH_CUBIC } mg_path_elt_type;
|
OC_PATH_CUBIC } oc_path_elt_type;
|
||||||
|
|
||||||
typedef struct mg_path_elt
|
typedef struct oc_path_elt
|
||||||
{
|
{
|
||||||
mg_path_elt_type type;
|
oc_path_elt_type type;
|
||||||
vec2 p[3];
|
oc_vec2 p[3];
|
||||||
|
|
||||||
} mg_path_elt;
|
} oc_path_elt;
|
||||||
|
|
||||||
typedef struct mg_path_descriptor
|
typedef struct oc_path_descriptor
|
||||||
{
|
{
|
||||||
u32 startIndex;
|
u32 startIndex;
|
||||||
u32 count;
|
u32 count;
|
||||||
vec2 startPoint;
|
oc_vec2 startPoint;
|
||||||
|
|
||||||
} mg_path_descriptor;
|
} oc_path_descriptor;
|
||||||
|
|
||||||
typedef struct mg_attributes
|
typedef struct oc_attributes
|
||||||
{
|
{
|
||||||
f32 width;
|
f32 width;
|
||||||
f32 tolerance;
|
f32 tolerance;
|
||||||
mg_color color;
|
oc_color color;
|
||||||
mg_joint_type joint;
|
oc_joint_type joint;
|
||||||
f32 maxJointExcursion;
|
f32 maxJointExcursion;
|
||||||
mg_cap_type cap;
|
oc_cap_type cap;
|
||||||
|
|
||||||
mg_font font;
|
oc_font font;
|
||||||
f32 fontSize;
|
f32 fontSize;
|
||||||
|
|
||||||
mg_image image;
|
oc_image image;
|
||||||
mp_rect srcRegion;
|
oc_rect srcRegion;
|
||||||
|
|
||||||
mg_mat2x3 transform;
|
oc_mat2x3 transform;
|
||||||
mp_rect clip;
|
oc_rect clip;
|
||||||
|
|
||||||
} mg_attributes;
|
} oc_attributes;
|
||||||
|
|
||||||
typedef enum { MG_CMD_FILL,
|
typedef enum { OC_CMD_FILL,
|
||||||
MG_CMD_STROKE,
|
OC_CMD_STROKE,
|
||||||
MG_CMD_JUMP
|
OC_CMD_JUMP
|
||||||
} mg_primitive_cmd;
|
} oc_primitive_cmd;
|
||||||
|
|
||||||
typedef struct mg_primitive
|
typedef struct oc_primitive
|
||||||
{
|
{
|
||||||
mg_primitive_cmd cmd;
|
oc_primitive_cmd cmd;
|
||||||
mg_attributes attributes;
|
oc_attributes attributes;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
mg_path_descriptor path;
|
oc_path_descriptor path;
|
||||||
mp_rect rect;
|
oc_rect rect;
|
||||||
u32 jump;
|
u32 jump;
|
||||||
};
|
};
|
||||||
|
|
||||||
} mg_primitive;
|
} oc_primitive;
|
||||||
|
|
||||||
MP_API void mg_surface_render_commands(mg_surface surface,
|
ORCA_API void oc_surface_render_commands(oc_surface surface,
|
||||||
mg_color clearColor,
|
oc_color clearColor,
|
||||||
u32 primitiveCount,
|
u32 primitiveCount,
|
||||||
mg_primitive* primitives,
|
oc_primitive* primitives,
|
||||||
u32 eltCount,
|
u32 eltCount,
|
||||||
mg_path_elt* elements);
|
oc_path_elt* elements);
|
||||||
|
|
||||||
#endif //__GRAPHICS_COMMON_H_
|
#endif //__GRAPHICS_COMMON_H_
|
||||||
|
|
|
@ -12,33 +12,33 @@
|
||||||
// per-thread selected surface
|
// per-thread selected surface
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
mp_thread_local mg_surface __mgSelectedSurface = {0};
|
oc_thread_local oc_surface oc_selectedSurface = {0};
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// typed handles functions
|
// 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);
|
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);
|
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);
|
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);
|
return(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,48 +46,48 @@ mg_image_data* mg_image_data_from_handle(mg_image handle)
|
||||||
// surface API
|
// surface API
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
#if MG_COMPILE_GL
|
#if OC_COMPILE_GL
|
||||||
#if PLATFORM_WINDOWS
|
#if OC_PLATFORM_WINDOWS
|
||||||
#include"wgl_surface.h"
|
#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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
#if OC_COMPILE_GLES
|
||||||
#include"egl_surface.h"
|
#include"egl_surface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_METAL
|
#if OC_COMPILE_METAL
|
||||||
#include"mtl_surface.h"
|
#include"mtl_surface.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
#if OC_COMPILE_CANVAS
|
||||||
#if PLATFORM_MACOS
|
#if OC_PLATFORM_MACOS
|
||||||
mg_surface_data* mtl_canvas_surface_create_for_window(mp_window window);
|
oc_surface_data* oc_mtl_canvas_surface_create_for_window(oc_window window);
|
||||||
#elif PLATFORM_WINDOWS
|
#elif OC_PLATFORM_WINDOWS
|
||||||
mg_surface_data* gl_canvas_surface_create_for_window(mp_window window);
|
oc_surface_data* oc_gl_canvas_surface_create_for_window(oc_window window);
|
||||||
#endif
|
#endif
|
||||||
#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;
|
bool result = false;
|
||||||
switch(api)
|
switch(api)
|
||||||
{
|
{
|
||||||
#if MG_COMPILE_METAL
|
#if OC_COMPILE_METAL
|
||||||
case MG_METAL:
|
case OC_METAL:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_GL
|
#if OC_COMPILE_GL
|
||||||
case MG_GL:
|
case OC_GL:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
#if OC_COMPILE_GLES
|
||||||
case MG_GLES:
|
case OC_GLES:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
#if OC_COMPILE_CANVAS
|
||||||
case MG_CANVAS:
|
case OC_CANVAS:
|
||||||
#endif
|
#endif
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
|
@ -98,45 +98,45 @@ bool mg_is_surface_backend_available(mg_surface_api api)
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_surface mg_surface_nil() { return((mg_surface){.h = 0}); }
|
oc_surface oc_surface_nil() { return((oc_surface){.h = 0}); }
|
||||||
bool mg_surface_is_nil(mg_surface surface) { return(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();
|
oc_surface surfaceHandle = oc_surface_nil();
|
||||||
mg_surface_data* surface = 0;
|
oc_surface_data* surface = 0;
|
||||||
|
|
||||||
switch(api)
|
switch(api)
|
||||||
{
|
{
|
||||||
#if MG_COMPILE_GL
|
#if OC_COMPILE_GL
|
||||||
case MG_GL:
|
case OC_GL:
|
||||||
surface = gl_surface_create_for_window(window);
|
surface = oc_gl_surface_create_for_window(window);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
#if OC_COMPILE_GLES
|
||||||
case MG_GLES:
|
case OC_GLES:
|
||||||
surface = mg_egl_surface_create_for_window(window);
|
surface = oc_egl_surface_create_for_window(window);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_METAL
|
#if OC_COMPILE_METAL
|
||||||
case MG_METAL:
|
case OC_METAL:
|
||||||
surface = mg_mtl_surface_create_for_window(window);
|
surface = oc_mtl_surface_create_for_window(window);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
#if OC_COMPILE_CANVAS
|
||||||
case MG_CANVAS:
|
case OC_CANVAS:
|
||||||
|
|
||||||
#if PLATFORM_MACOS
|
#if OC_PLATFORM_MACOS
|
||||||
surface = mtl_canvas_surface_create_for_window(window);
|
surface = oc_mtl_canvas_surface_create_for_window(window);
|
||||||
#elif PLATFORM_WINDOWS
|
#elif OC_PLATFORM_WINDOWS
|
||||||
surface = gl_canvas_surface_create_for_window(window);
|
surface = oc_gl_canvas_surface_create_for_window(window);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -146,26 +146,26 @@ mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api)
|
||||||
}
|
}
|
||||||
if(surface)
|
if(surface)
|
||||||
{
|
{
|
||||||
surfaceHandle = mg_surface_handle_alloc(surface);
|
surfaceHandle = oc_surface_handle_alloc(surface);
|
||||||
mg_surface_prepare(surfaceHandle);
|
oc_surface_select(surfaceHandle);
|
||||||
}
|
}
|
||||||
return(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();
|
oc_surface surfaceHandle = oc_surface_nil();
|
||||||
mg_surface_data* surface = 0;
|
oc_surface_data* surface = 0;
|
||||||
|
|
||||||
switch(api)
|
switch(api)
|
||||||
{
|
{
|
||||||
#if MG_COMPILE_GLES
|
#if OC_COMPILE_GLES
|
||||||
case MG_GLES:
|
case OC_GLES:
|
||||||
surface = mg_egl_surface_create_remote(width, height);
|
surface = oc_egl_surface_create_remote(width, height);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -174,42 +174,42 @@ mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api)
|
||||||
}
|
}
|
||||||
if(surface)
|
if(surface)
|
||||||
{
|
{
|
||||||
surfaceHandle = mg_surface_handle_alloc(surface);
|
surfaceHandle = oc_surface_handle_alloc(surface);
|
||||||
mg_surface_prepare(surfaceHandle);
|
oc_surface_select(surfaceHandle);
|
||||||
}
|
}
|
||||||
return(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();
|
oc_surface handle = oc_surface_nil();
|
||||||
mg_surface_data* surface = 0;
|
oc_surface_data* surface = 0;
|
||||||
#if PLATFORM_MACOS
|
#if OC_PLATFORM_MACOS
|
||||||
surface = mg_osx_surface_create_host(window);
|
surface = oc_osx_surface_create_host(window);
|
||||||
#elif PLATFORM_WINDOWS
|
#elif OC_PLATFORM_WINDOWS
|
||||||
surface = mg_win32_surface_create_host(window);
|
surface = oc_win32_surface_create_host(window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(surface)
|
if(surface)
|
||||||
{
|
{
|
||||||
handle = mg_surface_handle_alloc(surface);
|
handle = oc_surface_handle_alloc(surface);
|
||||||
}
|
}
|
||||||
return(handle);
|
return(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_surface_destroy(mg_surface handle)
|
void oc_surface_destroy(oc_surface handle)
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(__mgData.init);
|
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
oc_surface_data* surface = oc_surface_data_from_handle(handle);
|
||||||
if(surface)
|
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)
|
if(surface->backend && surface->backend->destroy)
|
||||||
|
@ -217,64 +217,64 @@ void mg_surface_destroy(mg_surface handle)
|
||||||
surface->backend->destroy(surface->backend);
|
surface->backend->destroy(surface->backend);
|
||||||
}
|
}
|
||||||
surface->destroy(surface);
|
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)
|
if(prevSurface && prevSurface->deselect)
|
||||||
{
|
{
|
||||||
prevSurface->deselect(prevSurface);
|
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)
|
if(surfaceData && surfaceData->prepare)
|
||||||
{
|
{
|
||||||
surfaceData->prepare(surfaceData);
|
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);
|
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->present)
|
if(surfaceData && surfaceData->present)
|
||||||
{
|
{
|
||||||
surfaceData->present(surfaceData);
|
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);
|
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->swapInterval)
|
if(surfaceData && surfaceData->swapInterval)
|
||||||
{
|
{
|
||||||
surfaceData->swapInterval(surfaceData, swap);
|
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);
|
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||||
vec2 size = {0};
|
oc_vec2 size = {0};
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->getSize)
|
if(surfaceData && surfaceData->getSize)
|
||||||
{
|
{
|
||||||
size = surfaceData->getSize(surfaceData);
|
size = surfaceData->getSize(surfaceData);
|
||||||
|
@ -282,11 +282,11 @@ vec2 mg_surface_get_size(mg_surface surface)
|
||||||
return(size);
|
return(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 mg_surface_contents_scaling(mg_surface surface)
|
oc_vec2 oc_surface_contents_scaling(oc_surface surface)
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(__mgData.init);
|
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||||
vec2 scaling = {1, 1};
|
oc_vec2 scaling = {1, 1};
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->contentsScaling)
|
if(surfaceData && surfaceData->contentsScaling)
|
||||||
{
|
{
|
||||||
scaling = surfaceData->contentsScaling(surfaceData);
|
scaling = surfaceData->contentsScaling(surfaceData);
|
||||||
|
@ -294,21 +294,21 @@ vec2 mg_surface_contents_scaling(mg_surface surface)
|
||||||
return(scaling);
|
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);
|
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->setHidden)
|
if(surfaceData && surfaceData->setHidden)
|
||||||
{
|
{
|
||||||
surfaceData->setHidden(surfaceData, hidden);
|
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;
|
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)
|
if(surfaceData && surfaceData->getHidden)
|
||||||
{
|
{
|
||||||
res = surfaceData->getHidden(surfaceData);
|
res = surfaceData->getHidden(surfaceData);
|
||||||
|
@ -316,10 +316,10 @@ bool mg_surface_get_hidden(mg_surface surface)
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* mg_surface_native_layer(mg_surface surface)
|
void* oc_surface_native_layer(oc_surface surface)
|
||||||
{
|
{
|
||||||
void* res = 0;
|
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)
|
if(surfaceData && surfaceData->nativeLayer)
|
||||||
{
|
{
|
||||||
res = surfaceData->nativeLayer(surfaceData);
|
res = surfaceData->nativeLayer(surfaceData);
|
||||||
|
@ -327,10 +327,10 @@ void* mg_surface_native_layer(mg_surface surface)
|
||||||
return(res);
|
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;
|
oc_surface_id remoteId = 0;
|
||||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
oc_surface_data* surface = oc_surface_data_from_handle(handle);
|
||||||
if(surface && surface->remoteID)
|
if(surface && surface->remoteID)
|
||||||
{
|
{
|
||||||
remoteId = surface->remoteID(surface);
|
remoteId = surface->remoteID(surface);
|
||||||
|
@ -338,27 +338,27 @@ mg_surface_id mg_surface_remote_id(mg_surface handle)
|
||||||
return(remoteId);
|
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)
|
if(surface && surface->hostConnect)
|
||||||
{
|
{
|
||||||
surface->hostConnect(surface, remoteID);
|
surface->hostConnect(surface, remoteID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_surface_render_commands(mg_surface surface,
|
void oc_surface_render_commands(oc_surface surface,
|
||||||
mg_color clearColor,
|
oc_color clearColor,
|
||||||
u32 primitiveCount,
|
u32 primitiveCount,
|
||||||
mg_primitive* primitives,
|
oc_primitive* primitives,
|
||||||
u32 eltCount,
|
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)
|
else if(surfaceData && surfaceData->backend)
|
||||||
{
|
{
|
||||||
|
@ -375,10 +375,10 @@ void mg_surface_render_commands(mg_surface surface,
|
||||||
//NOTE(martin): images
|
//NOTE(martin): images
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
vec2 mg_image_size(mg_image image)
|
oc_vec2 oc_image_size(oc_image image)
|
||||||
{
|
{
|
||||||
vec2 res = {0};
|
oc_vec2 res = {0};
|
||||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
oc_image_data* imageData = oc_image_data_from_handle(image);
|
||||||
if(imageData)
|
if(imageData)
|
||||||
{
|
{
|
||||||
res = imageData->size;
|
res = imageData->size;
|
||||||
|
@ -386,67 +386,67 @@ vec2 mg_image_size(mg_image image)
|
||||||
return(res);
|
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();
|
oc_image image = oc_image_nil();
|
||||||
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 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)
|
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)
|
if(imageData)
|
||||||
{
|
{
|
||||||
imageData->surface = surface;
|
imageData->surface = surface;
|
||||||
image = mg_image_handle_alloc(imageData);
|
image = oc_image_handle_alloc(imageData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(image);
|
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)
|
||||||
{
|
{
|
||||||
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
|
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)
|
if(surface && surface->backend)
|
||||||
{
|
{
|
||||||
surface->backend->imageDestroy(surface->backend, imageData);
|
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)
|
||||||
{
|
{
|
||||||
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
|
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)
|
if(surfaceData)
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(surfaceData->backend);
|
OC_DEBUG_ASSERT(surfaceData->backend);
|
||||||
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
|
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#define __GRAPHICS_SURFACE_H_
|
#define __GRAPHICS_SURFACE_H_
|
||||||
|
|
||||||
#include"graphics_common.h"
|
#include"graphics_common.h"
|
||||||
#include"app/mp_app_internal.h"
|
#include"app/app_internal.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -18,92 +18,92 @@ extern "C" {
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// surface interface
|
// surface interface
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
typedef struct mg_surface_data mg_surface_data;
|
typedef struct oc_surface_data oc_surface_data;
|
||||||
typedef struct mg_canvas_backend mg_canvas_backend;
|
typedef struct oc_canvas_backend oc_canvas_backend;
|
||||||
|
|
||||||
typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface);
|
typedef void (*oc_surface_destroy_proc)(oc_surface_data* surface);
|
||||||
typedef void (*mg_surface_prepare_proc)(mg_surface_data* surface);
|
typedef void (*oc_surface_select_proc)(oc_surface_data* surface);
|
||||||
typedef void (*mg_surface_deselect_proc)(mg_surface_data* surface);
|
typedef void (*oc_surface_deselect_proc)(oc_surface_data* surface);
|
||||||
typedef void (*mg_surface_present_proc)(mg_surface_data* surface);
|
typedef void (*oc_surface_present_proc)(oc_surface_data* surface);
|
||||||
typedef void (*mg_surface_swap_interval_proc)(mg_surface_data* surface, int swap);
|
typedef void (*oc_surface_swap_interval_proc)(oc_surface_data* surface, int swap);
|
||||||
typedef vec2 (*mg_surface_get_size_proc)(mg_surface_data* surface);
|
typedef oc_vec2 (*oc_surface_get_size_proc)(oc_surface_data* surface);
|
||||||
typedef vec2 (*mg_surface_contents_scaling_proc)(mg_surface_data* surface);
|
typedef oc_vec2 (*oc_surface_contents_scaling_proc)(oc_surface_data* surface);
|
||||||
typedef bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface);
|
typedef bool (*oc_surface_get_hidden_proc)(oc_surface_data* surface);
|
||||||
typedef void (*mg_surface_set_hidden_proc)(mg_surface_data* surface, bool hidden);
|
typedef void (*oc_surface_set_hidden_proc)(oc_surface_data* surface, bool hidden);
|
||||||
typedef void* (*mg_surface_native_layer_proc)(mg_surface_data* surface);
|
typedef void* (*oc_surface_native_layer_proc)(oc_surface_data* surface);
|
||||||
typedef mg_surface_id (*mg_surface_remote_id_proc)(mg_surface_data* surface);
|
typedef oc_surface_id (*oc_surface_remote_id_proc)(oc_surface_data* surface);
|
||||||
typedef void (*mg_surface_host_connect_proc)(mg_surface_data* surface, mg_surface_id remoteId);
|
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;
|
oc_surface_api api;
|
||||||
mp_layer layer;
|
oc_layer layer;
|
||||||
|
|
||||||
mg_surface_destroy_proc destroy;
|
oc_surface_destroy_proc destroy;
|
||||||
mg_surface_prepare_proc prepare;
|
oc_surface_select_proc prepare;
|
||||||
mg_surface_present_proc present;
|
oc_surface_present_proc present;
|
||||||
mg_surface_deselect_proc deselect;
|
oc_surface_deselect_proc deselect;
|
||||||
mg_surface_swap_interval_proc swapInterval;
|
oc_surface_swap_interval_proc swapInterval;
|
||||||
mg_surface_get_size_proc getSize;
|
oc_surface_get_size_proc getSize;
|
||||||
mg_surface_contents_scaling_proc contentsScaling;
|
oc_surface_contents_scaling_proc contentsScaling;
|
||||||
mg_surface_get_hidden_proc getHidden;
|
oc_surface_get_hidden_proc getHidden;
|
||||||
mg_surface_set_hidden_proc setHidden;
|
oc_surface_set_hidden_proc setHidden;
|
||||||
mg_surface_native_layer_proc nativeLayer;
|
oc_surface_native_layer_proc nativeLayer;
|
||||||
mg_surface_remote_id_proc remoteID;
|
oc_surface_remote_id_proc remoteID;
|
||||||
mg_surface_host_connect_proc hostConnect;
|
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);
|
oc_surface oc_surface_handle_alloc(oc_surface_data* surface);
|
||||||
mg_surface_data* mg_surface_data_from_handle(mg_surface handle);
|
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 oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window);
|
||||||
void mg_surface_init_remote(mg_surface_data* surface, u32 width, u32 height);
|
void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height);
|
||||||
void mg_surface_init_host(mg_surface_data* surface, mp_window_data* window);
|
void oc_surface_init_host(oc_surface_data* surface, oc_window_data* window);
|
||||||
void mg_surface_cleanup(mg_surface_data* surface);
|
void oc_surface_cleanup(oc_surface_data* surface);
|
||||||
void* mg_surface_native_layer(mg_surface surface);
|
void* oc_surface_native_layer(oc_surface surface);
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// canvas backend interface
|
// canvas backend interface
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
typedef struct mg_image_data
|
typedef struct oc_image_data
|
||||||
{
|
{
|
||||||
list_elt listElt;
|
oc_list_elt listElt;
|
||||||
u32 generation;
|
u32 generation;
|
||||||
mg_surface surface;
|
oc_surface surface;
|
||||||
vec2 size;
|
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 oc_image_data* (*oc_canvas_backend_image_create_proc)(oc_canvas_backend* backend, oc_vec2 size);
|
||||||
typedef void (*mg_canvas_backend_image_destroy_proc)(mg_canvas_backend* backend, mg_image_data* image);
|
typedef void (*oc_canvas_backend_image_destroy_proc)(oc_canvas_backend* backend, oc_image_data* image);
|
||||||
typedef void (*mg_canvas_backend_image_upload_region_proc)(mg_canvas_backend* backend,
|
typedef void (*oc_canvas_backend_image_upload_region_proc)(oc_canvas_backend* backend,
|
||||||
mg_image_data* image,
|
oc_image_data* image,
|
||||||
mp_rect region,
|
oc_rect region,
|
||||||
u8* pixels);
|
u8* pixels);
|
||||||
|
|
||||||
typedef void (*mg_canvas_backend_render_proc)(mg_canvas_backend* backend,
|
typedef void (*oc_canvas_backend_render_proc)(oc_canvas_backend* backend,
|
||||||
mg_color clearColor,
|
oc_color clearColor,
|
||||||
u32 primitiveCount,
|
u32 primitiveCount,
|
||||||
mg_primitive* primitives,
|
oc_primitive* primitives,
|
||||||
u32 eltCount,
|
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;
|
oc_canvas_backend_image_create_proc imageCreate;
|
||||||
mg_canvas_backend_image_destroy_proc imageDestroy;
|
oc_canvas_backend_image_destroy_proc imageDestroy;
|
||||||
mg_canvas_backend_image_upload_region_proc imageUploadRegion;
|
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
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -12,45 +12,45 @@
|
||||||
#include<simd/simd.h>
|
#include<simd/simd.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MG_MTL_FILL,
|
OC_MTL_FILL,
|
||||||
MG_MTL_STROKE,
|
OC_MTL_STROKE,
|
||||||
} mg_mtl_cmd;
|
} oc_mtl_cmd;
|
||||||
|
|
||||||
typedef struct mg_mtl_path
|
typedef struct oc_mtl_path
|
||||||
{
|
{
|
||||||
mg_mtl_cmd cmd;
|
oc_mtl_cmd cmd;
|
||||||
matrix_float3x3 uvTransform;
|
matrix_float3x3 uvTransform;
|
||||||
vector_float4 color;
|
vector_float4 color;
|
||||||
vector_float4 box;
|
vector_float4 box;
|
||||||
vector_float4 clip;
|
vector_float4 clip;
|
||||||
int texture;
|
int texture;
|
||||||
} mg_mtl_path;
|
} oc_mtl_path;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MG_MTL_LINE = 1,
|
OC_MTL_LINE = 1,
|
||||||
MG_MTL_QUADRATIC,
|
OC_MTL_QUADRATIC,
|
||||||
MG_MTL_CUBIC,
|
OC_MTL_CUBIC,
|
||||||
} mg_mtl_seg_kind;
|
} oc_mtl_seg_kind;
|
||||||
|
|
||||||
typedef struct mg_mtl_path_elt
|
typedef struct oc_mtl_path_elt
|
||||||
{
|
{
|
||||||
int pathIndex;
|
int pathIndex;
|
||||||
mg_mtl_seg_kind kind;
|
oc_mtl_seg_kind kind;
|
||||||
vector_float2 p[4];
|
vector_float2 p[4];
|
||||||
} mg_mtl_path_elt;
|
} oc_mtl_path_elt;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MG_MTL_BL, // curve on bottom left
|
OC_MTL_BL, // curve on bottom left
|
||||||
MG_MTL_BR, // curve on bottom right
|
OC_MTL_BR, // curve on bottom right
|
||||||
MG_MTL_TL, // curve on top left
|
OC_MTL_TL, // curve on top left
|
||||||
MG_MTL_TR // curve on top right
|
OC_MTL_TR // curve on top right
|
||||||
} mg_mtl_seg_config;
|
} 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;
|
int pathIndex;
|
||||||
mg_mtl_seg_config config; //TODO pack these
|
oc_mtl_seg_config config; //TODO pack these
|
||||||
int windingIncrement;
|
int windingIncrement;
|
||||||
vector_float4 box;
|
vector_float4 box;
|
||||||
matrix_float3x3 implicitMatrix;
|
matrix_float3x3 implicitMatrix;
|
||||||
|
@ -58,27 +58,27 @@ typedef struct mg_mtl_segment
|
||||||
vector_float2 hullVertex;
|
vector_float2 hullVertex;
|
||||||
int debugID;
|
int debugID;
|
||||||
|
|
||||||
} mg_mtl_segment;
|
} oc_mtl_segment;
|
||||||
|
|
||||||
typedef struct mg_mtl_path_queue
|
typedef struct oc_mtl_path_queue
|
||||||
{
|
{
|
||||||
vector_int4 area;
|
vector_int4 area;
|
||||||
int tileQueues;
|
int tileQueues;
|
||||||
} mg_mtl_path_queue;
|
} oc_mtl_path_queue;
|
||||||
|
|
||||||
#ifdef __METAL_VERSION__
|
#ifdef __METAL_VERSION__
|
||||||
using namespace metal;
|
using namespace metal;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum { MG_MTL_OP_FILL,
|
typedef enum { OC_MTL_OP_FILL,
|
||||||
MG_MTL_OP_CLIP_FILL,
|
OC_MTL_OP_CLIP_FILL,
|
||||||
MG_MTL_OP_START,
|
OC_MTL_OP_START,
|
||||||
MG_MTL_OP_END,
|
OC_MTL_OP_END,
|
||||||
MG_MTL_OP_SEGMENT } mg_mtl_tile_op_kind;
|
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 index;
|
||||||
int next;
|
int next;
|
||||||
union
|
union
|
||||||
|
@ -87,25 +87,25 @@ typedef struct mg_mtl_tile_op
|
||||||
int windingOffset;
|
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 windingOffset;
|
||||||
atomic_int first;
|
atomic_int first;
|
||||||
int last;
|
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;
|
vector_uint2 tileCoord;
|
||||||
int first;
|
int first;
|
||||||
|
|
||||||
} mg_mtl_screen_tile;
|
} oc_mtl_screen_tile;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MG_MTL_MAX_IMAGES_PER_BATCH = 30
|
OC_MTL_MAX_IMAGES_PER_BATCH = 30
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__MTL_RENDERER_H_
|
#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)]],
|
kernel void mtl_path_setup(constant int* pathCount [[buffer(0)]],
|
||||||
const device mg_mtl_path* pathBuffer [[buffer(1)]],
|
const device oc_mtl_path* pathBuffer [[buffer(1)]],
|
||||||
device mg_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
device oc_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
||||||
device mg_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
device oc_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
||||||
device atomic_int* tileQueueCount [[buffer(4)]],
|
device atomic_int* tileQueueCount [[buffer(4)]],
|
||||||
constant int* tileQueueMax [[buffer(5)]],
|
constant int* tileQueueMax [[buffer(5)]],
|
||||||
constant int* tileSize [[buffer(6)]],
|
constant int* tileSize [[buffer(6)]],
|
||||||
constant float* scale [[buffer(7)]],
|
constant float* scale [[buffer(7)]],
|
||||||
uint pathIndex [[thread_position_in_grid]])
|
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
|
//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].area = int4(firstTile.x, firstTile.y, nTilesX, nTilesY);
|
||||||
pathQueueBuffer[pathIndex].tileQueues = tileQueuesIndex;
|
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++)
|
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));
|
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;
|
int side = 0;
|
||||||
if(p.y > seg->box.w || p.y <= seg->box.y)
|
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)
|
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
|
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;
|
float2 a, b, c;
|
||||||
switch(seg->config)
|
switch(seg->config)
|
||||||
{
|
{
|
||||||
case MG_MTL_TL:
|
case OC_MTL_TL:
|
||||||
a = seg->box.xy;
|
a = seg->box.xy;
|
||||||
b = seg->box.zw;
|
b = seg->box.zw;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_MTL_BR:
|
case OC_MTL_BR:
|
||||||
a = seg->box.zw;
|
a = seg->box.zw;
|
||||||
b = seg->box.xy;
|
b = seg->box.xy;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_MTL_TR:
|
case OC_MTL_TR:
|
||||||
a = seg->box.xw;
|
a = seg->box.xw;
|
||||||
b = seg->box.zy;
|
b = seg->box.zy;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_MTL_BL:
|
case OC_MTL_BL:
|
||||||
a = seg->box.zy;
|
a = seg->box.zy;
|
||||||
b = seg->box.xw;
|
b = seg->box.xw;
|
||||||
break;
|
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)
|
if(ccw(a, b, p) < 0)
|
||||||
{
|
{
|
||||||
// other side of the diagonal
|
// 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)
|
else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0)
|
||||||
{
|
{
|
||||||
// same side of the diagonal, but outside curve hull
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// inside curve hull
|
// inside curve hull
|
||||||
switch(seg->kind)
|
switch(seg->kind)
|
||||||
{
|
{
|
||||||
case MG_MTL_LINE:
|
case OC_MTL_LINE:
|
||||||
side = 1;
|
side = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_MTL_QUADRATIC:
|
case OC_MTL_QUADRATIC:
|
||||||
{
|
{
|
||||||
float3 ph = {p.x, p.y, 1};
|
float3 ph = {p.x, p.y, 1};
|
||||||
float3 klm = seg->implicitMatrix * ph;
|
float3 klm = seg->implicitMatrix * ph;
|
||||||
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
|
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MG_MTL_CUBIC:
|
case OC_MTL_CUBIC:
|
||||||
{
|
{
|
||||||
float3 ph = {p.x, p.y, 1};
|
float3 ph = {p.x, p.y, 1};
|
||||||
float3 klm = seg->implicitMatrix * ph;
|
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
|
typedef struct mtl_segment_setup_context
|
||||||
{
|
{
|
||||||
device atomic_int* segmentCount;
|
device atomic_int* segmentCount;
|
||||||
device mg_mtl_segment* segmentBuffer;
|
device oc_mtl_segment* segmentBuffer;
|
||||||
const device mg_mtl_path_queue* pathQueue;
|
const device oc_mtl_path_queue* pathQueue;
|
||||||
device mg_mtl_tile_queue* tileQueues;
|
device oc_mtl_tile_queue* tileQueues;
|
||||||
device mg_mtl_tile_op* tileOpBuffer;
|
device oc_mtl_tile_op* tileOpBuffer;
|
||||||
device atomic_int* tileOpCount;
|
device atomic_int* tileOpCount;
|
||||||
int tileSize;
|
int tileSize;
|
||||||
mtl_log_context log;
|
mtl_log_context log;
|
||||||
|
@ -390,7 +390,7 @@ typedef struct mtl_segment_setup_context
|
||||||
|
|
||||||
} 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
|
//NOTE: add segment index to the queues of tiles it overlaps with
|
||||||
int segIndex = seg - context->segmentBuffer;
|
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);
|
bool crossB = (sbl*sbr < 0);
|
||||||
|
|
||||||
float2 s0, s1;
|
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;
|
s0 = seg->box.xy;
|
||||||
s1 = seg->box.zw;
|
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)
|
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->index = segIndex;
|
||||||
op->crossRight = false;
|
op->crossRight = false;
|
||||||
op->next = -1;
|
op->next = -1;
|
||||||
|
|
||||||
int tileIndex = y*pathArea.z + x;
|
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);
|
op->next = atomic_exchange_explicit(&tile->first, tileOpIndex, memory_order_relaxed);
|
||||||
if(op->next == -1)
|
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;
|
float2 s, e, c;
|
||||||
|
|
||||||
switch(kind)
|
switch(kind)
|
||||||
{
|
{
|
||||||
case MG_MTL_LINE:
|
case OC_MTL_LINE:
|
||||||
s = p[0];
|
s = p[0];
|
||||||
c = p[0];
|
c = p[0];
|
||||||
e = p[1];
|
e = p[1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_MTL_QUADRATIC:
|
case OC_MTL_QUADRATIC:
|
||||||
s = p[0];
|
s = p[0];
|
||||||
c = p[1];
|
c = p[1];
|
||||||
e = p[2];
|
e = p[2];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MG_MTL_CUBIC:
|
case OC_MTL_CUBIC:
|
||||||
{
|
{
|
||||||
s = p[0];
|
s = p[0];
|
||||||
float sqrNorm0 = length_squared(p[1]-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;
|
} 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);
|
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(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)
|
else if(dy > alpha*dx)
|
||||||
{
|
{
|
||||||
seg->config = MG_MTL_TL;
|
seg->config = OC_MTL_TL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
seg->config = MG_MTL_BR;
|
seg->config = OC_MTL_BR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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)
|
else if(dy < ofs - alpha*dx)
|
||||||
{
|
{
|
||||||
seg->config = MG_MTL_BL;
|
seg->config = OC_MTL_BL;
|
||||||
}
|
}
|
||||||
else
|
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])
|
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)
|
if(seg)
|
||||||
{
|
{
|
||||||
seg->hullVertex = p[0];
|
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,
|
void mtl_quadratic_emit(thread mtl_segment_setup_context* context,
|
||||||
thread float2* p)
|
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)
|
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 e = p[1].x - p[0].x;
|
||||||
float f = p[0].x*p[1].y - p[1].x*p[0].y;
|
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));
|
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.},
|
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])
|
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)
|
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)]],
|
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 atomic_int* segmentCount [[buffer(2)]],
|
||||||
device mg_mtl_segment* segmentBuffer [[buffer(3)]],
|
device oc_mtl_segment* segmentBuffer [[buffer(3)]],
|
||||||
const device mg_mtl_path_queue* pathQueueBuffer [[buffer(4)]],
|
const device oc_mtl_path_queue* pathQueueBuffer [[buffer(4)]],
|
||||||
device mg_mtl_tile_queue* tileQueueBuffer [[buffer(5)]],
|
device oc_mtl_tile_queue* tileQueueBuffer [[buffer(5)]],
|
||||||
device mg_mtl_tile_op* tileOpBuffer [[buffer(6)]],
|
device oc_mtl_tile_op* tileOpBuffer [[buffer(6)]],
|
||||||
device atomic_int* tileOpCount [[buffer(7)]],
|
device atomic_int* tileOpCount [[buffer(7)]],
|
||||||
constant int* segmentMax [[buffer(8)]],
|
constant int* segmentMax [[buffer(8)]],
|
||||||
constant int* tileOpMax [[buffer(9)]],
|
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)]],
|
device atomic_int* logOffsetBuffer [[buffer(13)]],
|
||||||
uint eltIndex [[thread_position_in_grid]])
|
uint eltIndex [[thread_position_in_grid]])
|
||||||
{
|
{
|
||||||
const device mg_mtl_path_elt* elt = &elementBuffer[eltIndex];
|
const device oc_mtl_path_elt* elt = &elementBuffer[eltIndex];
|
||||||
const device mg_mtl_path_queue* pathQueue = &pathQueueBuffer[elt->pathIndex];
|
const device oc_mtl_path_queue* pathQueue = &pathQueueBuffer[elt->pathIndex];
|
||||||
device mg_mtl_tile_queue* tileQueues = &tileQueueBuffer[pathQueue->tileQueues];
|
device oc_mtl_tile_queue* tileQueues = &tileQueueBuffer[pathQueue->tileQueues];
|
||||||
|
|
||||||
mtl_segment_setup_context setupCtx = {.pathIndex = elt->pathIndex,
|
mtl_segment_setup_context setupCtx = {.pathIndex = elt->pathIndex,
|
||||||
.segmentCount = segmentCount,
|
.segmentCount = segmentCount,
|
||||||
|
@ -1289,7 +1289,7 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
||||||
|
|
||||||
switch(elt->kind)
|
switch(elt->kind)
|
||||||
{
|
{
|
||||||
case MG_MTL_LINE:
|
case OC_MTL_LINE:
|
||||||
{
|
{
|
||||||
float2 p[2] = {elt->p[0]*scale[0], elt->p[1]*scale[0]};
|
float2 p[2] = {elt->p[0]*scale[0], elt->p[1]*scale[0]};
|
||||||
mtl_log(setupCtx.log, "line: ");
|
mtl_log(setupCtx.log, "line: ");
|
||||||
|
@ -1297,7 +1297,7 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
||||||
mtl_line_setup(&setupCtx, p);
|
mtl_line_setup(&setupCtx, p);
|
||||||
} break;
|
} 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]};
|
float2 p[3] = {elt->p[0]*scale[0], elt->p[1]*scale[0], elt->p[2]*scale[0]};
|
||||||
mtl_log(setupCtx.log, "quadratic: ");
|
mtl_log(setupCtx.log, "quadratic: ");
|
||||||
|
@ -1305,7 +1305,7 @@ kernel void mtl_segment_setup(constant int* elementCount [[buffer(0)]],
|
||||||
mtl_quadratic_setup(&setupCtx, p);
|
mtl_quadratic_setup(&setupCtx, p);
|
||||||
} break;
|
} 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]};
|
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: ");
|
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)]],
|
kernel void mtl_backprop(const device oc_mtl_path_queue* pathQueueBuffer [[buffer(0)]],
|
||||||
device mg_mtl_tile_queue* tileQueueBuffer [[buffer(1)]],
|
device oc_mtl_tile_queue* tileQueueBuffer [[buffer(1)]],
|
||||||
device char* logBuffer [[buffer(2)]],
|
device char* logBuffer [[buffer(2)]],
|
||||||
device atomic_int* logOffsetBuffer [[buffer(3)]],
|
device atomic_int* logOffsetBuffer [[buffer(3)]],
|
||||||
uint pathIndex [[threadgroup_position_in_grid]],
|
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);
|
threadgroup_barrier(mem_flags::mem_threadgroup);
|
||||||
|
|
||||||
int rowIndex = 0;
|
int rowIndex = 0;
|
||||||
const device mg_mtl_path_queue* pathQueue = &pathQueueBuffer[pathIndex];
|
const device oc_mtl_path_queue* pathQueue = &pathQueueBuffer[pathIndex];
|
||||||
device mg_mtl_tile_queue* tiles = &tileQueueBuffer[pathQueue->tileQueues];
|
device oc_mtl_tile_queue* tiles = &tileQueueBuffer[pathQueue->tileQueues];
|
||||||
int rowSize = pathQueue->area.z;
|
int rowSize = pathQueue->area.z;
|
||||||
int rowCount = pathQueue->area.w;
|
int rowCount = pathQueue->area.w;
|
||||||
|
|
||||||
rowIndex = atomic_fetch_add_explicit(&nextRowIndex, 1, memory_order_relaxed);
|
rowIndex = atomic_fetch_add_explicit(&nextRowIndex, 1, memory_order_relaxed);
|
||||||
while(rowIndex < rowCount)
|
while(rowIndex < rowCount)
|
||||||
{
|
{
|
||||||
device mg_mtl_tile_queue* row = &tiles[rowIndex * rowSize];
|
device oc_mtl_tile_queue* row = &tiles[rowIndex * rowSize];
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for(int x = rowSize-1; x >= 0; x--)
|
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;
|
int offset = *(device int*)&tile->windingOffset;
|
||||||
*(device int*)(&tile->windingOffset) = sum;
|
*(device int*)(&tile->windingOffset) = sum;
|
||||||
sum += offset;
|
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)]],
|
kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
||||||
const device mg_mtl_path* pathBuffer [[buffer(1)]],
|
const device oc_mtl_path* pathBuffer [[buffer(1)]],
|
||||||
const device mg_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
const device oc_mtl_path_queue* pathQueueBuffer [[buffer(2)]],
|
||||||
const device mg_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
const device oc_mtl_tile_queue* tileQueueBuffer [[buffer(3)]],
|
||||||
device mg_mtl_tile_op* tileOpBuffer [[buffer(4)]],
|
device oc_mtl_tile_op* tileOpBuffer [[buffer(4)]],
|
||||||
device atomic_int* tileOpCount [[buffer(5)]],
|
device atomic_int* tileOpCount [[buffer(5)]],
|
||||||
device MTLDispatchThreadgroupsIndirectArguments* dispatchBuffer [[buffer(6)]],
|
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* tileOpMax [[buffer(8)]],
|
||||||
constant int* tileSize [[buffer(9)]],
|
constant int* tileSize [[buffer(9)]],
|
||||||
constant float* scale [[buffer(10)]],
|
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++)
|
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;
|
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);
|
float xMax = min(path->box.z, path->clip.z);
|
||||||
int tileMaxX = xMax * scale[0] / tileSize[0];
|
int tileMaxX = xMax * scale[0] / tileSize[0];
|
||||||
int pathTileMaxX = tileMaxX - pathQueue->area.x;
|
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;
|
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 windingOffset = atomic_load_explicit(&tileQueue->windingOffset, memory_order_relaxed);
|
||||||
int firstOpIndex = atomic_load_explicit(&tileQueue->first, 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
device mg_mtl_tile_op* pathOp = &tileOpBuffer[pathOpIndex];
|
device oc_mtl_tile_op* pathOp = &tileOpBuffer[pathOpIndex];
|
||||||
pathOp->kind = MG_MTL_OP_CLIP_FILL;
|
pathOp->kind = OC_MTL_OP_CLIP_FILL;
|
||||||
pathOp->next = -1;
|
pathOp->next = -1;
|
||||||
pathOp->index = pathIndex;
|
pathOp->index = pathIndex;
|
||||||
pathOp->windingOffset = windingOffset;
|
pathOp->windingOffset = windingOffset;
|
||||||
|
@ -1448,7 +1448,7 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
||||||
&& tileBox.y >= clip.y
|
&& tileBox.y >= clip.y
|
||||||
&& tileBox.w < clip.w)
|
&& 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)
|
if(pathBuffer[pathIndex].color.a == 1 && pathBuffer[pathIndex].texture < 0)
|
||||||
{
|
{
|
||||||
|
@ -1468,8 +1468,8 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
device mg_mtl_tile_op* startOp = &tileOpBuffer[startOpIndex];
|
device oc_mtl_tile_op* startOp = &tileOpBuffer[startOpIndex];
|
||||||
startOp->kind = MG_MTL_OP_START;
|
startOp->kind = OC_MTL_OP_START;
|
||||||
startOp->next = -1;
|
startOp->next = -1;
|
||||||
startOp->index = pathIndex;
|
startOp->index = pathIndex;
|
||||||
startOp->windingOffset = windingOffset;
|
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
|
//NOTE: chain remaining path ops to end of tile list
|
||||||
int lastOpIndex = tileQueue->last;
|
int lastOpIndex = tileQueue->last;
|
||||||
device mg_mtl_tile_op* lastOp = &tileOpBuffer[lastOpIndex];
|
device oc_mtl_tile_op* lastOp = &tileOpBuffer[lastOpIndex];
|
||||||
*nextLink = firstOpIndex;
|
*nextLink = firstOpIndex;
|
||||||
nextLink = &lastOp->next;
|
nextLink = &lastOp->next;
|
||||||
|
|
||||||
|
@ -1491,8 +1491,8 @@ kernel void mtl_merge(constant int* pathCount [[buffer(0)]],
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
device mg_mtl_tile_op* endOp = &tileOpBuffer[endOpIndex];
|
device oc_mtl_tile_op* endOp = &tileOpBuffer[endOpIndex];
|
||||||
endOp->kind = MG_MTL_OP_END;
|
endOp->kind = OC_MTL_OP_END;
|
||||||
endOp->next = -1;
|
endOp->next = -1;
|
||||||
endOp->index = pathIndex;
|
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)]],
|
kernel void mtl_raster(const device oc_mtl_screen_tile* screenTilesBuffer [[buffer(0)]],
|
||||||
const device mg_mtl_tile_op* tileOpBuffer [[buffer(1)]],
|
const device oc_mtl_tile_op* tileOpBuffer [[buffer(1)]],
|
||||||
const device mg_mtl_path* pathBuffer [[buffer(2)]],
|
const device oc_mtl_path* pathBuffer [[buffer(2)]],
|
||||||
const device mg_mtl_segment* segmentBuffer [[buffer(3)]],
|
const device oc_mtl_segment* segmentBuffer [[buffer(3)]],
|
||||||
constant int* tileSize [[buffer(4)]],
|
constant int* tileSize [[buffer(4)]],
|
||||||
constant float* scale [[buffer(5)]],
|
constant float* scale [[buffer(5)]],
|
||||||
constant int* sampleCountBuffer [[buffer(6)]],
|
constant int* sampleCountBuffer [[buffer(6)]],
|
||||||
device char* logBuffer [[buffer(7)]],
|
device char* logBuffer [[buffer(7)]],
|
||||||
device atomic_int* logOffsetBuffer [[buffer(8)]],
|
device atomic_int* logOffsetBuffer [[buffer(8)]],
|
||||||
texture2d<float, access::write> outTexture [[texture(0)]],
|
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 threadGroupCoord [[threadgroup_position_in_grid]],
|
||||||
uint2 localCoord [[thread_position_in_threadgroup]])
|
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;
|
int opIndex = screenTilesBuffer[tileIndex].first;
|
||||||
|
|
||||||
const int MG_MTL_MAX_SAMPLE_COUNT = 8;
|
const int OC_MTL_MAX_SAMPLE_COUNT = 8;
|
||||||
float2 sampleCoords[MG_MTL_MAX_SAMPLE_COUNT];
|
float2 sampleCoords[OC_MTL_MAX_SAMPLE_COUNT];
|
||||||
int sampleCount = sampleCountBuffer[0];
|
int sampleCount = sampleCountBuffer[0];
|
||||||
float2 centerCoord = float2(pixelCoord) + float2(0.5, 0.5);
|
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;
|
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 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),
|
||||||
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};
|
float4 color = {0};
|
||||||
int winding[MG_MTL_MAX_SAMPLE_COUNT] = {0};
|
int winding[OC_MTL_MAX_SAMPLE_COUNT] = {0};
|
||||||
|
|
||||||
while(opIndex != -1)
|
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;
|
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++)
|
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++)
|
||||||
{
|
{
|
||||||
winding[sampleIndex] = op->windingOffset;
|
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++)
|
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(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))
|
&&(sampleCoord.y > seg->box.w))
|
||||||
{
|
{
|
||||||
winding[sampleIndex] += seg->windingIncrement;
|
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))
|
&&(sampleCoord.y > seg->box.y))
|
||||||
{
|
{
|
||||||
winding[sampleIndex] -= seg->windingIncrement;
|
winding[sampleIndex] -= seg->windingIncrement;
|
||||||
|
@ -1611,7 +1611,7 @@ kernel void mtl_raster(const device mg_mtl_screen_tile* screenTilesBuffer [[buff
|
||||||
nextColor.rgb *= nextColor.a;
|
nextColor.rgb *= nextColor.a;
|
||||||
|
|
||||||
int textureIndex = pathBuffer[pathIndex].texture;
|
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);
|
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;
|
nextColor *= texColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(op->kind == MG_MTL_OP_FILL)
|
if(op->kind == OC_MTL_OP_FILL)
|
||||||
{
|
{
|
||||||
color = color*(1-nextColor.a) + nextColor;
|
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.y
|
||||||
&& sampleCoord.y < clip.w)
|
&& sampleCoord.y < clip.w)
|
||||||
{
|
{
|
||||||
bool filled = op->kind == MG_MTL_OP_CLIP_FILL
|
bool filled = op->kind == OC_MTL_OP_CLIP_FILL
|
||||||
||(pathBuffer[pathIndex].cmd == MG_MTL_FILL && (winding[sampleIndex] & 1))
|
||(pathBuffer[pathIndex].cmd == OC_MTL_FILL && (winding[sampleIndex] & 1))
|
||||||
||(pathBuffer[pathIndex].cmd == MG_MTL_STROKE && (winding[sampleIndex] != 0));
|
||(pathBuffer[pathIndex].cmd == OC_MTL_STROKE && (winding[sampleIndex] != 0));
|
||||||
if(filled)
|
if(filled)
|
||||||
{
|
{
|
||||||
coverage++;
|
coverage++;
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
#import<Metal/Metal.h>
|
#import<Metal/Metal.h>
|
||||||
#endif
|
#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* oc_mtl_surface_render_encoder(oc_surface surface);
|
||||||
void* mg_mtl_surface_compute_encoder(mg_surface surface);
|
void* oc_mtl_surface_compute_encoder(oc_surface surface);
|
||||||
void* mg_mtl_surface_layer(mg_surface surface);
|
void* oc_mtl_surface_layer(oc_surface surface);
|
||||||
void* mg_mtl_surface_drawable(mg_surface surface);
|
void* oc_mtl_surface_drawable(oc_surface surface);
|
||||||
void* mg_mtl_surface_command_buffer(mg_surface surface);
|
void* oc_mtl_surface_command_buffer(oc_surface surface);
|
||||||
|
|
||||||
#endif //__MTL_SURFACE_H_
|
#endif //__MTL_SURFACE_H_
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
#include<simd/simd.h>
|
#include<simd/simd.h>
|
||||||
|
|
||||||
#include"graphics_surface.h"
|
#include"graphics_surface.h"
|
||||||
#include"util/macro_helpers.h"
|
#include"util/macros.h"
|
||||||
#include"app/osx_app.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
|
// permanent mtl resources
|
||||||
id<MTLDevice> device;
|
id<MTLDevice> device;
|
||||||
|
@ -28,11 +28,11 @@ typedef struct mg_mtl_surface
|
||||||
id<CAMetalDrawable> drawable;
|
id<CAMetalDrawable> drawable;
|
||||||
id<MTLCommandBuffer> commandBuffer;
|
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
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
@ -48,10 +48,10 @@ void mg_mtl_surface_destroy(mg_surface_data* interface)
|
||||||
[surface->mtlLayer release];
|
[surface->mtlLayer release];
|
||||||
[surface->device 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)
|
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{
|
{@autoreleasepool{
|
||||||
/*WARN(martin):
|
/*WARN(martin):
|
||||||
//TODO: we should stop trying to render if we detect that the app is in the background
|
//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;
|
oc_mtl_surface* surface = (oc_mtl_surface*)interface;
|
||||||
mg_mtl_surface_acquire_command_buffer(surface);
|
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
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
if(surface->commandBuffer != nil)
|
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
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
[surface->mtlLayer setDisplaySyncEnabled: (swap ? YES : NO)];
|
[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;
|
oc_mtl_surface* surface = (oc_mtl_surface*)interface;
|
||||||
mg_osx_surface_set_frame(interface, frame);
|
oc_osx_surface_set_frame(interface, frame);
|
||||||
vec2 scale = mg_osx_surface_contents_scaling(interface);
|
oc_vec2 scale = oc_osx_surface_contents_scaling(interface);
|
||||||
|
|
||||||
CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}};
|
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
|
//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).
|
//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
|
// 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;
|
oc_mtl_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)
|
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
|
//NOTE(martin): setup interface functions
|
||||||
surface->interface.api = MG_METAL;
|
surface->interface.api = OC_METAL;
|
||||||
surface->interface.destroy = mg_mtl_surface_destroy;
|
surface->interface.destroy = oc_mtl_surface_destroy;
|
||||||
surface->interface.prepare = mg_mtl_surface_prepare;
|
surface->interface.prepare = oc_mtl_surface_prepare;
|
||||||
surface->interface.deselect = 0;
|
surface->interface.deselect = 0;
|
||||||
surface->interface.present = mg_mtl_surface_present;
|
surface->interface.present = oc_mtl_surface_present;
|
||||||
surface->interface.swapInterval = mg_mtl_surface_swap_interval;
|
surface->interface.swapInterval = oc_mtl_surface_swap_interval;
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
@ -191,7 +191,7 @@ mg_surface_data* mg_mtl_surface_create_for_window(mp_window window)
|
||||||
}
|
}
|
||||||
if(surface->device == nil)
|
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];
|
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];
|
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
|
||||||
CGSize size = frame.size;
|
CGSize size = frame.size;
|
||||||
surface->mtlLayer.frame = (CGRect){{0, 0}, size};
|
surface->mtlLayer.frame = (CGRect){{0, 0}, size};
|
||||||
size.width *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
size.width *= OC_MTL_SURFACE_CONTENTS_SCALING;
|
||||||
size.height *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
size.height *= OC_MTL_SURFACE_CONTENTS_SCALING;
|
||||||
surface->mtlLayer.drawableSize = size;
|
surface->mtlLayer.drawableSize = size;
|
||||||
surface->mtlLayer.contentsScale = MG_MTL_SURFACE_CONTENTS_SCALING;
|
surface->mtlLayer.contentsScale = OC_MTL_SURFACE_CONTENTS_SCALING;
|
||||||
|
|
||||||
surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
|
|
||||||
|
@ -234,15 +234,15 @@ mg_surface_data* mg_mtl_surface_create_for_window(mp_window window)
|
||||||
surface->commandBuffer = nil;
|
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);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->api == MG_METAL)
|
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);
|
return(mtlSurface->mtlLayer);
|
||||||
}
|
}
|
||||||
else
|
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);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->api == MG_METAL)
|
if(surfaceData && surfaceData->api == OC_METAL)
|
||||||
{
|
{
|
||||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
|
||||||
mg_mtl_surface_acquire_drawable(mtlSurface);
|
oc_mtl_surface_acquire_drawable(mtlSurface);
|
||||||
return(mtlSurface->drawable);
|
return(mtlSurface->drawable);
|
||||||
}
|
}
|
||||||
else
|
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);
|
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
|
||||||
if(surfaceData && surfaceData->api == MG_METAL)
|
if(surfaceData && surfaceData->api == OC_METAL)
|
||||||
{
|
{
|
||||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
|
||||||
mg_mtl_surface_acquire_command_buffer(mtlSurface);
|
oc_mtl_surface_acquire_command_buffer(mtlSurface);
|
||||||
return(mtlSurface->commandBuffer);
|
return(mtlSurface->commandBuffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -11,42 +11,42 @@
|
||||||
#include"gl_loader.h"
|
#include"gl_loader.h"
|
||||||
|
|
||||||
#include<GL/wglext.h>
|
#include<GL/wglext.h>
|
||||||
#include"util/macro_helpers.h"
|
#include"util/macros.h"
|
||||||
|
|
||||||
#define WGL_PROC_LIST \
|
#define OC_WGL_PROC_LIST \
|
||||||
WGL_PROC(WGLCHOOSEPIXELFORMATARB, wglChoosePixelFormatARB) \
|
OC_WGL_PROC(WGLCHOOSEPIXELFORMATARB, wglChoosePixelFormatARB) \
|
||||||
WGL_PROC(WGLCREATECONTEXTATTRIBSARB, wglCreateContextAttribsARB) \
|
OC_WGL_PROC(WGLCREATECONTEXTATTRIBSARB, wglCreateContextAttribsARB) \
|
||||||
WGL_PROC(WGLMAKECONTEXTCURRENTARB, wglMakeContextCurrentARB) \
|
OC_WGL_PROC(WGLMAKECONTEXTCURRENTARB, wglMakeContextCurrentARB) \
|
||||||
WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT) \
|
OC_WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT) \
|
||||||
|
|
||||||
//NOTE: wgl function pointers declarations
|
//NOTE: wgl function pointers declarations
|
||||||
|
|
||||||
#define WGL_PROC(type, name) _cat3_(PFN, type, PROC) name = 0;
|
#define OC_WGL_PROC(type, name) OC_CAT3(PFN, type, PROC) name = 0;
|
||||||
WGL_PROC_LIST
|
OC_WGL_PROC_LIST
|
||||||
#undef WGL_PROC
|
#undef OC_WGL_PROC
|
||||||
|
|
||||||
//NOTE: wgl loader
|
//NOTE: wgl loader
|
||||||
|
|
||||||
typedef struct wgl_dummy_context
|
typedef struct oc_wgl_dummy_context
|
||||||
{
|
{
|
||||||
bool init;
|
bool init;
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
HDC hDC;
|
HDC hDC;
|
||||||
HGLRC glContext;
|
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
|
//NOTE: create a dummy window
|
||||||
WNDCLASS windowClass = {.style = CS_OWNDC,
|
WNDCLASS windowClass = {.style = CS_OWNDC,
|
||||||
.lpfnWndProc = DefWindowProc,
|
.lpfnWndProc = DefWindowProc,
|
||||||
.hInstance = GetModuleHandleW(NULL),
|
.hInstance = GetModuleHandleW(NULL),
|
||||||
.lpszClassName = "wgl_helper_window_class",
|
.lpszClassName = "oc_wgl_helper_window_class",
|
||||||
.hCursor = LoadCursor(0, IDC_ARROW)};
|
.hCursor = LoadCursor(0, IDC_ARROW)};
|
||||||
|
|
||||||
if(!RegisterClass(&windowClass))
|
if(!RegisterClass(&windowClass))
|
||||||
|
@ -55,18 +55,18 @@ static void wgl_init()
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
__mgWGLDummyContext.hWnd = CreateWindow("wgl_helper_window_class",
|
oc_wglDummyContext.hWnd = CreateWindow("oc_wgl_helper_window_class",
|
||||||
"dummy",
|
"dummy",
|
||||||
WS_OVERLAPPEDWINDOW,
|
WS_OVERLAPPEDWINDOW,
|
||||||
0, 0, 100, 100,
|
0, 0, 100, 100,
|
||||||
0, 0, windowClass.hInstance, 0);
|
0, 0, windowClass.hInstance, 0);
|
||||||
|
|
||||||
if(!__mgWGLDummyContext.hWnd)
|
if(!oc_wglDummyContext.hWnd)
|
||||||
{
|
{
|
||||||
//TODO: error
|
//TODO: error
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
__mgWGLDummyContext.hDC = GetDC(__mgWGLDummyContext.hWnd);
|
oc_wglDummyContext.hDC = GetDC(oc_wglDummyContext.hWnd);
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pixelFormatDesc =
|
PIXELFORMATDESCRIPTOR pixelFormatDesc =
|
||||||
{
|
{
|
||||||
|
@ -88,44 +88,44 @@ static void wgl_init()
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
int pixelFormat = ChoosePixelFormat(__mgWGLDummyContext.hDC, &pixelFormatDesc);
|
int pixelFormat = ChoosePixelFormat(oc_wglDummyContext.hDC, &pixelFormatDesc);
|
||||||
SetPixelFormat(__mgWGLDummyContext.hDC, pixelFormat, &pixelFormatDesc);
|
SetPixelFormat(oc_wglDummyContext.hDC, pixelFormat, &pixelFormatDesc);
|
||||||
|
|
||||||
__mgWGLDummyContext.glContext = wglCreateContext(__mgWGLDummyContext.hDC);
|
oc_wglDummyContext.glContext = wglCreateContext(oc_wglDummyContext.hDC);
|
||||||
wglMakeCurrent(__mgWGLDummyContext.hDC, __mgWGLDummyContext.glContext);
|
wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext);
|
||||||
|
|
||||||
//NOTE(martin): now load WGL extension functions
|
//NOTE(martin): now load WGL extension functions
|
||||||
#define WGL_PROC(type, name) name = (_cat3_(PFN, type, PROC))wglGetProcAddress( #name );
|
#define OC_WGL_PROC(type, name) name = (OC_CAT3(PFN, type, PROC))wglGetProcAddress( #name );
|
||||||
WGL_PROC_LIST
|
OC_WGL_PROC_LIST
|
||||||
#undef WGL_PROC
|
#undef OC_WGL_PROC
|
||||||
|
|
||||||
__mgWGLDummyContext.init = true;
|
oc_wglDummyContext.init = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wglMakeCurrent(__mgWGLDummyContext.hDC, __mgWGLDummyContext.glContext);
|
wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext);
|
||||||
}
|
}
|
||||||
quit:;
|
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;
|
HDC hDC;
|
||||||
HGLRC glContext;
|
HGLRC glContext;
|
||||||
|
|
||||||
//NOTE: this may be a bit wasteful to have one api struct per surface, but win32 docs says that loading procs
|
//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)
|
// from different contexts might select different implementations (eg. depending on context version/pixel format)
|
||||||
mg_gl_api api;
|
oc_gl_api api;
|
||||||
} mg_wgl_surface;
|
} 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())
|
if(surface->glContext == wglGetCurrentContext())
|
||||||
{
|
{
|
||||||
|
@ -133,39 +133,39 @@ void mg_wgl_surface_destroy(mg_surface_data* interface)
|
||||||
}
|
}
|
||||||
wglDeleteContext(surface->glContext);
|
wglDeleteContext(surface->glContext);
|
||||||
|
|
||||||
mg_surface_cleanup(interface);
|
oc_surface_cleanup(interface);
|
||||||
|
|
||||||
free(surface);
|
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);
|
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);
|
SwapBuffers(surface->hDC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_wgl_surface_deselect(mg_surface_data* interface)
|
void oc_wgl_surface_deselect(oc_surface_data* interface)
|
||||||
{
|
{
|
||||||
wglMakeCurrent(NULL, NULL);
|
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);
|
wglSwapIntervalEXT(swap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* mg_wgl_get_proc(const char* name)
|
void* oc_wgl_get_proc(const char* name)
|
||||||
{
|
{
|
||||||
void* p = wglGetProcAddress(name);
|
void* p = wglGetProcAddress(name);
|
||||||
if( p == 0
|
if( p == 0
|
||||||
|
@ -181,28 +181,28 @@ void* mg_wgl_get_proc(const char* name)
|
||||||
return(p);
|
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)
|
if(windowData)
|
||||||
{
|
{
|
||||||
wgl_init();
|
oc_wgl_init();
|
||||||
|
|
||||||
//NOTE: fill surface data and load api
|
//NOTE: fill surface data and load api
|
||||||
surface = malloc_type(mg_wgl_surface);
|
surface = oc_malloc_type(oc_wgl_surface);
|
||||||
if(surface)
|
if(surface)
|
||||||
{
|
{
|
||||||
memset(surface, 0, sizeof(mg_wgl_surface));
|
memset(surface, 0, sizeof(oc_wgl_surface));
|
||||||
mg_surface_init_for_window((mg_surface_data*)surface, windowData);
|
oc_surface_init_for_window((oc_surface_data*)surface, windowData);
|
||||||
|
|
||||||
surface->interface.api = MG_GL;
|
surface->interface.api = OC_GL;
|
||||||
surface->interface.destroy = mg_wgl_surface_destroy;
|
surface->interface.destroy = oc_wgl_surface_destroy;
|
||||||
surface->interface.prepare = mg_wgl_surface_prepare;
|
surface->interface.prepare = oc_wgl_surface_prepare;
|
||||||
surface->interface.present = mg_wgl_surface_present;
|
surface->interface.present = oc_wgl_surface_present;
|
||||||
surface->interface.swapInterval = mg_wgl_surface_swap_interval;
|
surface->interface.swapInterval = oc_wgl_surface_swap_interval;
|
||||||
surface->interface.deselect = mg_wgl_surface_deselect;
|
surface->interface.deselect = oc_wgl_surface_deselect;
|
||||||
|
|
||||||
surface->hDC = GetDC(surface->interface.layer.hWnd);
|
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,
|
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||||
0};
|
0};
|
||||||
|
|
||||||
surface->glContext = wglCreateContextAttribsARB(surface->hDC, __mgWGLDummyContext.glContext, contextAttrs);
|
surface->glContext = wglCreateContextAttribsARB(surface->hDC, oc_wglDummyContext.glContext, contextAttrs);
|
||||||
|
|
||||||
if(!surface->glContext)
|
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
|
//NOTE: make gl context current and load api
|
||||||
wglMakeCurrent(surface->hDC, surface->glContext);
|
wglMakeCurrent(surface->hDC, surface->glContext);
|
||||||
wglSwapIntervalEXT(1);
|
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"
|
#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_
|
#endif // __WIN32_GL_SURFACE_H_
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define assert(x) (void)0
|
#define assert(x) (void)0
|
||||||
#else
|
#else
|
||||||
#define assert(x) ASSERT(x)
|
#define assert(x) OC_ASSERT(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define abort(...) ORCA_ABORT(__VA_ARGS__)
|
#define abort(...) OC_ABORT(__VA_ARGS__)
|
||||||
|
|
||||||
int abs (int);
|
int abs (int);
|
||||||
|
|
||||||
|
|
21
src/orca.c
21
src/orca.c
|
@ -12,7 +12,7 @@
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
#include"platform/platform.h"
|
#include"platform/platform.h"
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if OC_PLATFORM_WINDOWS
|
||||||
#include"platform/native_debug.c"
|
#include"platform/native_debug.c"
|
||||||
#include"platform/win32_memory.c"
|
#include"platform/win32_memory.c"
|
||||||
#include"platform/win32_clock.c"
|
#include"platform/win32_clock.c"
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
#include"platform/win32_io.c"
|
#include"platform/win32_io.c"
|
||||||
#include"platform/win32_thread.c"
|
#include"platform/win32_thread.c"
|
||||||
//TODO
|
//TODO
|
||||||
#elif PLATFORM_MACOS
|
#elif OC_PLATFORM_MACOS
|
||||||
#include"platform/native_debug.c"
|
#include"platform/native_debug.c"
|
||||||
#include"platform/unix_memory.c"
|
#include"platform/unix_memory.c"
|
||||||
#include"platform/osx_clock.c"
|
#include"platform/osx_clock.c"
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
#include"platform/unix_rng.c"
|
#include"platform/unix_rng.c"
|
||||||
#include"platform/posix_socket.c"
|
#include"platform/posix_socket.c"
|
||||||
*/
|
*/
|
||||||
#elif PLATFORM_ORCA
|
#elif OC_PLATFORM_ORCA
|
||||||
#include"platform/orca_debug.c"
|
#include"platform/orca_debug.c"
|
||||||
#include"platform/orca_clock.c"
|
#include"platform/orca_clock.c"
|
||||||
#include"platform/orca_memory.c"
|
#include"platform/orca_memory.c"
|
||||||
|
@ -62,35 +62,36 @@
|
||||||
#include"util/utf8.c"
|
#include"util/utf8.c"
|
||||||
#include"util/hash.c"
|
#include"util/hash.c"
|
||||||
#include"util/ringbuffer.c"
|
#include"util/ringbuffer.c"
|
||||||
|
#include"util/algebra.c"
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// app/graphics layer
|
// app/graphics layer
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if OC_PLATFORM_WINDOWS
|
||||||
#include"app/win32_app.c"
|
#include"app/win32_app.c"
|
||||||
#include"graphics/graphics_common.c"
|
#include"graphics/graphics_common.c"
|
||||||
#include"graphics/graphics_surface.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"
|
#include"graphics/gl_loader.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_GL
|
#if OC_COMPILE_GL
|
||||||
#include"graphics/wgl_surface.c"
|
#include"graphics/wgl_surface.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
#if OC_COMPILE_CANVAS
|
||||||
#include"graphics/gl_canvas.c"
|
#include"graphics/gl_canvas.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
#if OC_COMPILE_GLES
|
||||||
#include"graphics/egl_surface.c"
|
#include"graphics/egl_surface.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif PLATFORM_MACOS
|
#elif OC_PLATFORM_MACOS
|
||||||
//NOTE: macos application layer and graphics backends are defined in orca.m
|
//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"app/orca_app.c"
|
||||||
#include"graphics/graphics_common.c"
|
#include"graphics/graphics_common.c"
|
||||||
#include"graphics/orca_surface_stubs.c"
|
#include"graphics/orca_surface_stubs.c"
|
||||||
|
|
15
src/orca.h
15
src/orca.h
|
@ -10,39 +10,40 @@
|
||||||
#define __ORCA_H_
|
#define __ORCA_H_
|
||||||
|
|
||||||
#include"util/typedefs.h"
|
#include"util/typedefs.h"
|
||||||
#include"util/macro_helpers.h"
|
#include"util/macros.h"
|
||||||
#include"util/debug.h"
|
#include"util/debug.h"
|
||||||
#include"util/lists.h"
|
#include"util/lists.h"
|
||||||
#include"util/memory.h"
|
#include"util/memory.h"
|
||||||
#include"util/strings.h"
|
#include"util/strings.h"
|
||||||
#include"util/utf8.h"
|
#include"util/utf8.h"
|
||||||
#include"util/hash.h"
|
#include"util/hash.h"
|
||||||
|
#include"util/algebra.h"
|
||||||
|
|
||||||
#include"platform/platform.h"
|
#include"platform/platform.h"
|
||||||
#include"platform/platform_clock.h"
|
#include"platform/platform_clock.h"
|
||||||
#include"platform/platform_path.h"
|
#include"platform/platform_path.h"
|
||||||
#include"platform/platform_io.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"
|
#include"platform/platform_thread.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include"app/mp_app.h"
|
#include"app/app.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// graphics
|
// graphics
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
#include"graphics/graphics.h"
|
#include"graphics/graphics.h"
|
||||||
|
|
||||||
#if PLATFORM_ORCA
|
#if OC_PLATFORM_ORCA
|
||||||
//TODO: maybe make this conditional
|
//TODO: maybe make this conditional
|
||||||
#include"graphics/orca_gl31.h"
|
#include"graphics/orca_gl31.h"
|
||||||
|
|
||||||
mg_surface mg_surface_canvas();
|
oc_surface oc_surface_canvas();
|
||||||
mg_surface mg_surface_gles();
|
oc_surface oc_surface_gles();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifdef MG_INCLUDE_GL_API
|
#ifdef OC_INCLUDE_GL_API
|
||||||
#include"graphics/gl_api.h"
|
#include"graphics/gl_api.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,15 +12,15 @@
|
||||||
#include"graphics/graphics_common.c"
|
#include"graphics/graphics_common.c"
|
||||||
#include"graphics/graphics_surface.c"
|
#include"graphics/graphics_surface.c"
|
||||||
|
|
||||||
#if MG_COMPILE_METAL
|
#if OC_COMPILE_METAL
|
||||||
#include"graphics/mtl_surface.m"
|
#include"graphics/mtl_surface.m"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
#if OC_COMPILE_CANVAS
|
||||||
#include"graphics/mtl_renderer.m"
|
#include"graphics/mtl_renderer.m"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
#if OC_COMPILE_GLES
|
||||||
#include"graphics/gl_loader.c"
|
#include"graphics/gl_loader.c"
|
||||||
#include"graphics/egl_surface.c"
|
#include"graphics/egl_surface.c"
|
||||||
#endif
|
#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<stdio.h>
|
||||||
|
|
||||||
#include"app/mp_app.h"
|
#include"app/app.h"
|
||||||
#include"platform_debug.c"
|
#include"platform_debug.c"
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Logging
|
// Logging
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if OC_PLATFORM_WINDOWS
|
||||||
#include<io.h>
|
#include<io.h>
|
||||||
#define isatty _isatty
|
#define isatty _isatty
|
||||||
#define fileno _fileno
|
#define fileno _fileno
|
||||||
#elif PLATFORM_MACOS || PLATFORM_LINUX
|
#elif OC_PLATFORM_MACOS || PLATFORM_LINUX
|
||||||
#include<unistd.h>
|
#include<unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char* LOG_HEADINGS[LOG_LEVEL_COUNT] = {
|
static const char* OC_LOG_HEADINGS[OC_LOG_LEVEL_COUNT] = {
|
||||||
"Error",
|
"Error",
|
||||||
"Warning",
|
"Warning",
|
||||||
"Info"};
|
"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;9m\033[1m",
|
||||||
"\033[38;5;13m\033[1m",
|
"\033[38;5;13m\033[1m",
|
||||||
"\033[38;5;10m\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;
|
FILE* f;
|
||||||
} log_output;
|
} oc_log_output;
|
||||||
|
|
||||||
static log_output _logDefaultOutput = {0};
|
static oc_log_output oc_logDefaultOutput = {0};
|
||||||
log_output* LOG_DEFAULT_OUTPUT = &_logDefaultOutput;
|
oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput;
|
||||||
|
|
||||||
void platform_log_push(log_output* output,
|
void platform_log_push(oc_log_output* output,
|
||||||
log_level level,
|
oc_log_level level,
|
||||||
const char* file,
|
const char* file,
|
||||||
const char* function,
|
const char* function,
|
||||||
int line,
|
int line,
|
||||||
const char* fmt,
|
const char* fmt,
|
||||||
va_list ap)
|
va_list ap)
|
||||||
{
|
{
|
||||||
if(output == LOG_DEFAULT_OUTPUT && output->f == 0)
|
if(output == OC_LOG_DEFAULT_OUTPUT && output->f == 0)
|
||||||
{
|
{
|
||||||
output->f = stdout;
|
output->f = stdout;
|
||||||
}
|
}
|
||||||
|
@ -59,9 +59,9 @@ void platform_log_push(log_output* output,
|
||||||
{
|
{
|
||||||
fprintf(output->f,
|
fprintf(output->f,
|
||||||
"%s%s:%s %s() in %s:%i: ",
|
"%s%s:%s %s() in %s:%i: ",
|
||||||
LOG_FORMATS[level],
|
OC_LOG_FORMATS[level],
|
||||||
LOG_HEADINGS[level],
|
OC_LOG_HEADINGS[level],
|
||||||
LOG_FORMAT_STOP,
|
OC_LOG_FORMAT_STOP,
|
||||||
function,
|
function,
|
||||||
file,
|
file,
|
||||||
line);
|
line);
|
||||||
|
@ -70,7 +70,7 @@ void platform_log_push(log_output* output,
|
||||||
{
|
{
|
||||||
fprintf(output->f,
|
fprintf(output->f,
|
||||||
"%s: %s() in %s:%i: ",
|
"%s: %s() in %s:%i: ",
|
||||||
LOG_HEADINGS[level],
|
OC_LOG_HEADINGS[level],
|
||||||
function,
|
function,
|
||||||
file,
|
file,
|
||||||
line);
|
line);
|
||||||
|
@ -82,16 +82,16 @@ void platform_log_push(log_output* output,
|
||||||
// Assert/Abort
|
// 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_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
str8 note = str8_pushfv(scratch, fmt, ap);
|
oc_str8 note = oc_str8_pushfv(scratch, fmt, ap);
|
||||||
va_end(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",
|
"Fatal error in function %s() in file \"%s\", line %i:\n%.*s\n",
|
||||||
function,
|
function,
|
||||||
file,
|
file,
|
||||||
|
@ -99,38 +99,40 @@ _Noreturn void orca_abort(const char* file, const char* function, int line, cons
|
||||||
(int)note.len,
|
(int)note.len,
|
||||||
note.ptr);
|
note.ptr);
|
||||||
|
|
||||||
const char* msgCStr = str8_to_cstring(scratch, msg);
|
oc_log_error(msg.ptr);
|
||||||
log_error(msgCStr);
|
|
||||||
|
|
||||||
const char* options[] = {"OK"};
|
oc_str8_list options = {0};
|
||||||
mp_alert_popup("Fatal Error", msgCStr, 1, options);
|
oc_str8_list_push(scratch, &options, OC_STR8("OK"));
|
||||||
|
|
||||||
|
oc_alert_popup(OC_STR8("Fatal Error"), msg, options);
|
||||||
|
|
||||||
//TODO: could terminate more gracefully?
|
//TODO: could terminate more gracefully?
|
||||||
exit(-1);
|
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_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
str8 note = str8_pushfv(scratch, fmt, ap);
|
oc_str8 note = oc_str8_pushfv(scratch, fmt, ap);
|
||||||
va_end(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",
|
"Assertion failed in function %s() in file \"%s\", line %i:\n%s\nNote: %.*s\n",
|
||||||
function,
|
function,
|
||||||
file,
|
file,
|
||||||
line,
|
line,
|
||||||
src,
|
src,
|
||||||
str8_ip(note));
|
oc_str8_ip(note));
|
||||||
|
|
||||||
const char* msgCStr = str8_to_cstring(scratch, msg);
|
oc_log_error(msg.ptr);
|
||||||
log_error(msgCStr);
|
|
||||||
|
|
||||||
const char* options[] = {"OK"};
|
oc_str8_list options = {0};
|
||||||
mp_alert_popup("Assertion Failed", msgCStr, 1, options);
|
oc_str8_list_push(scratch, &options, OC_STR8("OK"));
|
||||||
|
|
||||||
|
oc_alert_popup(OC_STR8("Assertion Failed"), msg, options);
|
||||||
|
|
||||||
//TODO: could terminate more gracefully?
|
//TODO: could terminate more gracefully?
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include"util/typedefs.h"
|
#include"util/typedefs.h"
|
||||||
#include"platform_clock.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
|
// stb sprintf callback and user struct
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct orca_stbsp_context
|
typedef struct oc_stbsp_context
|
||||||
{
|
{
|
||||||
mem_arena* arena;
|
oc_arena* arena;
|
||||||
str8_list list;
|
oc_str8_list list;
|
||||||
} orca_stbsp_context;
|
} 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);
|
oc_str8 string = oc_str8_push_buffer(ctx->arena, len, (char*)buf);
|
||||||
str8_list_push(ctx->arena, &ctx->list, string);
|
oc_str8_list_push(ctx->arena, &ctx->list, string);
|
||||||
|
|
||||||
return((char*)buf);
|
return((char*)buf);
|
||||||
}
|
}
|
||||||
|
@ -39,18 +39,18 @@ typedef enum
|
||||||
{
|
{
|
||||||
ORCA_LOG_OUTPUT_CONSOLE,
|
ORCA_LOG_OUTPUT_CONSOLE,
|
||||||
ORCA_LOG_OUTPUT_FILE
|
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
|
//TODO: file output
|
||||||
} log_output;
|
} oc_log_output;
|
||||||
|
|
||||||
static log_output _logDefaultOutput = {.kind = ORCA_LOG_OUTPUT_CONSOLE};
|
static oc_log_output oc_logDefaultOutput = {.kind = ORCA_LOG_OUTPUT_CONSOLE};
|
||||||
log_output* LOG_DEFAULT_OUTPUT = &_logDefaultOutput;
|
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,
|
int fileLen,
|
||||||
const char* file,
|
const char* file,
|
||||||
int functionLen,
|
int functionLen,
|
||||||
|
@ -59,42 +59,42 @@ void ORCA_IMPORT(orca_log)(log_level level,
|
||||||
int msgLen,
|
int msgLen,
|
||||||
const char* msg);
|
const char* msg);
|
||||||
|
|
||||||
void platform_log_push(log_output* output,
|
void platform_log_push(oc_log_output* output,
|
||||||
log_level level,
|
oc_log_level level,
|
||||||
const char* file,
|
const char* file,
|
||||||
const char* function,
|
const char* function,
|
||||||
int line,
|
int line,
|
||||||
const char* fmt,
|
const char* fmt,
|
||||||
va_list ap)
|
va_list ap)
|
||||||
{
|
{
|
||||||
mem_arena* scratch = mem_scratch();
|
oc_arena* scratch = oc_scratch();
|
||||||
mem_arena_scope tmp = mem_arena_scope_begin(scratch);
|
oc_arena_scope tmp = oc_arena_scope_begin(scratch);
|
||||||
|
|
||||||
orca_stbsp_context ctx = {.arena = scratch,
|
oc_stbsp_context ctx = {.arena = scratch,
|
||||||
.list = {0}};
|
.list = {0}};
|
||||||
|
|
||||||
char buf[STB_SPRINTF_MIN];
|
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
|
// Assert/Abort
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
_Noreturn void ORCA_IMPORT(orca_runtime_abort)(const char* file, const char* function, int line, 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(orca_runtime_assert_fail)(const char* file, const char* function, int line, const char* src, 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,
|
.arena = scratch.arena,
|
||||||
.list = {0}
|
.list = {0}
|
||||||
};
|
};
|
||||||
|
@ -103,22 +103,22 @@ _Noreturn void orca_abort(const char* file, const char* function, int line, cons
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|
||||||
char buf[STB_SPRINTF_MIN];
|
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);
|
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,
|
.arena = scratch.arena,
|
||||||
.list = {0}
|
.list = {0}
|
||||||
};
|
};
|
||||||
|
@ -127,13 +127,13 @@ _Noreturn void orca_assert_fail(const char* file, const char* function, int line
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|
||||||
char buf[STB_SPRINTF_MIN];
|
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);
|
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_UNISTD_H
|
||||||
#define LACKS_SYS_PARAM_H
|
#define LACKS_SYS_PARAM_H
|
||||||
|
|
||||||
extern void* orca_mem_grow(u64 size);
|
extern void* oc_mem_grow(u64 size);
|
||||||
#define MORECORE orca_mem_grow
|
#define MORECORE oc_mem_grow
|
||||||
#define MORECORE_CONTIGUOUS 0
|
#define MORECORE_CONTIGUOUS 0
|
||||||
/*
|
/*
|
||||||
This is a version (aka dlmalloc) of malloc/free/realloc written by
|
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
|
* Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
|
||||||
memory allocation routines
|
memory allocation routines
|
||||||
* Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
|
* 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
|
usage of 'assert' in non-WIN32 code
|
||||||
* Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
|
* Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
|
||||||
avoid infinite loop
|
avoid infinite loop
|
||||||
|
|
|
@ -8,24 +8,24 @@
|
||||||
|
|
||||||
#include"platform_memory.h"
|
#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)
|
if(base.reserve == 0)
|
||||||
{
|
{
|
||||||
base.reserve = orca_mem_base_reserve;
|
base.reserve = orca_oc_base_reserve;
|
||||||
base.commit = orca_mem_base_nop;
|
base.commit = orca_oc_base_nop;
|
||||||
base.decommit = orca_mem_base_nop;
|
base.decommit = orca_oc_base_nop;
|
||||||
base.release = orca_mem_base_nop;
|
base.release = orca_oc_base_nop;
|
||||||
}
|
}
|
||||||
return(&base);
|
return(&base);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
#include<sys/types.h>
|
#include<sys/types.h>
|
||||||
#include<sys/sysctl.h>
|
#include<sys/sysctl.h>
|
||||||
|
|
||||||
#include<unistd.h> // nanosleep()
|
|
||||||
|
|
||||||
#include"platform_clock.h"
|
#include"platform_clock.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,8 +25,8 @@ typedef struct timeval timeval;
|
||||||
typedef struct timespec timespec;
|
typedef struct timespec timespec;
|
||||||
|
|
||||||
//TODO(martin): measure the actual values of these constants
|
//TODO(martin): measure the actual values of these constants
|
||||||
const f64 SYSTEM_FUZZ = 25e-9, // minimum time to read the clock (s)
|
const f64 OC_CLOCK_FUZZ = 25e-9, // minimum time to read the clock (s)
|
||||||
SYSTEM_TICK = 25e-9; // minimum step between two clock readings (s)
|
OC_CLOCK_TICK = 25e-9; // minimum step between two clock readings (s)
|
||||||
|
|
||||||
static mach_timebase_info_data_t __machTimeBase__ = {1,1};
|
static mach_timebase_info_data_t __machTimeBase__ = {1,1};
|
||||||
static u64 __initialTimestamp__ = 0;
|
static u64 __initialTimestamp__ = 0;
|
||||||
|
@ -45,9 +43,9 @@ static inline u64 OSXGetUptimeNanoseconds()
|
||||||
|
|
||||||
static inline u64 OSXGetMonotonicNanoseconds()
|
static inline u64 OSXGetMonotonicNanoseconds()
|
||||||
{
|
{
|
||||||
//NOTE(martin): according to the documentation, MP_CLOCK_MONOTONIC increment monotonically
|
//NOTE(martin): according to the documentation, OC_CLOCK_MONOTONIC increment monotonically
|
||||||
// on systems where MP_CLOCK_MONOTONIC_RAW is present, we may want to use that instead,
|
// on systems where OC_CLOCK_MONOTONIC_RAW is present, we may want to use that instead,
|
||||||
// because MP_CLOCK_MONOTONIC seems to be subject to frequency changes ?
|
// because OC_CLOCK_MONOTONIC seems to be subject to frequency changes ?
|
||||||
|
|
||||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
||||||
#ifndef CLOCK_MONOTONIC_RAW
|
#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 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
|
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__);
|
mach_timebase_info(&__machTimeBase__);
|
||||||
|
|
||||||
|
@ -78,7 +76,7 @@ void mp_clock_init()
|
||||||
|
|
||||||
if(sysctl(mib, 2, &tv, &size, 0, 0) == -1)
|
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
|
//NOTE(martin): convert boot date to timestamp
|
||||||
__initialTimestamp__ = (((u64)tv.tv_sec + CLK_JAN_1970) << 32)
|
__initialTimestamp__ = (((u64)tv.tv_sec + CLK_JAN_1970) << 32)
|
||||||
|
@ -88,12 +86,12 @@ void mp_clock_init()
|
||||||
//RandomSeedFromDevice();
|
//RandomSeedFromDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 mp_get_timestamp(mp_clock_kind clock)
|
u64 oc_clock_timestamp(oc_clock_kind clock)
|
||||||
{
|
{
|
||||||
u64 ts = 0;
|
u64 ts = 0;
|
||||||
switch(clock)
|
switch(clock)
|
||||||
{
|
{
|
||||||
case MP_CLOCK_MONOTONIC:
|
case OC_CLOCK_MONOTONIC:
|
||||||
{
|
{
|
||||||
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
||||||
u64 noff = OSXGetMonotonicNanoseconds() ;
|
u64 noff = OSXGetMonotonicNanoseconds() ;
|
||||||
|
@ -101,7 +99,7 @@ u64 mp_get_timestamp(mp_clock_kind clock)
|
||||||
ts = __initialTimestamp__ + foff;
|
ts = __initialTimestamp__ + foff;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MP_CLOCK_UPTIME:
|
case OC_CLOCK_UPTIME:
|
||||||
{
|
{
|
||||||
//TODO(martin): maybe we should warn that this date is inconsistent after a sleep ?
|
//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
|
//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;
|
ts = __initialTimestamp__ + foff;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MP_CLOCK_DATE:
|
case OC_CLOCK_DATE:
|
||||||
{
|
{
|
||||||
//NOTE(martin): get system date and convert it to a fixed-point timestamp
|
//NOTE(martin): get system date and convert it to a fixed-point timestamp
|
||||||
timeval tv;
|
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
|
//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
|
//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_timediff tdfuzz = TimediffFromSeconds(fuzz);
|
||||||
ts = TimestampAdd(ts, tdfuzz);
|
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)
|
switch(clock)
|
||||||
{
|
{
|
||||||
case MP_CLOCK_MONOTONIC:
|
case OC_CLOCK_MONOTONIC:
|
||||||
{
|
{
|
||||||
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
//NOTE(martin): compute monotonic offset and add it to bootup timestamp
|
||||||
u64 noff = OSXGetMonotonicNanoseconds();
|
u64 noff = OSXGetMonotonicNanoseconds();
|
||||||
return((f64)noff * 1e-9);
|
return((f64)noff * 1e-9);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MP_CLOCK_UPTIME:
|
case OC_CLOCK_UPTIME:
|
||||||
{
|
{
|
||||||
//TODO(martin): maybe we should warn that this date is inconsistent after a sleep ?
|
//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
|
//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);
|
return((f64)noff * 1e-9);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MP_CLOCK_DATE:
|
case OC_CLOCK_DATE:
|
||||||
{
|
{
|
||||||
//TODO(martin): maybe warn about precision loss ?
|
//TODO(martin): maybe warn about precision loss ?
|
||||||
// could also change the epoch since we only promise to return a relative time
|
// 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;
|
} 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"
|
#include"platform_path.c"
|
||||||
|
|
||||||
bool path_is_absolute(str8 path)
|
bool oc_path_is_absolute(oc_str8 path)
|
||||||
{
|
{
|
||||||
return(path.len && (path.ptr[0] == '/'));
|
return(path.len && (path.ptr[0] == '/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
str8 path_executable(mem_arena* arena)
|
oc_str8 oc_path_executable(oc_arena* arena)
|
||||||
{@autoreleasepool{
|
{@autoreleasepool{
|
||||||
str8 result = {};
|
oc_str8 result = {};
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
_NSGetExecutablePath(0, &size);
|
_NSGetExecutablePath(0, &size);
|
||||||
result.len = 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);
|
_NSGetExecutablePath(result.ptr, &size);
|
||||||
result.ptr[result.len] = '\0';
|
result.ptr[result.len] = '\0';
|
||||||
return(result);
|
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);
|
oc_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||||
char* pathCString = str8_to_cstring(scratch.arena, path);
|
char* pathCString = oc_str8_to_cstring(scratch.arena, path);
|
||||||
|
|
||||||
char* real = realpath(pathCString, 0);
|
char* real = realpath(pathCString, 0);
|
||||||
str8 result = str8_push_cstring(arena, real);
|
oc_str8 result = oc_str8_push_cstring(arena, real);
|
||||||
|
|
||||||
free(real);
|
free(real);
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,17 @@
|
||||||
// Compiler identification
|
// Compiler identification
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define COMPILER_CLANG 1
|
#define OC_COMPILER_CLANG 1
|
||||||
#if defined(__apple_build_version__)
|
#if defined(__apple_build_version__)
|
||||||
#define COMPILER_CLANG_APPLE 1
|
#define OC_COMPILER_CLANG_APPLE 1
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define COMPILER_CLANG_CL 1
|
#define OC_COMPILER_CLANG_CL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define COMPILER_CL 1
|
#define OC_COMPILER_CL 1
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
#define COMPILER_GCC 1
|
#define OC_COMPILER_GCC 1
|
||||||
#else
|
#else
|
||||||
#error "Can't identify compiler"
|
#error "Can't identify compiler"
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,15 +33,15 @@
|
||||||
// OS identification
|
// OS identification
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
#define PLATFORM_WINDOWS 1
|
#define OC_PLATFORM_WINDOWS 1
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#error "Unsupported OS (32bit only version of Windows)"
|
#error "Unsupported OS (32bit only version of Windows)"
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
#define PLATFORM_MACOS 1
|
#define OC_PLATFORM_MACOS 1
|
||||||
#elif defined(__gnu_linux__)
|
#elif defined(__gnu_linux__)
|
||||||
#define PLATFORM_LINUX 1
|
#define PLATFORM_LINUX 1
|
||||||
#elif defined(__ORCA__)
|
#elif defined(__ORCA__)
|
||||||
#define PLATFORM_ORCA 1
|
#define OC_PLATFORM_ORCA 1
|
||||||
#else
|
#else
|
||||||
#error "Can't identify platform"
|
#error "Can't identify platform"
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,29 +49,29 @@
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// Architecture identification
|
// Architecture identification
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
#if defined(COMPILER_CL)
|
#if defined(OC_COMPILER_CL)
|
||||||
#if defined(_M_AMD64)
|
#if defined(_M_AMD64)
|
||||||
#define ARCH_X64 1
|
#define OC_ARCH_X64 1
|
||||||
#elif defined(_M_I86)
|
#elif defined(_M_I86)
|
||||||
#define ARCH_X86 1
|
#define OC_ARCH_X86 1
|
||||||
#elif defined(_M_ARM64)
|
#elif defined(_M_ARM64)
|
||||||
#define ARCH_ARM64 1
|
#define OC_ARCH_ARM64 1
|
||||||
#elif defined(_M_ARM)
|
#elif defined(_M_ARM)
|
||||||
#define ARCH_ARM32 1
|
#define OC_ARCH_ARM32 1
|
||||||
#else
|
#else
|
||||||
#error "Can't identify architecture"
|
#error "Can't identify architecture"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
#define ARCH_X64 1
|
#define OC_ARCH_X64 1
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#define ARCH_X86 1
|
#define OC_ARCH_X86 1
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
#define ARCH_ARM32 1
|
#define OC_ARCH_ARM32 1
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
#define ARCH_ARM64 1
|
#define OC_ARCH_ARM64 1
|
||||||
#elif defined(__ORCA__)
|
#elif defined(__ORCA__)
|
||||||
#define ARCH_WASM 1
|
#define OC_ARCH_WASM32 1
|
||||||
#else
|
#else
|
||||||
#error "Can't identify architecture"
|
#error "Can't identify architecture"
|
||||||
#endif
|
#endif
|
||||||
|
@ -80,28 +80,28 @@
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// platform helper macros
|
// platform helper macros
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
#if defined(COMPILER_CL)
|
#if defined(OC_COMPILER_CL)
|
||||||
#if defined(MP_BUILD_DLL)
|
#if defined(OC_BUILD_DLL)
|
||||||
#define MP_API __declspec(dllexport)
|
#define ORCA_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define MP_API __declspec(dllimport)
|
#define ORCA_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
|
#elif defined(OC_COMPILER_GCC) || defined(OC_COMPILER_CLANG)
|
||||||
#define MP_API
|
#define ORCA_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_ORCA
|
#if OC_PLATFORM_ORCA
|
||||||
#define mp_thread_local // no tls (or threads) for now on wasm orca
|
#define oc_thread_local // no tls (or threads) for now on wasm orca
|
||||||
#elif defined(COMPILER_CL)
|
#elif defined(OC_COMPILER_CL)
|
||||||
#define mp_thread_local __declspec(thread)
|
#define oc_thread_local __declspec(thread)
|
||||||
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
|
#elif defined(OC_COMPILER_GCC) || defined(OC_COMPILER_CLANG)
|
||||||
#define mp_thread_local __thread
|
#define oc_thread_local __thread
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_ORCA
|
#if OC_PLATFORM_ORCA
|
||||||
#define ORCA_IMPORT(f) __attribute__((import_name(#f))) f
|
#define ORCA_IMPORT(f) __attribute__((import_name(#f))) f
|
||||||
|
|
||||||
#if COMPILER_CLANG
|
#if OC_COMPILER_CLANG
|
||||||
#define ORCA_EXPORT __attribute__((visibility("default")))
|
#define ORCA_EXPORT __attribute__((visibility("default")))
|
||||||
#else
|
#else
|
||||||
#error "Orca apps can only be compiled with clang for now"
|
#error "Orca apps can only be compiled with clang for now"
|
||||||
|
|
|
@ -17,15 +17,14 @@ extern "C" {
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MP_CLOCK_MONOTONIC, // clock that increment monotonically
|
OC_CLOCK_MONOTONIC, // clock that increment monotonically
|
||||||
MP_CLOCK_UPTIME, // clock that increment monotonically during uptime
|
OC_CLOCK_UPTIME, // clock that increment monotonically during uptime
|
||||||
MP_CLOCK_DATE // clock that is driven by the platform time
|
OC_CLOCK_DATE // clock that is driven by the platform time
|
||||||
} mp_clock_kind;
|
} oc_clock_kind;
|
||||||
|
|
||||||
MP_API void mp_clock_init(); // initialize the clock subsystem
|
ORCA_API void oc_clock_init(); // initialize the clock subsystem
|
||||||
MP_API u64 mp_get_timestamp(mp_clock_kind clock);
|
ORCA_API u64 oc_clock_timestamp(oc_clock_kind clock);
|
||||||
MP_API f64 mp_get_time(mp_clock_kind clock);
|
ORCA_API f64 oc_clock_time(oc_clock_kind clock);
|
||||||
MP_API void mp_sleep_nanoseconds(u64 nanoseconds); // sleep for a given number of nanoseconds
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -7,34 +7,34 @@
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
#include"platform_debug.h"
|
#include"platform_debug.h"
|
||||||
|
|
||||||
typedef struct log_config
|
typedef struct oc_log_config
|
||||||
{
|
{
|
||||||
log_output* output;
|
oc_log_output* output;
|
||||||
log_level level;
|
oc_log_level level;
|
||||||
} log_config;
|
} oc_log_config;
|
||||||
|
|
||||||
//TODO: make default output a compile-time constant to avoid check in log_push()?
|
//TODO: make default output a compile-time constant to avoid check in oc_log_ext()?
|
||||||
static log_config __logConfig = {0, LOG_LEVEL_INFO};
|
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;
|
__logConfig.output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_set_level(log_level level)
|
void oc_log_set_level(oc_log_level level)
|
||||||
{
|
{
|
||||||
__logConfig.level = level;
|
__logConfig.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_log_push(log_output* output,
|
void platform_log_push(oc_log_output* output,
|
||||||
log_level level,
|
oc_log_level level,
|
||||||
const char* file,
|
const char* file,
|
||||||
const char* function,
|
const char* function,
|
||||||
int line,
|
int line,
|
||||||
const char* fmt,
|
const char* fmt,
|
||||||
va_list ap);
|
va_list ap);
|
||||||
|
|
||||||
void log_push(log_level level,
|
void oc_log_ext(oc_log_level level,
|
||||||
const char* function,
|
const char* function,
|
||||||
const char* file,
|
const char* file,
|
||||||
int line,
|
int line,
|
||||||
|
@ -43,7 +43,7 @@ void log_push(log_level level,
|
||||||
{
|
{
|
||||||
if(!__logConfig.output)
|
if(!__logConfig.output)
|
||||||
{
|
{
|
||||||
__logConfig.output = LOG_DEFAULT_OUTPUT;
|
__logConfig.output = OC_LOG_DEFAULT_OUTPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(level <= __logConfig.level)
|
if(level <= __logConfig.level)
|
||||||
|
|
|
@ -14,25 +14,25 @@
|
||||||
// Assert / Abort
|
// Assert / Abort
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
MP_API _Noreturn void orca_abort(const char* file, const char* function, int line, const char* fmt, ...);
|
ORCA_API _Noreturn void oc_abort_ext(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_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...);
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Logging
|
// Logging
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
typedef enum { LOG_LEVEL_ERROR,
|
typedef enum { OC_LOG_LEVEL_ERROR,
|
||||||
LOG_LEVEL_WARNING,
|
OC_LOG_LEVEL_WARNING,
|
||||||
LOG_LEVEL_INFO,
|
OC_LOG_LEVEL_INFO,
|
||||||
LOG_LEVEL_COUNT } log_level;
|
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);
|
ORCA_API void oc_log_set_level(oc_log_level level);
|
||||||
MP_API void log_set_output(log_output* output);
|
ORCA_API void oc_log_set_output(oc_log_output* output);
|
||||||
MP_API void log_push(log_level level,
|
ORCA_API void oc_log_ext(oc_log_level level,
|
||||||
const char* function,
|
const char* function,
|
||||||
const char* file,
|
const char* file,
|
||||||
int line,
|
int line,
|
||||||
|
|
|
@ -15,56 +15,56 @@
|
||||||
// IO API
|
// IO API
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct { u64 h; } file_handle;
|
typedef struct { u64 h; } oc_file;
|
||||||
|
|
||||||
typedef u16 file_open_flags;
|
typedef u16 oc_file_open_flags;
|
||||||
enum _file_open_flags
|
enum oc_file_open_flags_enum
|
||||||
{
|
{
|
||||||
FILE_OPEN_NONE = 0,
|
OC_FILE_OPEN_NONE = 0,
|
||||||
FILE_OPEN_APPEND = 1<<1,
|
OC_FILE_OPEN_APPEND = 1<<1,
|
||||||
FILE_OPEN_TRUNCATE = 1<<2,
|
OC_FILE_OPEN_TRUNCATE = 1<<2,
|
||||||
FILE_OPEN_CREATE = 1<<3,
|
OC_FILE_OPEN_CREATE = 1<<3,
|
||||||
|
|
||||||
FILE_OPEN_SYMLINK = 1<<4,
|
OC_FILE_OPEN_SYMLINK = 1<<4,
|
||||||
FILE_OPEN_NO_FOLLOW = 1<<5,
|
OC_FILE_OPEN_NO_FOLLOW = 1<<5,
|
||||||
FILE_OPEN_RESTRICT = 1<<6,
|
OC_FILE_OPEN_RESTRICT = 1<<6,
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef u16 file_access_rights;
|
typedef u16 oc_file_access;
|
||||||
enum _file_access_rights
|
enum oc_file_access_enum
|
||||||
{
|
{
|
||||||
FILE_ACCESS_NONE = 0,
|
OC_FILE_ACCESS_NONE = 0,
|
||||||
FILE_ACCESS_READ = 1<<1,
|
OC_FILE_ACCESS_READ = 1<<1,
|
||||||
FILE_ACCESS_WRITE = 1<<2,
|
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;
|
typedef u32 oc_io_op;
|
||||||
enum _io_op
|
enum oc_io_op_enum
|
||||||
{
|
{
|
||||||
IO_OP_OPEN_AT = 0,
|
OC_IO_OPEN_AT = 0,
|
||||||
IO_OP_CLOSE,
|
OC_IO_CLOSE,
|
||||||
|
|
||||||
IO_OP_FSTAT,
|
OC_IO_FSTAT,
|
||||||
|
|
||||||
IO_OP_SEEK,
|
OC_IO_SEEK,
|
||||||
IO_OP_READ,
|
OC_IO_READ,
|
||||||
IO_OP_WRITE,
|
OC_IO_WRITE,
|
||||||
|
|
||||||
IO_OP_ERROR,
|
OC_OC_IO_ERROR,
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct io_req
|
typedef struct oc_io_req
|
||||||
{
|
{
|
||||||
io_req_id id;
|
oc_io_req_id id;
|
||||||
io_op op;
|
oc_io_op op;
|
||||||
file_handle handle;
|
oc_file handle;
|
||||||
|
|
||||||
i64 offset;
|
i64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
@ -78,133 +78,133 @@ typedef struct io_req
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
file_access_rights rights;
|
oc_file_access rights;
|
||||||
file_open_flags flags;
|
oc_file_open_flags flags;
|
||||||
} open;
|
} open;
|
||||||
|
|
||||||
file_whence whence;
|
oc_file_whence whence;
|
||||||
};
|
};
|
||||||
|
|
||||||
} io_req;
|
} oc_io_req;
|
||||||
|
|
||||||
typedef i32 io_error;
|
typedef i32 oc_io_error;
|
||||||
enum _io_error {
|
enum oc_io_error_enum {
|
||||||
IO_OK = 0,
|
OC_IO_OK = 0,
|
||||||
IO_ERR_UNKNOWN,
|
OC_IO_ERR_UNKNOWN,
|
||||||
IO_ERR_OP, // unsupported operation
|
OC_IO_ERR_OP, // unsupported operation
|
||||||
IO_ERR_HANDLE, // invalid handle
|
OC_IO_ERR_HANDLE, // invalid handle
|
||||||
IO_ERR_PREV, // previously had a fatal error (last error stored on handle)
|
OC_IO_ERR_PREV, // previously had a fatal error (last error stored on handle)
|
||||||
IO_ERR_ARG, // invalid argument or argument combination
|
OC_IO_ERR_ARG, // invalid argument or argument combination
|
||||||
IO_ERR_PERM, // access denied
|
OC_IO_ERR_PERM, // access denied
|
||||||
IO_ERR_SPACE, // no space left
|
OC_IO_ERR_SPACE, // no space left
|
||||||
IO_ERR_NO_ENTRY, // file or directory does not exist
|
OC_IO_ERR_NO_ENTRY, // file or directory does not exist
|
||||||
IO_ERR_EXISTS, // file already exists
|
OC_IO_ERR_EXISTS, // file already exists
|
||||||
IO_ERR_NOT_DIR, // path element is not a directory
|
OC_IO_ERR_NOT_DIR, // path element is not a directory
|
||||||
IO_ERR_DIR, // attempted to write directory
|
OC_IO_ERR_DIR, // attempted to write directory
|
||||||
IO_ERR_MAX_FILES, // max open files reached
|
OC_IO_ERR_MAX_FILES, // max open files reached
|
||||||
IO_ERR_MAX_LINKS, // too many symbolic links in path
|
OC_IO_ERR_MAX_LINKS, // too many symbolic links in path
|
||||||
IO_ERR_PATH_LENGTH, // path too long
|
OC_IO_ERR_PATH_LENGTH, // path too long
|
||||||
IO_ERR_FILE_SIZE, // file too big
|
OC_IO_ERR_FILE_SIZE, // file too big
|
||||||
IO_ERR_OVERFLOW, // offset too big
|
OC_IO_ERR_OVERFLOW, // offset too big
|
||||||
IO_ERR_NOT_READY, // no data ready to be read/written
|
OC_IO_ERR_NOT_READY, // no data ready to be read/written
|
||||||
IO_ERR_MEM, // failed to allocate memory
|
OC_IO_ERR_MEM, // failed to allocate memory
|
||||||
IO_ERR_INTERRUPT, // operation interrupted by a signal
|
OC_IO_ERR_INTERRUPT, // operation interrupted by a signal
|
||||||
IO_ERR_PHYSICAL, // physical IO error
|
OC_IO_ERR_PHYSICAL, // physical IO error
|
||||||
IO_ERR_NO_DEVICE, // device not found
|
OC_IO_ERR_NO_DEVICE, // device not found
|
||||||
IO_ERR_WALKOUT, // attempted to walk out of root directory
|
OC_IO_ERR_WALKOUT, // attempted to walk out of root directory
|
||||||
|
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct io_cmp
|
typedef struct oc_io_cmp
|
||||||
{
|
{
|
||||||
io_req_id id;
|
oc_io_req_id id;
|
||||||
io_error error;
|
oc_io_error error;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
i64 result;
|
i64 result;
|
||||||
u64 size;
|
u64 size;
|
||||||
i64 offset;
|
i64 offset;
|
||||||
file_handle handle;
|
oc_file handle;
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
} io_cmp;
|
} oc_io_cmp;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
//TODO: complete io queue api
|
//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
|
// File IO wrapper API
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
MP_API file_handle file_handle_nil();
|
ORCA_API oc_file oc_file_nil();
|
||||||
MP_API bool file_handle_is_nil(file_handle handle);
|
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);
|
ORCA_API oc_file oc_file_open(oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
|
||||||
MP_API file_handle file_open_at(file_handle dir, str8 path, file_access_rights rights, 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);
|
||||||
MP_API void file_close(file_handle file);
|
ORCA_API void oc_file_close(oc_file file);
|
||||||
|
|
||||||
MP_API i64 file_pos(file_handle file);
|
ORCA_API i64 oc_file_pos(oc_file file);
|
||||||
MP_API i64 file_seek(file_handle file, i64 offset, file_whence whence);
|
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);
|
ORCA_API u64 oc_file_write(oc_file file, u64 size, char* buffer);
|
||||||
MP_API u64 file_read(file_handle 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
|
// File System wrapper API
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
typedef enum file_type
|
typedef enum oc_file_type
|
||||||
{
|
{
|
||||||
MP_FILE_UNKNOWN,
|
OC_FILE_UNKNOWN,
|
||||||
MP_FILE_REGULAR,
|
OC_FILE_REGULAR,
|
||||||
MP_FILE_DIRECTORY,
|
OC_FILE_DIRECTORY,
|
||||||
MP_FILE_SYMLINK,
|
OC_FILE_SYMLINK,
|
||||||
MP_FILE_BLOCK,
|
OC_FILE_BLOCK,
|
||||||
MP_FILE_CHARACTER,
|
OC_FILE_CHARACTER,
|
||||||
MP_FILE_FIFO,
|
OC_FILE_FIFO,
|
||||||
MP_FILE_SOCKET,
|
OC_FILE_SOCKET,
|
||||||
|
|
||||||
} file_type;
|
} oc_file_type;
|
||||||
|
|
||||||
typedef u16 file_perm;
|
typedef u16 oc_file_perm;
|
||||||
enum file_perm
|
enum oc_file_perm
|
||||||
{
|
{
|
||||||
MP_FILE_OTHER_EXEC = 1<<0,
|
OC_FILE_OTHER_EXEC = 1<<0,
|
||||||
MP_FILE_OTHER_WRITE = 1<<1,
|
OC_FILE_OTHER_WRITE = 1<<1,
|
||||||
MP_FILE_OTHER_READ = 1<<2,
|
OC_FILE_OTHER_READ = 1<<2,
|
||||||
|
|
||||||
MP_FILE_GROUP_EXEC = 1<<3,
|
OC_FILE_GROUP_EXEC = 1<<3,
|
||||||
MP_FILE_GROUP_WRITE = 1<<4,
|
OC_FILE_GROUP_WRITE = 1<<4,
|
||||||
MP_FILE_GROUP_READ = 1<<5,
|
OC_FILE_GROUP_READ = 1<<5,
|
||||||
|
|
||||||
MP_FILE_OWNER_EXEC = 1<<6,
|
OC_FILE_OWNER_EXEC = 1<<6,
|
||||||
MP_FILE_OWNER_WRITE = 1<<7,
|
OC_FILE_OWNER_WRITE = 1<<7,
|
||||||
MP_FILE_OWNER_READ = 1<<8,
|
OC_FILE_OWNER_READ = 1<<8,
|
||||||
|
|
||||||
MP_FILE_STICKY_BIT = 1<<9,
|
OC_FILE_STICKY_BIT = 1<<9,
|
||||||
MP_FILE_SET_GID = 1<<10,
|
OC_FILE_SET_GID = 1<<10,
|
||||||
MP_FILE_SET_UID = 1<<11,
|
OC_FILE_SET_UID = 1<<11,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct file_status
|
typedef struct oc_file_status
|
||||||
{
|
{
|
||||||
u64 uid;
|
u64 uid;
|
||||||
file_type type;
|
oc_file_type type;
|
||||||
file_perm perm;
|
oc_file_perm perm;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
|
||||||
//TODO times
|
//TODO times
|
||||||
|
|
||||||
} file_status;
|
} oc_file_status;
|
||||||
|
|
||||||
MP_API file_status file_get_status(file_handle file);
|
ORCA_API oc_file_status oc_file_get_status(oc_file file);
|
||||||
MP_API u64 file_size(file_handle file);
|
ORCA_API u64 oc_file_size(oc_file file);
|
||||||
|
|
||||||
//TODO: Complete as needed...
|
//TODO: Complete as needed...
|
||||||
|
|
||||||
|
|
|
@ -11,112 +11,112 @@
|
||||||
// File stream read/write API
|
// 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);
|
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,
|
.size = path.len,
|
||||||
.buffer = path.ptr,
|
.buffer = path.ptr,
|
||||||
.open.rights = rights,
|
.open.rights = rights,
|
||||||
.open.flags = flags };
|
.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
|
//WARN: we always return a handle that can be queried for errors. Handles must be closed
|
||||||
// even if there was an error when opening
|
// even if there was an error when opening
|
||||||
return(cmp.handle);
|
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,
|
.handle = dir,
|
||||||
.size = path.len,
|
.size = path.len,
|
||||||
.buffer = path.ptr,
|
.buffer = path.ptr,
|
||||||
.open.rights = rights,
|
.open.rights = rights,
|
||||||
.open.flags = flags,};
|
.open.flags = flags,};
|
||||||
|
|
||||||
io_cmp cmp = io_wait_single_req(&req);
|
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||||
return(cmp.handle);
|
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};
|
.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,
|
.handle = file,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
.whence = whence};
|
.whence = whence};
|
||||||
|
|
||||||
io_cmp cmp = io_wait_single_req(&req);
|
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||||
return(cmp.offset);
|
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,
|
.handle = file,
|
||||||
.size = size,
|
.size = size,
|
||||||
.buffer = buffer};
|
.buffer = buffer};
|
||||||
|
|
||||||
io_cmp cmp = io_wait_single_req(&req);
|
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||||
return(cmp.size);
|
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,
|
.handle = file,
|
||||||
.size = size,
|
.size = size,
|
||||||
.buffer = buffer};
|
.buffer = buffer};
|
||||||
|
|
||||||
io_cmp cmp = io_wait_single_req(&req);
|
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||||
return(cmp.size);
|
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};
|
.handle = file};
|
||||||
|
|
||||||
io_cmp cmp = io_wait_single_req(&req);
|
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||||
return((io_error)cmp.result);
|
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};
|
oc_file_status status = {0};
|
||||||
io_req req = {.op = IO_OP_FSTAT,
|
oc_io_req req = {.op = OC_IO_FSTAT,
|
||||||
.handle = file,
|
.handle = file,
|
||||||
.size = sizeof(file_status),
|
.size = sizeof(oc_file_status),
|
||||||
.buffer = (char*)&status};
|
.buffer = (char*)&status};
|
||||||
|
|
||||||
io_cmp cmp = io_wait_single_req(&req);
|
oc_io_cmp cmp = oc_io_wait_single_req(&req);
|
||||||
return(status);
|
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);
|
return(status.size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
#include"platform_io_internal.h"
|
#include"platform_io_internal.h"
|
||||||
#include"platform_path.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);
|
oc_file_slot* slot = oc_list_pop_entry(&table->freeList, oc_file_slot, freeListElt);
|
||||||
if(!slot && table->nextSlot < ORCA_MAX_FILE_SLOTS)
|
if(!slot && table->nextSlot < OC_IO_MAX_FILE_SLOTS)
|
||||||
{
|
{
|
||||||
slot = &table->slots[table->nextSlot];
|
slot = &table->slots[table->nextSlot];
|
||||||
slot->generation = 1;
|
slot->generation = 1;
|
||||||
|
@ -22,36 +22,36 @@ file_slot* file_slot_alloc(file_table* table)
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 tmpGeneration = slot->generation;
|
u32 tmpGeneration = slot->generation;
|
||||||
memset(slot, 0, sizeof(file_slot));
|
memset(slot, 0, sizeof(oc_file_slot));
|
||||||
slot->generation = tmpGeneration;
|
slot->generation = tmpGeneration;
|
||||||
|
|
||||||
return(slot);
|
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++;
|
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 index = slot - table->slots;
|
||||||
u64 generation = slot->generation;
|
u64 generation = slot->generation;
|
||||||
file_handle handle = {.h = (generation<<32) | index };
|
oc_file handle = {.h = (generation<<32) | index };
|
||||||
return(handle);
|
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 index = handle.h & 0xffffffff;
|
||||||
u64 generation = handle.h>>32;
|
u64 generation = handle.h>>32;
|
||||||
|
|
||||||
if(index < table->nextSlot)
|
if(index < table->nextSlot)
|
||||||
{
|
{
|
||||||
file_slot* candidate = &table->slots[index];
|
oc_file_slot* candidate = &table->slots[index];
|
||||||
if(candidate->generation == generation)
|
if(candidate->generation == generation)
|
||||||
{
|
{
|
||||||
slot = candidate;
|
slot = candidate;
|
||||||
|
@ -60,149 +60,149 @@ file_slot* file_slot_from_handle(file_table* table, file_handle handle)
|
||||||
return(slot);
|
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
|
// 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;
|
u64 rootUID;
|
||||||
io_file_desc rootFd;
|
oc_file_desc rootFd;
|
||||||
io_file_desc fd;
|
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);
|
oc_file_desc nextFd = oc_io_raw_open_at(context->fd, name, accessRights, openFlags);
|
||||||
if(io_file_desc_is_nil(nextFd))
|
if(oc_file_desc_is_nil(nextFd))
|
||||||
{
|
{
|
||||||
context->error = io_raw_last_error();
|
context->error = oc_io_raw_last_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(context->fd != context->rootFd)
|
if(context->fd != context->rootFd)
|
||||||
{
|
{
|
||||||
io_raw_close(context->fd);
|
oc_io_raw_close(context->fd);
|
||||||
}
|
}
|
||||||
context->fd = nextFd;
|
context->fd = nextFd;
|
||||||
}
|
}
|
||||||
return(context->error);
|
return(context->error);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct io_open_restrict_result
|
typedef struct oc_io_open_restrict_result
|
||||||
{
|
{
|
||||||
io_error error;
|
oc_io_error error;
|
||||||
io_file_desc fd;
|
oc_file_desc fd;
|
||||||
} io_open_restrict_result;
|
} 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};
|
oc_str8_list sep = {0};
|
||||||
str8_list_push(scratch.arena, &sep, STR8("/"));
|
oc_str8_list_push(scratch.arena, &sep, OC_STR8("/"));
|
||||||
str8_list_push(scratch.arena, &sep, STR8("\\"));
|
oc_str8_list_push(scratch.arena, &sep, OC_STR8("\\"));
|
||||||
str8_list pathElements = str8_split(scratch.arena, path, sep);
|
oc_str8_list pathElements = oc_str8_split(scratch.arena, path, sep);
|
||||||
|
|
||||||
io_open_restrict_context context = {
|
oc_io_open_restrict_context context = {
|
||||||
.error = IO_OK,
|
.error = OC_IO_OK,
|
||||||
.rootFd = dirFd,
|
.rootFd = dirFd,
|
||||||
.fd = 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
|
else
|
||||||
{
|
{
|
||||||
file_status status;
|
oc_file_status status;
|
||||||
context.error = io_raw_fstat(dirFd, &status);
|
context.error = oc_io_raw_fstat(dirFd, &status);
|
||||||
context.rootUID = status.uid;
|
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;
|
oc_str8 name = elt->string;
|
||||||
file_access_rights eltAccessRights = FILE_ACCESS_READ;
|
oc_file_access eltAccessRights = OC_FILE_ACCESS_READ;
|
||||||
file_open_flags eltOpenFlags = 0;
|
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)
|
if(atLastElement)
|
||||||
{
|
{
|
||||||
eltAccessRights = accessRights;
|
eltAccessRights = accessRights;
|
||||||
eltOpenFlags = openFlags;
|
eltOpenFlags = openFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !str8_cmp(name, STR8("."))
|
if( !oc_str8_cmp(name, OC_STR8("."))
|
||||||
&& !atLastElement)
|
&& !atLastElement)
|
||||||
{
|
{
|
||||||
//NOTE: if we're not at the last element we can just skip '.' elements
|
//NOTE: if we're not at the last element we can just skip '.' elements
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(!str8_cmp(name, STR8("..")))
|
else if(!oc_str8_cmp(name, OC_STR8("..")))
|
||||||
{
|
{
|
||||||
//NOTE: check that we don't escape root dir
|
//NOTE: check that we don't escape root dir
|
||||||
file_status status;
|
oc_file_status status;
|
||||||
context.error = io_raw_fstat(context.fd, &status);
|
context.error = oc_io_raw_fstat(context.fd, &status);
|
||||||
if(context.error)
|
if(context.error)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(status.uid == context.rootUID)
|
else if(status.uid == context.rootUID)
|
||||||
{
|
{
|
||||||
context.error = IO_ERR_WALKOUT;
|
context.error = OC_IO_ERR_WALKOUT;
|
||||||
break;
|
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
|
//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 IO_ERROR_NO_ENTRY error.
|
// is set, we create the file. Otherwise it is a OC_IO_ERROR_NO_ENTRY error.
|
||||||
if( !atLastElement
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//NOTE: if the file exists, we check the type of file
|
//NOTE: if the file exists, we check the type of file
|
||||||
file_status status = {0};
|
oc_file_status status = {0};
|
||||||
context.error = io_raw_fstat_at(context.fd, name, FILE_OPEN_SYMLINK, &status);
|
context.error = oc_io_raw_fstat_at(context.fd, name, OC_FILE_OPEN_SYMLINK, &status);
|
||||||
if(context.error)
|
if(context.error)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.type == MP_FILE_REGULAR)
|
if(status.type == OC_FILE_REGULAR)
|
||||||
{
|
{
|
||||||
if(!atLastElement)
|
if(!atLastElement)
|
||||||
{
|
{
|
||||||
context.error = IO_ERR_NOT_DIR;
|
context.error = OC_IO_ERR_NOT_DIR;
|
||||||
break;
|
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?
|
//TODO - do we need a OC_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?
|
// - do we need a OC_FILE_OPEN_NO_SYMLINKS that fails if _any_ element is a symlink?
|
||||||
|
|
||||||
if( !atLastElement
|
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)
|
if(link.error)
|
||||||
{
|
{
|
||||||
context.error = 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)
|
if(link.target.len == 0)
|
||||||
{
|
{
|
||||||
//NOTE: treat an empty target as a '.'
|
//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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
str8_list linkElements = str8_split(scratch.arena, link.target, sep);
|
oc_str8_list linkElements = oc_str8_split(scratch.arena, link.target, sep);
|
||||||
if(!list_empty(&linkElements.list))
|
if(!oc_list_empty(&linkElements.list))
|
||||||
{
|
{
|
||||||
//NOTE: insert linkElements into pathElements after elt
|
//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;
|
elt->listElt.next = linkElements.list.first;
|
||||||
linkElements.list.last->next = tmp;
|
linkElements.list.last->next = tmp;
|
||||||
if(!tmp)
|
if(!tmp)
|
||||||
|
@ -234,63 +234,63 @@ io_open_restrict_result io_open_restrict(io_file_desc dirFd, str8 path, file_acc
|
||||||
continue;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: if we arrive here, we have no errors and the correct flags are set,
|
//NOTE: if we arrive here, we have no errors and the correct flags are set,
|
||||||
// so we can enter the element
|
// so we can enter the element
|
||||||
DEBUG_ASSERT(context.error == IO_OK);
|
OC_DEBUG_ASSERT(context.error == OC_IO_OK);
|
||||||
io_open_restrict_enter(&context, name, eltAccessRights, eltOpenFlags);
|
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)
|
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,
|
.error = context.error,
|
||||||
.fd = context.fd
|
.fd = context.fd
|
||||||
};
|
};
|
||||||
|
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
return(result);
|
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)
|
if(!slot)
|
||||||
{
|
{
|
||||||
cmp.error = IO_ERR_MAX_FILES;
|
cmp.error = OC_IO_ERR_MAX_FILES;
|
||||||
cmp.result = 0;
|
cmp.result = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slot->fd = io_file_desc_nil();
|
slot->fd = oc_file_desc_nil();
|
||||||
cmp.handle = file_handle_from_slot(table, slot);
|
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)
|
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
|
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)
|
if(slot->rights != req->open.rights)
|
||||||
{
|
{
|
||||||
slot->error = IO_ERR_PERM;
|
slot->error = OC_IO_ERR_PERM;
|
||||||
}
|
}
|
||||||
else
|
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->error = res.error;
|
||||||
slot->fd = res.fd;
|
slot->fd = res.fd;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slot->fd = io_raw_open_at(dirFd, path, slot->rights, req->open.flags);
|
slot->fd = oc_io_raw_open_at(dirFd, path, slot->rights, req->open.flags);
|
||||||
if(io_file_desc_is_nil(slot->fd))
|
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;
|
oc_file_status status;
|
||||||
slot->error = io_raw_fstat(slot->fd, &status);
|
slot->error = oc_io_raw_fstat(slot->fd, &status);
|
||||||
if(slot->error == IO_OK)
|
if(slot->error == OC_IO_OK)
|
||||||
{
|
{
|
||||||
slot->type = status.type;
|
slot->type = status.type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,60 +11,60 @@
|
||||||
#include"platform_io.h"
|
#include"platform_io.h"
|
||||||
#include"platform.h"
|
#include"platform.h"
|
||||||
|
|
||||||
#if PLATFORM_MACOS || PLATFORM_LINUX
|
#if OC_PLATFORM_MACOS || PLATFORM_LINUX
|
||||||
typedef int io_file_desc;
|
typedef int oc_file_desc;
|
||||||
#elif PLATFORM_WINDOWS
|
#elif OC_PLATFORM_WINDOWS
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
#include<windows.h>
|
#include<windows.h>
|
||||||
typedef HANDLE io_file_desc;
|
typedef HANDLE oc_file_desc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct file_slot
|
typedef struct oc_file_slot
|
||||||
{
|
{
|
||||||
u32 generation;
|
u32 generation;
|
||||||
io_error error;
|
oc_io_error error;
|
||||||
bool fatal;
|
bool fatal;
|
||||||
list_elt freeListElt;
|
oc_list_elt freeListElt;
|
||||||
|
|
||||||
file_type type;
|
oc_file_type type;
|
||||||
file_access_rights rights;
|
oc_file_access rights;
|
||||||
io_file_desc fd;
|
oc_file_desc fd;
|
||||||
|
|
||||||
} file_slot;
|
} oc_file_slot;
|
||||||
|
|
||||||
enum
|
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;
|
u32 nextSlot;
|
||||||
list_info freeList;
|
oc_list freeList;
|
||||||
} file_table;
|
} oc_file_table;
|
||||||
|
|
||||||
file_slot* file_slot_alloc(file_table* table);
|
oc_file_slot* oc_file_slot_alloc(oc_file_table* table);
|
||||||
void file_slot_recycle(file_table* table, file_slot* slot);
|
void oc_file_slot_recycle(oc_file_table* table, oc_file_slot* slot);
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
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
|
// raw io primitives
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
io_file_desc io_file_desc_nil();
|
oc_file_desc oc_file_desc_nil();
|
||||||
bool io_file_desc_is_nil(io_file_desc fd);
|
bool oc_file_desc_is_nil(oc_file_desc fd);
|
||||||
|
|
||||||
/*WARN
|
/*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:
|
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)
|
- If dirFd is a nil fd, it is _ignored_ (i.e., path can be absolute, or relative to the current directory)
|
||||||
|
|
||||||
This means that:
|
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 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)
|
(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);
|
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 io_raw_close(io_file_desc fd);
|
void oc_io_raw_close(oc_file_desc fd);
|
||||||
io_error io_raw_last_error();
|
oc_io_error oc_io_raw_last_error();
|
||||||
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);
|
||||||
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 io_raw_fstat_at(io_file_desc dirFd, str8 path, file_open_flags openFlags, 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;
|
oc_io_error error;
|
||||||
str8 target;
|
oc_str8 target;
|
||||||
} io_raw_read_link_result;
|
} 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_
|
#endif //__PLATFORM_IO_INTERNAL_H_
|
||||||
|
|
|
@ -19,40 +19,34 @@ extern "C" {
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
//NOTE(martin): base allocator
|
//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*(*oc_mem_reserve_function)(oc_base_allocator* context, u64 size);
|
||||||
typedef void(*mem_modify_function)(mem_base_allocator* context, void* ptr, 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;
|
oc_mem_reserve_function reserve;
|
||||||
mem_modify_function commit;
|
oc_mem_modify_function commit;
|
||||||
mem_modify_function decommit;
|
oc_mem_modify_function decommit;
|
||||||
mem_modify_function release;
|
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 oc_base_reserve(base, size) base->reserve(base, size)
|
||||||
#define mem_base_commit(base, ptr, size) base->commit(base, ptr, size)
|
#define oc_base_commit(base, ptr, size) base->commit(base, ptr, size)
|
||||||
#define mem_base_decommit(base, ptr, size) base->decommit(base, ptr, size)
|
#define oc_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_release(base, ptr, size) base->release(base, ptr, size)
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
//NOTE(martin): malloc/free
|
//NOTE(martin): malloc/free
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
#if PLATFORM_ORCA
|
#include<stdlib.h>
|
||||||
void* malloc(size_t size);
|
|
||||||
void* realloc(void* ptr, size_t size);
|
|
||||||
void free(void* ptr);
|
|
||||||
#else
|
|
||||||
#include<stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define malloc_type(type) ((type*)malloc(sizeof(type)))
|
#define oc_malloc_type(type) ((type*)malloc(sizeof(type)))
|
||||||
#define malloc_array(type, count) ((type*)malloc(sizeof(type)*count))
|
#define oc_malloc_array(type, count) ((type*)malloc(sizeof(type)*count))
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
//NOTE(martin): memset / memcpy
|
//NOTE(martin): memset / memcpy
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include"platform_path.h"
|
#include"platform_path.h"
|
||||||
|
|
||||||
str8 path_slice_directory(str8 fullPath)
|
oc_str8 oc_path_slice_directory(oc_str8 fullPath)
|
||||||
{
|
{
|
||||||
i64 lastSlashIndex = -1;
|
i64 lastSlashIndex = -1;
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ str8 path_slice_directory(str8 fullPath)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str8 directory = str8_slice(fullPath, 0, lastSlashIndex+1);
|
oc_str8 directory = oc_str8_slice(fullPath, 0, lastSlashIndex+1);
|
||||||
return(directory);
|
return(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
str8 path_slice_filename(str8 fullPath)
|
oc_str8 oc_path_slice_filename(oc_str8 fullPath)
|
||||||
{
|
{
|
||||||
i64 lastSlashIndex = -1;
|
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);
|
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);
|
oc_arena_scope tmp = oc_scratch_begin_next(arena);
|
||||||
str8_list split = {0};
|
oc_str8_list split = {0};
|
||||||
str8_list_push(tmp.arena, &split, STR8("/"));
|
oc_str8_list_push(tmp.arena, &split, OC_STR8("/"));
|
||||||
str8_list res = str8_split(arena, path, split);
|
oc_str8_list res = oc_str8_split(arena, path, split);
|
||||||
mem_scratch_end(tmp);
|
oc_scratch_end(tmp);
|
||||||
return(res);
|
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 '/' ?
|
//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);
|
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)
|
if(parent.len == 0)
|
||||||
{
|
{
|
||||||
result = str8_push_copy(arena, relPath);
|
result = oc_str8_push_copy(arena, relPath);
|
||||||
}
|
}
|
||||||
else if(relPath.len == 0)
|
else if(relPath.len == 0)
|
||||||
{
|
{
|
||||||
result = str8_push_copy(arena, parent);
|
result = oc_str8_push_copy(arena, parent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mem_arena_scope tmp = mem_scratch_begin_next(arena);
|
oc_arena_scope tmp = oc_scratch_begin_next(arena);
|
||||||
|
|
||||||
str8_list list = {0};
|
oc_str8_list list = {0};
|
||||||
str8_list_push(tmp.arena, &list, parent);
|
oc_str8_list_push(tmp.arena, &list, parent);
|
||||||
if( (parent.ptr[parent.len-1] != '/')
|
if( (parent.ptr[parent.len-1] != '/')
|
||||||
&&(relPath.ptr[relPath.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);
|
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};
|
oc_str8_list list = {0};
|
||||||
mem_arena_scope scratch = mem_scratch_begin_next(arena);
|
oc_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||||
|
|
||||||
str8 executablePath = path_executable(scratch.arena);
|
oc_str8 executablePath = oc_path_executable(scratch.arena);
|
||||||
str8 dirPath = path_slice_directory(executablePath);
|
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);
|
return(path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,18 +16,18 @@
|
||||||
the string.
|
the string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MP_API str8 path_slice_directory(str8 path);
|
ORCA_API oc_str8 oc_path_slice_directory(oc_str8 path);
|
||||||
MP_API str8 path_slice_filename(str8 path);
|
ORCA_API oc_str8 oc_path_slice_filename(oc_str8 path);
|
||||||
|
|
||||||
MP_API str8_list path_split(mem_arena* arena, str8 path);
|
ORCA_API oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path);
|
||||||
MP_API str8 path_join(mem_arena* arena, str8_list elements);
|
ORCA_API oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements);
|
||||||
MP_API str8 path_append(mem_arena* arena, str8 parent, str8 relPath);
|
ORCA_API oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath);
|
||||||
|
|
||||||
MP_API bool path_is_absolute(str8 path);
|
ORCA_API bool oc_path_is_absolute(oc_str8 path);
|
||||||
MP_API str8 path_executable(mem_arena* arena);
|
ORCA_API oc_str8 oc_path_executable(oc_arena* arena);
|
||||||
MP_API str8 path_canonical(mem_arena* arena, str8 path);
|
ORCA_API oc_str8 oc_path_canonical(oc_arena* arena, oc_str8 path);
|
||||||
|
|
||||||
// helper: gets the path from path_executable() and appends relPath
|
// helper: gets the path from oc_path_executable() and appends relPath
|
||||||
MP_API str8 path_executable_relative(mem_arena* arena, str8 relPath);
|
ORCA_API oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath);
|
||||||
|
|
||||||
#endif //__PLATFORM_PATH_H_
|
#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_
|
#ifndef __PLATFORM_THREAD_H_
|
||||||
#define __PLATFORM_THREAD_H_
|
#define __PLATFORM_THREAD_H_
|
||||||
|
|
||||||
|
#include"util/strings.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include<atomic>
|
#include<atomic>
|
||||||
|
@ -27,59 +28,64 @@ extern "C" {
|
||||||
|
|
||||||
enum
|
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);
|
ORCA_API oc_thread* oc_thread_create(oc_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);
|
ORCA_API oc_thread* oc_thread_create_with_name(oc_thread_start_function start, void* userPointer, oc_str8 name);
|
||||||
MP_API const char* mp_thread_get_name(mp_thread* thread);
|
ORCA_API oc_str8 oc_thread_get_name(oc_thread* thread);
|
||||||
MP_API u64 mp_thread_unique_id(mp_thread* thread);
|
ORCA_API u64 oc_thread_unique_id(oc_thread* thread);
|
||||||
MP_API u64 mp_thread_self_id();
|
ORCA_API u64 oc_thread_self_id();
|
||||||
MP_API int mp_thread_signal(mp_thread* thread, int sig);
|
ORCA_API int oc_thread_signal(oc_thread* thread, int sig);
|
||||||
MP_API int mp_thread_join(mp_thread* thread, i64* exitCode);
|
ORCA_API int oc_thread_join(oc_thread* thread, i64* exitCode);
|
||||||
MP_API int mp_thread_detach(mp_thread* thread);
|
ORCA_API int oc_thread_detach(oc_thread* thread);
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Platform Mutex API
|
// Platform Mutex API
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct mp_mutex mp_mutex;
|
typedef struct oc_mutex oc_mutex;
|
||||||
|
|
||||||
MP_API mp_mutex* mp_mutex_create();
|
ORCA_API oc_mutex* oc_mutex_create();
|
||||||
MP_API int mp_mutex_destroy(mp_mutex* mutex);
|
ORCA_API int oc_mutex_destroy(oc_mutex* mutex);
|
||||||
MP_API int mp_mutex_lock(mp_mutex* mutex);
|
ORCA_API int oc_mutex_lock(oc_mutex* mutex);
|
||||||
MP_API int mp_mutex_unlock(mp_mutex* mutex);
|
ORCA_API int oc_mutex_unlock(oc_mutex* mutex);
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Lightweight ticket mutex API
|
// Lightweight ticket mutex API
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct mp_ticket_spin_mutex
|
typedef struct oc_ticket
|
||||||
{
|
{
|
||||||
volatile _Atomic(u64) nextTicket;
|
volatile _Atomic(u64) nextTicket;
|
||||||
volatile _Atomic(u64) serving;
|
volatile _Atomic(u64) serving;
|
||||||
} mp_ticket_spin_mutex;
|
} oc_ticket;
|
||||||
|
|
||||||
MP_API void mp_ticket_spin_mutex_init(mp_ticket_spin_mutex* mutex);
|
ORCA_API void oc_ticket_init(oc_ticket* mutex);
|
||||||
MP_API void mp_ticket_spin_mutex_lock(mp_ticket_spin_mutex* mutex);
|
ORCA_API void oc_ticket_lock(oc_ticket* mutex);
|
||||||
MP_API void mp_ticket_spin_mutex_unlock(mp_ticket_spin_mutex* mutex);
|
ORCA_API void oc_ticket_unlock(oc_ticket* mutex);
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Platform condition variable API
|
// Platform condition variable API
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct mp_condition mp_condition;
|
typedef struct oc_condition oc_condition;
|
||||||
|
|
||||||
MP_API mp_condition* mp_condition_create();
|
ORCA_API oc_condition* oc_condition_create();
|
||||||
MP_API int mp_condition_destroy(mp_condition* cond);
|
ORCA_API int oc_condition_destroy(oc_condition* cond);
|
||||||
MP_API int mp_condition_wait(mp_condition* cond, mp_mutex* mutex);
|
ORCA_API int oc_condition_wait(oc_condition* cond, oc_mutex* mutex);
|
||||||
MP_API int mp_condition_timedwait(mp_condition* cond, mp_mutex* mutex, f64 seconds);
|
ORCA_API int oc_condition_timedwait(oc_condition* cond, oc_mutex* mutex, f64 seconds);
|
||||||
MP_API int mp_condition_signal(mp_condition* cond);
|
ORCA_API int oc_condition_signal(oc_condition* cond);
|
||||||
MP_API int mp_condition_broadcast(mp_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
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -15,116 +15,116 @@
|
||||||
#include"platform_io_common.c"
|
#include"platform_io_common.c"
|
||||||
#include"platform_io_internal.c"
|
#include"platform_io_internal.c"
|
||||||
|
|
||||||
io_file_desc io_file_desc_nil()
|
oc_file_desc oc_file_desc_nil()
|
||||||
{
|
{
|
||||||
return(-1);
|
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);
|
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)
|
switch(errno)
|
||||||
{
|
{
|
||||||
case EPERM:
|
case EPERM:
|
||||||
case EACCES:
|
case EACCES:
|
||||||
case EROFS:
|
case EROFS:
|
||||||
error = IO_ERR_PERM;
|
error = OC_IO_ERR_PERM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
error = IO_ERR_NO_ENTRY;
|
error = OC_IO_ERR_NO_ENTRY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EINTR:
|
case EINTR:
|
||||||
error = IO_ERR_INTERRUPT;
|
error = OC_IO_ERR_INTERRUPT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EIO:
|
case EIO:
|
||||||
error = IO_ERR_PHYSICAL;
|
error = OC_IO_ERR_PHYSICAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENXIO:
|
case ENXIO:
|
||||||
error = IO_ERR_NO_DEVICE;
|
error = OC_IO_ERR_NO_DEVICE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EBADF:
|
case EBADF:
|
||||||
// this should only happen when user tries to write/read to a file handle
|
// this should only happen when user tries to write/read to a file handle
|
||||||
// opened with readonly/writeonly access
|
// opened with readonly/writeonly access
|
||||||
error = IO_ERR_PERM;
|
error = OC_IO_ERR_PERM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
error = IO_ERR_MEM;
|
error = OC_IO_ERR_MEM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EFAULT:
|
case EFAULT:
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
case EDOM:
|
case EDOM:
|
||||||
error = IO_ERR_ARG;
|
error = OC_IO_ERR_ARG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EBUSY:
|
case EBUSY:
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
error = IO_ERR_NOT_READY;
|
error = OC_IO_ERR_NOT_READY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EEXIST:
|
case EEXIST:
|
||||||
error = IO_ERR_EXISTS;
|
error = OC_IO_ERR_EXISTS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENOTDIR:
|
case ENOTDIR:
|
||||||
error = IO_ERR_NOT_DIR;
|
error = OC_IO_ERR_NOT_DIR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EISDIR:
|
case EISDIR:
|
||||||
error = IO_ERR_DIR;
|
error = OC_IO_ERR_DIR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENFILE:
|
case ENFILE:
|
||||||
case EMFILE:
|
case EMFILE:
|
||||||
error = IO_ERR_MAX_FILES;
|
error = OC_IO_ERR_MAX_FILES;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EFBIG:
|
case EFBIG:
|
||||||
error = IO_ERR_FILE_SIZE;
|
error = OC_IO_ERR_FILE_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENOSPC:
|
case ENOSPC:
|
||||||
case EDQUOT:
|
case EDQUOT:
|
||||||
error = IO_ERR_SPACE;
|
error = OC_IO_ERR_SPACE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ELOOP:
|
case ELOOP:
|
||||||
error = IO_ERR_MAX_LINKS;
|
error = OC_IO_ERR_MAX_LINKS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENAMETOOLONG:
|
case ENAMETOOLONG:
|
||||||
error = IO_ERR_PATH_LENGTH;
|
error = OC_IO_ERR_PATH_LENGTH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EOVERFLOW:
|
case EOVERFLOW:
|
||||||
error = IO_ERR_OVERFLOW;
|
error = OC_IO_ERR_OVERFLOW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error = IO_ERR_UNKNOWN;
|
error = OC_IO_ERR_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return(error);
|
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;
|
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;
|
oflags = O_RDWR;
|
||||||
}
|
}
|
||||||
|
@ -133,41 +133,41 @@ int io_convert_access_rights(file_access_rights rights)
|
||||||
oflags = O_RDONLY;
|
oflags = O_RDONLY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(rights & FILE_ACCESS_WRITE)
|
else if(rights & OC_FILE_ACCESS_WRITE)
|
||||||
{
|
{
|
||||||
oflags = O_WRONLY;
|
oflags = O_WRONLY;
|
||||||
}
|
}
|
||||||
return(oflags);
|
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;
|
int oflags = 0;
|
||||||
|
|
||||||
if(flags & FILE_OPEN_TRUNCATE)
|
if(flags & OC_FILE_OPEN_TRUNCATE)
|
||||||
{
|
{
|
||||||
oflags |= O_TRUNC;
|
oflags |= O_TRUNC;
|
||||||
}
|
}
|
||||||
if(flags & FILE_OPEN_APPEND)
|
if(flags & OC_FILE_OPEN_APPEND)
|
||||||
{
|
{
|
||||||
oflags |= O_APPEND;
|
oflags |= O_APPEND;
|
||||||
}
|
}
|
||||||
if(flags & FILE_OPEN_CREATE)
|
if(flags & OC_FILE_OPEN_CREATE)
|
||||||
{
|
{
|
||||||
oflags |= O_CREAT;
|
oflags |= O_CREAT;
|
||||||
}
|
}
|
||||||
if(flags & FILE_OPEN_NO_FOLLOW)
|
if(flags & OC_FILE_OPEN_NO_FOLLOW)
|
||||||
{
|
{
|
||||||
oflags |= O_NOFOLLOW;
|
oflags |= O_NOFOLLOW;
|
||||||
}
|
}
|
||||||
if(flags & FILE_OPEN_SYMLINK)
|
if(flags & OC_FILE_OPEN_SYMLINK)
|
||||||
{
|
{
|
||||||
oflags |= O_SYMLINK;
|
oflags |= O_SYMLINK;
|
||||||
}
|
}
|
||||||
return(oflags);
|
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;
|
struct stat s;
|
||||||
if(!fstatat(dirFd, path, &s, AT_SYMLINK_NOFOLLOW))
|
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);
|
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);
|
int flags = oc_io_convert_access_rights(accessRights);
|
||||||
flags |= io_convert_open_flags(openFlags);
|
flags |= oc_io_convert_open_flags(openFlags);
|
||||||
|
|
||||||
mode_t mode = S_IRUSR
|
mode_t mode = S_IRUSR
|
||||||
| S_IWUSR
|
| 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_IROTH
|
||||||
| S_IWOTH;
|
| 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(dirFd >= 0)
|
||||||
{
|
{
|
||||||
if(path.len && path.ptr[0] == '/')
|
if(path.len && path.ptr[0] == '/')
|
||||||
{
|
{
|
||||||
//NOTE: if path is absolute, change for a relative one, otherwise openat ignores fd.
|
//NOTE: if path is absolute, change for a relative one, otherwise openat ignores fd.
|
||||||
str8_list list = {0};
|
oc_str8_list list = {0};
|
||||||
str8_list_push(scratch.arena, &list, STR8("."));
|
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||||
str8_list_push(scratch.arena, &list, path);
|
oc_str8_list_push(scratch.arena, &list, path);
|
||||||
path = str8_list_join(scratch.arena, list);
|
path = oc_str8_list_join(scratch.arena, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
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);
|
fd = openat(dirFd, pathCStr, flags, mode);
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
|
|
||||||
return(fd);
|
return(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void io_raw_close(io_file_desc fd)
|
void oc_io_raw_close(oc_file_desc fd)
|
||||||
{
|
{
|
||||||
close(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);
|
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)
|
switch(mode & S_IFMT)
|
||||||
{
|
{
|
||||||
case S_IFIFO:
|
case S_IFIFO:
|
||||||
type = MP_FILE_FIFO;
|
type = OC_FILE_FIFO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_IFCHR:
|
case S_IFCHR:
|
||||||
type = MP_FILE_CHARACTER;
|
type = OC_FILE_CHARACTER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_IFDIR:
|
case S_IFDIR:
|
||||||
type = MP_FILE_DIRECTORY;
|
type = OC_FILE_DIRECTORY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_IFBLK:
|
case S_IFBLK:
|
||||||
type = MP_FILE_BLOCK;
|
type = OC_FILE_BLOCK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_IFREG:
|
case S_IFREG:
|
||||||
type = MP_FILE_REGULAR;
|
type = OC_FILE_REGULAR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_IFLNK:
|
case S_IFLNK:
|
||||||
type = MP_FILE_SYMLINK;
|
type = OC_FILE_SYMLINK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_IFSOCK:
|
case S_IFSOCK:
|
||||||
type = MP_FILE_SOCKET;
|
type = OC_FILE_SOCKET;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
type = MP_FILE_UNKNOWN;
|
type = OC_FILE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return(type);
|
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;
|
struct stat s;
|
||||||
if(fstat(fd, &s))
|
if(fstat(fd, &s))
|
||||||
{
|
{
|
||||||
error = io_raw_last_error();
|
error = oc_io_raw_last_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status->uid = s.st_ino;
|
status->uid = s.st_ino;
|
||||||
status->perm = io_convert_perm_from_stat(s.st_mode);
|
status->perm = oc_io_convert_perm_from_stat(s.st_mode);
|
||||||
status->type = io_convert_type_from_stat(s.st_mode);
|
status->type = oc_io_convert_type_from_stat(s.st_mode);
|
||||||
status->size = s.st_size;
|
status->size = s.st_size;
|
||||||
//TODO: times
|
//TODO: times
|
||||||
}
|
}
|
||||||
return(error);
|
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(dirFd >= 0)
|
||||||
{
|
{
|
||||||
if(path.len && path.ptr[0] == '/')
|
if(path.len && path.ptr[0] == '/')
|
||||||
{
|
{
|
||||||
str8_list list = {0};
|
oc_str8_list list = {0};
|
||||||
str8_list_push(scratch.arena, &list, STR8("."));
|
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||||
str8_list_push(scratch.arena, &list, path);
|
oc_str8_list_push(scratch.arena, &list, path);
|
||||||
path = str8_list_join(scratch.arena, list);
|
path = oc_str8_list_join(scratch.arena, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
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;
|
int statFlag = (flags & OC_FILE_OPEN_SYMLINK)? AT_SYMLINK_NOFOLLOW : 0;
|
||||||
io_error error = IO_OK;
|
oc_io_error error = OC_IO_OK;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if(fstatat(dirFd, pathCStr, &s, statFlag))
|
if(fstatat(dirFd, pathCStr, &s, statFlag))
|
||||||
{
|
{
|
||||||
error = io_raw_last_error();
|
error = oc_io_raw_last_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status->uid = s.st_ino;
|
status->uid = s.st_ino;
|
||||||
status->perm = io_convert_perm_from_stat(s.st_mode);
|
status->perm = oc_io_convert_perm_from_stat(s.st_mode);
|
||||||
status->type = io_convert_type_from_stat(s.st_mode);
|
status->type = oc_io_convert_type_from_stat(s.st_mode);
|
||||||
status->size = s.st_size;
|
status->size = s.st_size;
|
||||||
//TODO: times
|
//TODO: times
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
return(error);
|
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(dirFd >= 0)
|
||||||
{
|
{
|
||||||
if(path.len && path.ptr[0] == '/')
|
if(path.len && path.ptr[0] == '/')
|
||||||
{
|
{
|
||||||
str8_list list = {0};
|
oc_str8_list list = {0};
|
||||||
str8_list_push(scratch.arena, &list, STR8("."));
|
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||||
str8_list_push(scratch.arena, &list, path);
|
oc_str8_list_push(scratch.arena, &list, path);
|
||||||
path = str8_list_join(scratch.arena, list);
|
path = oc_str8_list_join(scratch.arena, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
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];
|
char buffer[PATH_MAX];
|
||||||
u64 bufferSize = 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)
|
if(r<0)
|
||||||
{
|
{
|
||||||
result.error = io_raw_last_error();
|
result.error = oc_io_raw_last_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.target.len = r;
|
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);
|
memcpy(result.target.ptr, buffer, result.target.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
return(result);
|
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(dirFd >= 0)
|
||||||
{
|
{
|
||||||
if(path.len && path.ptr[0] == '/')
|
if(path.len && path.ptr[0] == '/')
|
||||||
{
|
{
|
||||||
str8_list list = {0};
|
oc_str8_list list = {0};
|
||||||
str8_list_push(scratch.arena, &list, STR8("."));
|
oc_str8_list_push(scratch.arena, &list, OC_STR8("."));
|
||||||
str8_list_push(scratch.arena, &list, path);
|
oc_str8_list_push(scratch.arena, &list, path);
|
||||||
path = str8_list_join(scratch.arena, list);
|
path = oc_str8_list_join(scratch.arena, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -401,48 +401,48 @@ bool io_raw_file_exists_at(io_file_desc dirFd, str8 path, file_open_flags openFl
|
||||||
dirFd = AT_FDCWD;
|
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);
|
int r = faccessat(dirFd, pathCStr, F_OK, flags);
|
||||||
bool result = (r == 0);
|
bool result = (r == 0);
|
||||||
|
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
return(result);
|
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)
|
if(slot->fd >= 0)
|
||||||
{
|
{
|
||||||
close(slot->fd);
|
close(slot->fd);
|
||||||
}
|
}
|
||||||
file_slot_recycle(table, slot);
|
oc_file_slot_recycle(table, slot);
|
||||||
return(cmp);
|
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
|
else
|
||||||
{
|
{
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if(fstat(slot->fd, &s))
|
if(fstat(slot->fd, &s))
|
||||||
{
|
{
|
||||||
slot->error = io_raw_last_error();
|
slot->error = oc_io_raw_last_error();
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
file_status* status = (file_status*)req->buffer;
|
oc_file_status* status = (oc_file_status*)req->buffer;
|
||||||
status->perm = io_convert_perm_from_stat(s.st_mode);
|
status->perm = oc_io_convert_perm_from_stat(s.st_mode);
|
||||||
status->type = io_convert_type_from_stat(s.st_mode);
|
status->type = oc_io_convert_type_from_stat(s.st_mode);
|
||||||
status->size = s.st_size;
|
status->size = s.st_size;
|
||||||
//TODO: times
|
//TODO: times
|
||||||
}
|
}
|
||||||
|
@ -450,44 +450,44 @@ io_cmp io_fstat(file_slot* slot, io_req* req)
|
||||||
return(cmp);
|
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;
|
int whence;
|
||||||
switch(req->whence)
|
switch(req->whence)
|
||||||
{
|
{
|
||||||
case FILE_SEEK_CURRENT:
|
case OC_FILE_SEEK_CURRENT:
|
||||||
whence = SEEK_CUR;
|
whence = SEEK_CUR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_SEEK_SET:
|
case OC_FILE_SEEK_SET:
|
||||||
whence = SEEK_SET;
|
whence = SEEK_SET;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_SEEK_END:
|
case OC_FILE_SEEK_END:
|
||||||
whence = SEEK_END;
|
whence = SEEK_END;
|
||||||
}
|
}
|
||||||
cmp.result = lseek(slot->fd, req->offset, whence);
|
cmp.result = lseek(slot->fd, req->offset, whence);
|
||||||
|
|
||||||
if(cmp.result < 0)
|
if(cmp.result < 0)
|
||||||
{
|
{
|
||||||
slot->error = io_raw_last_error();
|
slot->error = oc_io_raw_last_error();
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(cmp);
|
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);
|
cmp.result = read(slot->fd, req->buffer, req->size);
|
||||||
|
|
||||||
if(cmp.result < 0)
|
if(cmp.result < 0)
|
||||||
{
|
{
|
||||||
slot->error = io_raw_last_error();
|
slot->error = oc_io_raw_last_error();
|
||||||
cmp.result = 0;
|
cmp.result = 0;
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
|
@ -495,15 +495,15 @@ io_cmp io_read(file_slot* slot, io_req* req)
|
||||||
return(cmp);
|
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);
|
cmp.result = write(slot->fd, req->buffer, req->size);
|
||||||
|
|
||||||
if(cmp.result < 0)
|
if(cmp.result < 0)
|
||||||
{
|
{
|
||||||
slot->error = io_raw_last_error();
|
slot->error = oc_io_raw_last_error();
|
||||||
cmp.result = 0;
|
cmp.result = 0;
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
|
@ -511,66 +511,66 @@ io_cmp io_write(file_slot* slot, io_req* req)
|
||||||
return(cmp);
|
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;
|
cmp.result = slot->error;
|
||||||
return(cmp);
|
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(!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
|
else if( slot->fatal
|
||||||
&& req->op != IO_OP_CLOSE
|
&& req->op != OC_IO_CLOSE
|
||||||
&& req->op != IO_OP_ERROR)
|
&& 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)
|
switch(req->op)
|
||||||
{
|
{
|
||||||
case IO_OP_OPEN_AT:
|
case OC_IO_OPEN_AT:
|
||||||
cmp = io_open_at(slot, req, table);
|
cmp = oc_io_open_at(slot, req, table);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_FSTAT:
|
case OC_IO_FSTAT:
|
||||||
cmp = io_fstat(slot, req);
|
cmp = oc_io_fstat(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_CLOSE:
|
case OC_IO_CLOSE:
|
||||||
cmp = io_close(slot, req, table);
|
cmp = oc_io_close(slot, req, table);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_READ:
|
case OC_IO_READ:
|
||||||
cmp = io_read(slot, req);
|
cmp = oc_io_read(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_WRITE:
|
case OC_IO_WRITE:
|
||||||
cmp = io_write(slot, req);
|
cmp = oc_io_write(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_SEEK:
|
case OC_IO_SEEK:
|
||||||
cmp = io_seek(slot, req);
|
cmp = oc_io_seek(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_ERROR:
|
case OC_OC_IO_ERROR:
|
||||||
cmp = io_get_error(slot, req);
|
cmp = oc_io_get_error(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cmp.error = IO_ERR_OP;
|
cmp.error = OC_IO_ERR_OP;
|
||||||
break;
|
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<signal.h> //needed for pthread_kill() on linux
|
||||||
#include<string.h>
|
#include<string.h>
|
||||||
#include<sys/time.h>
|
#include<sys/time.h>
|
||||||
|
#include<unistd.h> // nanosleep()
|
||||||
|
|
||||||
#include"platform_thread.h"
|
#include"platform_thread.h"
|
||||||
|
|
||||||
struct mp_thread
|
struct oc_thread
|
||||||
{
|
{
|
||||||
bool valid;
|
bool valid;
|
||||||
pthread_t pthread;
|
pthread_t pthread;
|
||||||
mp_thread_start_function start;
|
oc_thread_start_function start;
|
||||||
void* userPointer;
|
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;
|
oc_thread* thread = (oc_thread*)data;
|
||||||
if(strlen(thread->name))
|
if(thread->name.len)
|
||||||
{
|
{
|
||||||
pthread_setname_np(thread->name);
|
pthread_setname_np(thread->nameBuffer);
|
||||||
}
|
}
|
||||||
i32 exitCode = thread->start(thread->userPointer);
|
i32 exitCode = thread->start(thread->userPointer);
|
||||||
return((void*)(ptrdiff_t)exitCode);
|
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)
|
if(!thread)
|
||||||
{
|
{
|
||||||
return(0);
|
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';
|
*end = '\0';
|
||||||
|
thread->name = oc_str8_from_buffer(end - thread->nameBuffer, thread->nameBuffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thread->name[0] = '\0';
|
thread->nameBuffer[0] = '\0';
|
||||||
|
thread->name = oc_str8_from_buffer(0, thread->nameBuffer);
|
||||||
}
|
}
|
||||||
thread->start = start;
|
thread->start = start;
|
||||||
thread->userPointer = userPointer;
|
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);
|
free(thread);
|
||||||
return(0);
|
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);
|
return(thread->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 mp_thread_unique_id(mp_thread* thread)
|
u64 oc_thread_unique_id(oc_thread* thread)
|
||||||
{
|
{
|
||||||
u64 id;
|
u64 id;
|
||||||
pthread_threadid_np(thread->pthread, &id);
|
pthread_threadid_np(thread->pthread, &id);
|
||||||
return(id);
|
return(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 mp_thread_self_id()
|
u64 oc_thread_self_id()
|
||||||
{
|
{
|
||||||
pthread_t thread = pthread_self();
|
pthread_t thread = pthread_self();
|
||||||
u64 id;
|
u64 id;
|
||||||
|
@ -91,12 +95,12 @@ u64 mp_thread_self_id()
|
||||||
return(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));
|
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;
|
void* ret;
|
||||||
if(pthread_join(thread->pthread, &ret))
|
if(pthread_join(thread->pthread, &ret))
|
||||||
|
@ -112,7 +116,7 @@ int mp_thread_join(mp_thread* thread, i64* exitCode)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_thread_detach(mp_thread* thread)
|
int oc_thread_detach(oc_thread* thread)
|
||||||
{
|
{
|
||||||
if(pthread_detach(thread->pthread))
|
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;
|
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)
|
if(!mutex)
|
||||||
{
|
{
|
||||||
return(0);
|
return(0);
|
||||||
|
@ -143,7 +147,7 @@ mp_mutex* mp_mutex_create()
|
||||||
return(mutex);
|
return(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_mutex_destroy(mp_mutex* mutex)
|
int oc_mutex_destroy(oc_mutex* mutex)
|
||||||
{
|
{
|
||||||
if(pthread_mutex_destroy(&mutex->pmutex) != 0)
|
if(pthread_mutex_destroy(&mutex->pmutex) != 0)
|
||||||
{
|
{
|
||||||
|
@ -153,44 +157,44 @@ int mp_mutex_destroy(mp_mutex* mutex)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_mutex_lock(mp_mutex* mutex)
|
int oc_mutex_lock(oc_mutex* mutex)
|
||||||
{
|
{
|
||||||
return(pthread_mutex_lock(&mutex->pmutex));
|
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));
|
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->nextTicket = 0;
|
||||||
mutex->serving = 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);
|
u64 ticket = atomic_fetch_add(&mutex->nextTicket, 1ULL);
|
||||||
while(ticket != mutex->serving); //spin
|
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);
|
atomic_fetch_add(&mutex->serving, 1ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct mp_condition
|
struct oc_condition
|
||||||
{
|
{
|
||||||
pthread_cond_t pcond;
|
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)
|
if(!cond)
|
||||||
{
|
{
|
||||||
return(0);
|
return(0);
|
||||||
|
@ -203,7 +207,7 @@ mp_condition* mp_condition_create()
|
||||||
return(cond);
|
return(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_condition_destroy(mp_condition* cond)
|
int oc_condition_destroy(oc_condition* cond)
|
||||||
{
|
{
|
||||||
if(pthread_cond_destroy(&cond->pcond) != 0)
|
if(pthread_cond_destroy(&cond->pcond) != 0)
|
||||||
{
|
{
|
||||||
|
@ -213,12 +217,12 @@ int mp_condition_destroy(mp_condition* cond)
|
||||||
return(0);
|
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));
|
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;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, 0);
|
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));
|
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));
|
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));
|
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):
|
/*NOTE(martin):
|
||||||
Linux and MacOS don't make a distinction between reserved and committed memory, contrary to Windows
|
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));
|
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);
|
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)
|
if(base.reserve == 0)
|
||||||
{
|
{
|
||||||
base.reserve = mem_base_reserve_mmap;
|
base.reserve = oc_base_reserve_mmap;
|
||||||
base.commit = mem_base_nop;
|
base.commit = oc_base_nop;
|
||||||
base.decommit = mem_base_nop;
|
base.decommit = oc_base_nop;
|
||||||
base.release = mem_base_release_mmap;
|
base.release = oc_base_release_mmap;
|
||||||
}
|
}
|
||||||
return(&base);
|
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;
|
static u64 __performanceCounterFreq = 0;
|
||||||
|
|
||||||
void mp_clock_init()
|
void oc_clock_init()
|
||||||
{
|
{
|
||||||
LARGE_INTEGER freq;
|
LARGE_INTEGER freq;
|
||||||
QueryPerformanceFrequency(&freq);
|
QueryPerformanceFrequency(&freq);
|
||||||
__performanceCounterFreq = freq.QuadPart;
|
__performanceCounterFreq = freq.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 mp_get_time(mp_clock_kind clock)
|
f64 oc_clock_time(oc_clock_kind clock)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER counter;
|
LARGE_INTEGER counter;
|
||||||
QueryPerformanceCounter(&counter);
|
QueryPerformanceCounter(&counter);
|
||||||
|
|
|
@ -15,72 +15,72 @@
|
||||||
#include"platform_io_internal.c"
|
#include"platform_io_internal.c"
|
||||||
#include"platform_io_common.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();
|
int winError = GetLastError();
|
||||||
switch(winError)
|
switch(winError)
|
||||||
{
|
{
|
||||||
case ERROR_SUCCESS:
|
case ERROR_SUCCESS:
|
||||||
error = IO_OK;
|
error = OC_IO_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_ACCESS_DENIED:
|
case ERROR_ACCESS_DENIED:
|
||||||
error = IO_ERR_PERM;
|
error = OC_IO_ERR_PERM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_FILE_NOT_FOUND:
|
case ERROR_FILE_NOT_FOUND:
|
||||||
case ERROR_PATH_NOT_FOUND:
|
case ERROR_PATH_NOT_FOUND:
|
||||||
case ERROR_INVALID_DRIVE:
|
case ERROR_INVALID_DRIVE:
|
||||||
case ERROR_DIRECTORY:
|
case ERROR_DIRECTORY:
|
||||||
error = IO_ERR_NO_ENTRY;
|
error = OC_IO_ERR_NO_ENTRY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_TOO_MANY_OPEN_FILES:
|
case ERROR_TOO_MANY_OPEN_FILES:
|
||||||
error = IO_ERR_MAX_FILES;
|
error = OC_IO_ERR_MAX_FILES;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_NOT_ENOUGH_MEMORY:
|
case ERROR_NOT_ENOUGH_MEMORY:
|
||||||
case ERROR_OUTOFMEMORY:
|
case ERROR_OUTOFMEMORY:
|
||||||
error = IO_ERR_MEM;
|
error = OC_IO_ERR_MEM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_DEV_NOT_EXIST:
|
case ERROR_DEV_NOT_EXIST:
|
||||||
error = IO_ERR_NO_DEVICE;
|
error = OC_IO_ERR_NO_DEVICE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_FILE_EXISTS:
|
case ERROR_FILE_EXISTS:
|
||||||
case ERROR_ALREADY_EXISTS:
|
case ERROR_ALREADY_EXISTS:
|
||||||
error = IO_ERR_EXISTS;
|
error = OC_IO_ERR_EXISTS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_BUFFER_OVERFLOW:
|
case ERROR_BUFFER_OVERFLOW:
|
||||||
case ERROR_FILENAME_EXCED_RANGE:
|
case ERROR_FILENAME_EXCED_RANGE:
|
||||||
error = IO_ERR_PATH_LENGTH;
|
error = OC_IO_ERR_PATH_LENGTH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERROR_FILE_TOO_LARGE:
|
case ERROR_FILE_TOO_LARGE:
|
||||||
error = IO_ERR_FILE_SIZE;
|
error = OC_IO_ERR_FILE_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//TODO: complete
|
//TODO: complete
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error = IO_ERR_UNKNOWN;
|
error = OC_IO_ERR_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return(error);
|
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);
|
res.len = GetFinalPathNameByHandleW(handle, NULL, 0, FILE_NAME_NORMALIZED);
|
||||||
if(res.len)
|
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))
|
if(!GetFinalPathNameByHandleW(handle, res.ptr, res.len, FILE_NAME_NORMALIZED))
|
||||||
{
|
{
|
||||||
res.len = 0;
|
res.len = 0;
|
||||||
|
@ -90,36 +90,36 @@ str16 win32_path_from_handle_null_terminated(mem_arena* arena, HANDLE handle)
|
||||||
return(res);
|
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);
|
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);
|
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};
|
oc_str16 result = {0};
|
||||||
mem_arena_scope scratch = mem_scratch_begin_next(arena);
|
oc_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||||
|
|
||||||
str16 dirPathW = win32_path_from_handle_null_terminated(scratch.arena, dirFd);
|
oc_str16 dirPathW = win32_path_from_handle_null_terminated(scratch.arena, dirFd);
|
||||||
str16 pathW = win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||||
|
|
||||||
if(dirPathW.len && pathW.len)
|
if(dirPathW.len && pathW.len)
|
||||||
{
|
{
|
||||||
u64 fullPathWSize = 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));
|
memcpy(fullPathW, dirPathW.ptr, (dirPathW.len-1)*sizeof(u16));
|
||||||
fullPathW[dirPathW.len-1] = '\\';
|
fullPathW[dirPathW.len-1] = '\\';
|
||||||
memcpy(fullPathW + dirPathW.len, pathW.ptr, pathW.len*sizeof(u16));
|
memcpy(fullPathW + dirPathW.len, pathW.ptr, pathW.len*sizeof(u16));
|
||||||
|
|
||||||
result.len = fullPathWSize;
|
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))
|
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;
|
result.len = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
|
|
||||||
return(result);
|
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;
|
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
|
DWORD win32AttributeFlags = FILE_ATTRIBUTE_NORMAL
|
||||||
| FILE_FLAG_BACKUP_SEMANTICS;
|
| FILE_FLAG_BACKUP_SEMANTICS;
|
||||||
|
|
||||||
if(accessRights & FILE_ACCESS_READ)
|
if(accessRights & OC_FILE_ACCESS_READ)
|
||||||
{
|
{
|
||||||
win32AccessFlags |= GENERIC_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;
|
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;
|
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;
|
win32CreateFlags |= TRUNCATE_EXISTING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(openFlags & FILE_OPEN_CREATE)
|
if(openFlags & OC_FILE_OPEN_CREATE)
|
||||||
{
|
{
|
||||||
if(!(win32CreateFlags & CREATE_ALWAYS))
|
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;
|
win32CreateFlags |= OPEN_EXISTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(openFlags & FILE_OPEN_SYMLINK)
|
if(openFlags & OC_FILE_OPEN_SYMLINK)
|
||||||
{
|
{
|
||||||
win32AttributeFlags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
win32AttributeFlags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_arena_scope scratch = mem_scratch_begin();
|
oc_arena_scope scratch = oc_scratch_begin();
|
||||||
str16 pathW = win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||||
|
|
||||||
if(dirFd == NULL || dirFd == INVALID_HANDLE_VALUE)
|
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
|
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)
|
if(fullPathW.len)
|
||||||
{
|
{
|
||||||
handle = CreateFileW(fullPathW.ptr, win32AccessFlags, win32ShareMode, NULL, win32CreateFlags, win32AttributeFlags, NULL);
|
handle = CreateFileW(fullPathW.ptr, win32AccessFlags, win32ShareMode, NULL, win32CreateFlags, win32AttributeFlags, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
return(handle);
|
return(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void io_raw_close(io_file_desc fd)
|
void oc_io_raw_close(oc_file_desc fd)
|
||||||
{
|
{
|
||||||
CloseHandle(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;
|
bool result = false;
|
||||||
io_file_desc fd = io_raw_open_at(dirFd, path, FILE_ACCESS_NONE, (openFlags & FILE_OPEN_SYMLINK));
|
oc_file_desc fd = oc_io_raw_open_at(dirFd, path, OC_FILE_ACCESS_NONE, (openFlags & OC_FILE_OPEN_SYMLINK));
|
||||||
if(!io_file_desc_is_nil(fd))
|
if(!oc_file_desc_is_nil(fd))
|
||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
io_raw_close(fd);
|
oc_io_raw_close(fd);
|
||||||
}
|
}
|
||||||
return(result);
|
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;
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
if(!GetFileInformationByHandle(fd, &info))
|
if(!GetFileInformationByHandle(fd, &info))
|
||||||
{
|
{
|
||||||
error = io_raw_last_error();
|
error = oc_io_raw_last_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -260,53 +260,53 @@ io_error io_raw_fstat(io_file_desc fd, file_status* status)
|
||||||
FILE_ATTRIBUTE_TAG_INFO tagInfo;
|
FILE_ATTRIBUTE_TAG_INFO tagInfo;
|
||||||
if(!GetFileInformationByHandleEx(fd, FileAttributeTagInfo, &tagInfo, sizeof(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)
|
else if(tagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||||
{
|
{
|
||||||
status->type = MP_FILE_SYMLINK;
|
status->type = OC_FILE_SYMLINK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status->type = MP_FILE_UNKNOWN;
|
status->type = OC_FILE_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
else if(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
status->type = MP_FILE_DIRECTORY;
|
status->type = OC_FILE_DIRECTORY;
|
||||||
}
|
}
|
||||||
else if(info.dwFileAttributes & attrRegularSet)
|
else if(info.dwFileAttributes & attrRegularSet)
|
||||||
{
|
{
|
||||||
status->type = MP_FILE_REGULAR;
|
status->type = OC_FILE_REGULAR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TODO: might want to check for socket/block/character devices? (otoh MS STL impl. doesn't seem to do it)
|
//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))
|
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
|
//TODO: times
|
||||||
}
|
}
|
||||||
return(error);
|
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;
|
oc_io_error error = OC_IO_OK;
|
||||||
io_file_desc fd = io_raw_open_at(dirFd, name, FILE_ACCESS_NONE, FILE_OPEN_SYMLINK);
|
oc_file_desc fd = oc_io_raw_open_at(dirFd, name, OC_FILE_ACCESS_NONE, OC_FILE_OPEN_SYMLINK);
|
||||||
if(io_file_desc_is_nil(fd))
|
if(oc_file_desc_is_nil(fd))
|
||||||
{
|
{
|
||||||
error = io_raw_last_error();
|
error = oc_io_raw_last_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = io_raw_fstat(fd, status);
|
error = oc_io_raw_fstat(fd, status);
|
||||||
io_raw_close(fd);
|
oc_io_raw_close(fd);
|
||||||
}
|
}
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
|
@ -342,88 +342,88 @@ typedef struct
|
||||||
UCHAR DataBuffer[1];
|
UCHAR DataBuffer[1];
|
||||||
} GenericReparseBuffer;
|
} 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];
|
char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||||
DWORD bytesReturned;
|
DWORD bytesReturned;
|
||||||
|
|
||||||
if(!DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned, 0))
|
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
|
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)
|
if(reparse->ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||||
{
|
{
|
||||||
str16 nameW = {0};
|
oc_str16 nameW = {0};
|
||||||
nameW.len = reparse->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
|
nameW.len = reparse->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
|
||||||
nameW.ptr = (u16*)((char*)reparse->SymbolicLinkReparseBuffer.PathBuffer + reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset);
|
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
|
else
|
||||||
{
|
{
|
||||||
result.error = IO_ERR_UNKNOWN;
|
result.error = OC_IO_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(result);
|
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);
|
oc_file_desc fd = oc_io_raw_open_at(dirFd, name, OC_FILE_ACCESS_READ, OC_FILE_OPEN_SYMLINK);
|
||||||
io_raw_read_link_result result = io_raw_read_link(arena, fd);
|
oc_io_raw_read_link_result result = oc_io_raw_read_link(arena, fd);
|
||||||
io_raw_close(fd);
|
oc_io_raw_close(fd);
|
||||||
return(result);
|
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)
|
if(slot->fd)
|
||||||
{
|
{
|
||||||
CloseHandle(slot->fd);
|
CloseHandle(slot->fd);
|
||||||
}
|
}
|
||||||
file_slot_recycle(table, slot);
|
oc_file_slot_recycle(table, slot);
|
||||||
return(cmp);
|
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
|
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;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
return(cmp);
|
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;
|
DWORD whence;
|
||||||
switch(req->whence)
|
switch(req->whence)
|
||||||
{
|
{
|
||||||
case FILE_SEEK_CURRENT:
|
case OC_FILE_SEEK_CURRENT:
|
||||||
whence = FILE_CURRENT;
|
whence = FILE_CURRENT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_SEEK_SET:
|
case OC_FILE_SEEK_SET:
|
||||||
whence = FILE_BEGIN;
|
whence = FILE_BEGIN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_SEEK_END:
|
case OC_FILE_SEEK_END:
|
||||||
whence = FILE_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))
|
if(!SetFilePointerEx(slot->fd, off, &newPos, whence))
|
||||||
{
|
{
|
||||||
slot->error = io_raw_last_error();
|
slot->error = oc_io_raw_last_error();
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -443,13 +443,13 @@ io_cmp io_seek(file_slot* slot, io_req* req)
|
||||||
return(cmp);
|
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;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
else
|
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))
|
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.result = 0;
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
|
@ -470,13 +470,13 @@ io_cmp io_read(file_slot* slot, io_req* req)
|
||||||
return(cmp);
|
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;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
else
|
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))
|
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.result = 0;
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
|
@ -497,64 +497,64 @@ io_cmp io_write(file_slot* slot, io_req* req)
|
||||||
return(cmp);
|
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;
|
cmp.result = slot->error;
|
||||||
return(cmp);
|
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(!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)
|
switch(req->op)
|
||||||
{
|
{
|
||||||
case IO_OP_OPEN_AT:
|
case OC_IO_OPEN_AT:
|
||||||
cmp = io_open_at(slot, req, table);
|
cmp = oc_io_open_at(slot, req, table);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_FSTAT:
|
case OC_IO_FSTAT:
|
||||||
cmp = io_fstat(slot, req);
|
cmp = oc_io_fstat(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_CLOSE:
|
case OC_IO_CLOSE:
|
||||||
cmp = io_close(slot, req, table);
|
cmp = oc_io_close(slot, req, table);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_READ:
|
case OC_IO_READ:
|
||||||
cmp = io_read(slot, req);
|
cmp = oc_io_read(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_WRITE:
|
case OC_IO_WRITE:
|
||||||
cmp = io_write(slot, req);
|
cmp = oc_io_write(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_SEEK:
|
case OC_IO_SEEK:
|
||||||
cmp = io_seek(slot, req);
|
cmp = oc_io_seek(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_OP_ERROR:
|
case OC_OC_IO_ERROR:
|
||||||
cmp = io_get_error(slot, req);
|
cmp = oc_io_get_error(slot, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cmp.error = IO_ERR_OP;
|
cmp.error = OC_IO_ERR_OP;
|
||||||
if(slot)
|
if(slot)
|
||||||
{
|
{
|
||||||
slot->error = cmp.error;
|
slot->error = cmp.error;
|
||||||
|
|
|
@ -10,36 +10,36 @@
|
||||||
#include<windows.h>
|
#include<windows.h>
|
||||||
#include"platform_memory.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);
|
void* result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
||||||
return(result);
|
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);
|
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);
|
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);
|
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)
|
if(base.reserve == 0)
|
||||||
{
|
{
|
||||||
base.reserve = mem_base_reserve_win32;
|
base.reserve = oc_base_reserve_win32;
|
||||||
base.commit = mem_base_commit_win32;
|
base.commit = oc_base_commit_win32;
|
||||||
base.decommit = mem_base_decommit_win32;
|
base.decommit = oc_base_decommit_win32;
|
||||||
base.release = mem_base_release_win32;
|
base.release = oc_base_release_win32;
|
||||||
}
|
}
|
||||||
return(&base);
|
return(&base);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,23 +10,23 @@
|
||||||
#include"win32_string_helpers.h"
|
#include"win32_string_helpers.h"
|
||||||
#include"platform_path.c"
|
#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();
|
oc_arena_scope scratch = oc_scratch_begin();
|
||||||
str16 pathW = win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path);
|
||||||
bool result = !PathIsRelativeW(pathW.ptr);
|
bool result = !PathIsRelativeW(pathW.ptr);
|
||||||
|
|
||||||
mem_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
str8 path_executable(mem_arena* arena)
|
oc_str8 oc_path_executable(oc_arena* arena)
|
||||||
{
|
{
|
||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
//TODO use wide chars
|
//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);
|
int size = GetModuleFileName(NULL, buffer, MAX_PATH+1);
|
||||||
//TODO: check for errors...
|
//TODO: check for errors...
|
||||||
for(int i=0; i<size; i++)
|
for(int i=0; i<size; i++)
|
||||||
|
@ -36,7 +36,7 @@ str8 path_executable(mem_arena* arena)
|
||||||
buffer[i] = '/';
|
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"
|
#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.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);
|
MultiByteToWideChar(CP_UTF8, 0, s.ptr, s.len, res.ptr, res.len);
|
||||||
res.ptr[res.len-1] = '\0';
|
res.ptr[res.len-1] = '\0';
|
||||||
return(res);
|
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.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);
|
WideCharToMultiByte(CP_UTF8, 0, s.ptr, s.len, res.ptr, res.len, NULL, NULL);
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
|
|
||||||
#include"util/strings.h"
|
#include"util/strings.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);
|
||||||
str8 win32_wide_to_utf8(mem_arena* arena, str16 s);
|
oc_str8 oc_win32_wide_to_utf8(oc_arena* arena, oc_str16 s);
|
||||||
|
|
||||||
|
|
||||||
#endif // __WIN32_STRING_HELPERS_H_
|
#endif // __WIN32_STRING_HELPERS_H_
|
||||||
|
|
|
@ -12,36 +12,39 @@
|
||||||
|
|
||||||
#include"platform_thread.h"
|
#include"platform_thread.h"
|
||||||
|
|
||||||
struct mp_thread
|
struct oc_thread
|
||||||
{
|
{
|
||||||
mp_thread_start_function start;
|
oc_thread_start_function start;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
DWORD threadId;
|
DWORD threadId;
|
||||||
void* userPointer;
|
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);
|
i32 exitCode = thread->start(thread->userPointer);
|
||||||
return(exitCode);
|
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->start = start;
|
||||||
thread->handle = INVALID_HANDLE_VALUE;
|
thread->handle = INVALID_HANDLE_VALUE;
|
||||||
thread->userPointer = userPointer;
|
thread->userPointer = userPointer;
|
||||||
if(name)
|
if(name.len && name.ptr)
|
||||||
{
|
{
|
||||||
char* end = strncpy(thread->name, name, MP_THREAD_NAME_MAX_SIZE-1);
|
strncpy(thread->nameBuffer, name.ptr, oc_min(name.len, OC_THREAD_NAME_MAX_SIZE-1));
|
||||||
*end = '\0';
|
thread->nameBuffer[OC_THREAD_NAME_MAX_SIZE-1] = '\0';
|
||||||
|
thread->name = OC_STR8(thread->nameBuffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thread->name[0] = '\0';
|
thread->nameBuffer[0] = '\0';
|
||||||
|
thread->name = oc_str8_from_buffer(0, thread->nameBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES childProcessSecurity = {
|
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
|
SIZE_T stackSize = 0; // uses process default
|
||||||
DWORD flags = 0;
|
DWORD flags = 0;
|
||||||
DWORD threadId = 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) {
|
if (thread->handle == NULL) {
|
||||||
free(thread);
|
free(thread);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
@ -59,9 +62,9 @@ mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* user
|
||||||
|
|
||||||
thread->threadId = threadId;
|
thread->threadId = threadId;
|
||||||
|
|
||||||
if (thread->name[0]) {
|
if (thread->name.len) {
|
||||||
wchar_t widename[MP_THREAD_NAME_MAX_SIZE];
|
wchar_t widename[OC_THREAD_NAME_MAX_SIZE];
|
||||||
size_t length = mbstowcs(widename, thread->name, MP_THREAD_NAME_MAX_SIZE - 1);
|
size_t length = mbstowcs(widename, thread->nameBuffer, OC_THREAD_NAME_MAX_SIZE - 1);
|
||||||
widename[length] = '\0';
|
widename[length] = '\0';
|
||||||
|
|
||||||
SetThreadDescription(thread->handle, widename);
|
SetThreadDescription(thread->handle, widename);
|
||||||
|
@ -70,33 +73,33 @@ mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* user
|
||||||
return(thread);
|
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);
|
return(thread->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 mp_thread_unique_id(mp_thread* thread)
|
u64 oc_thread_unique_id(oc_thread* thread)
|
||||||
{
|
{
|
||||||
return(thread->threadId);
|
return(thread->threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 mp_thread_self_id()
|
u64 oc_thread_self_id()
|
||||||
{
|
{
|
||||||
return(GetCurrentThreadId());
|
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);
|
BOOL success = TerminateThread(thread->handle, (DWORD)sig);
|
||||||
return(success ? 0 : -1);
|
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);
|
DWORD result = WaitForSingleObject(thread->handle, INFINITE);
|
||||||
if (result == WAIT_FAILED) {
|
if (result == WAIT_FAILED) {
|
||||||
|
@ -116,7 +119,7 @@ int mp_thread_join(mp_thread* thread, i64* exitCode)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_thread_detach(mp_thread* thread)
|
int oc_thread_detach(oc_thread* thread)
|
||||||
{
|
{
|
||||||
if (CloseHandle(thread->handle))
|
if (CloseHandle(thread->handle))
|
||||||
{
|
{
|
||||||
|
@ -127,86 +130,86 @@ int mp_thread_detach(mp_thread* thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct mp_mutex
|
struct oc_mutex
|
||||||
{
|
{
|
||||||
u64 owningThreadId;
|
u64 owningThreadId;
|
||||||
SRWLOCK lock;
|
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;
|
mutex->owningThreadId = 0;
|
||||||
InitializeSRWLock(&mutex->lock);
|
InitializeSRWLock(&mutex->lock);
|
||||||
return mutex;
|
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);
|
free(mutex);
|
||||||
return(0);
|
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);
|
AcquireSRWLockExclusive(&mutex->lock);
|
||||||
return(0);
|
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);
|
ReleaseSRWLockExclusive(&mutex->lock);
|
||||||
mutex->owningThreadId = 0;
|
mutex->owningThreadId = 0;
|
||||||
return(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->nextTicket = 0;
|
||||||
mutex->serving = 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);
|
u64 ticket = atomic_fetch_add(&mutex->nextTicket, 1ULL);
|
||||||
while(ticket != mutex->serving); //spin
|
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);
|
atomic_fetch_add(&mutex->serving, 1ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct mp_condition
|
struct oc_condition
|
||||||
{
|
{
|
||||||
CONDITION_VARIABLE cond;
|
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);
|
InitializeConditionVariable(&cond->cond);
|
||||||
return cond;
|
return cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_condition_destroy(mp_condition* cond)
|
int oc_condition_destroy(oc_condition* cond)
|
||||||
{
|
{
|
||||||
free(cond);
|
free(cond);
|
||||||
return(0);
|
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;
|
const f32 ms = (seconds == INFINITY) ? INFINITE : seconds * 1000;
|
||||||
if (!SleepConditionVariableSRW(&cond->cond, &mutex->lock, ms, 0))
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_condition_signal(mp_condition* cond)
|
int oc_condition_signal(oc_condition* cond)
|
||||||
{
|
{
|
||||||
WakeConditionVariable(&cond->cond);
|
WakeConditionVariable(&cond->cond);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_condition_broadcast(mp_condition* cond)
|
int oc_condition_broadcast(oc_condition* cond)
|
||||||
{
|
{
|
||||||
WakeAllConditionVariable(&cond->cond);
|
WakeAllConditionVariable(&cond->cond);
|
||||||
return(0);
|
return(0);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue