Compare commits

..

No commits in common. "0ee8e3904a33d9b7789c186fcf1220d5705f19d1" and "7359649465158670feb917bafc0de54caa5eb2e4" have entirely different histories.

39 changed files with 2584 additions and 4136 deletions

View File

@ -26,55 +26,5 @@ Welcome to the 4coder community repository.
1. `$ cd 4cc/code`
2. `$ ./bin/build-linux.sh`
## Mac
> 4coder targets x86_64. If you are using a M1+ ARM CPU you need to prefix the build scripts commands with: `arch -arch x86_64`
1. Use the `package-mac.sh` script from the code directory (this builds a distribution in the `distributions` directory with all the non-binary dependencies)
1. `$ cd 4cc/code`
2. `$ ./bin/package-mac.sh`
2. You can also use the `build-mac.sh` script if you want just build the binaries, (this produces the build artifacts in the `build` directory, this doesn't produce a functional distribution)
1. `$ cd 4cc/code`
2. `$ ./bin/build-mac.sh`
### Older Macs, 10.15.7 Catalina
If you are using an older version of mac, such as 10.15.7 Catalina you need to install the realpath command:
1. `$ sudo port install coreutils`
2. macports names the `realpath` command `grealpath`, so make a symbolic link in order to use build-mac.sh:
`$ sudo ln -s /opt/local/bin/grealpath /opt/local/bin/realpath`
## Build script parameter
The build script accepts a parameter (mutually exclusive):
- `/DDEV_BUILD` or `/DDEV_BUILD_X86` (default value) : build without optimizations.
Produces debug symbols.
Defines: `FRED_INTERNAL`, `FRED_SUPER`, `DO_CRAZY_EXPENSIVE_ASSERTS` (on Windows) macros.
- `/DOPT_BUILD` or `/DOPT_BUILD_X86` (similar to `build_optimized` script): build with optimizations.
Doesn't produce debug symbols.
Defines `FRED_SUPER` macro.
- `/DPACKAGE_SUPER_X64` or `/DPACKAGE_SUPER_X86` (similar to `package` script): package 4coder for distribution.
Turns on optimizations.
Produces debug symbols.
Defines `SHIP_MODE`, `FRED_SUPER`, `DO_CRAZY_EXPENSIVE_ASSERTS` (on Windows) macros.
- `/DPACKAGE_DEMO_X64` or `/DPACKAGE_DEMO_X86`: packages 4coder demo for distribution.
Turns on optimizations.
Produces debug symbols.
Defines `SHIP_MODE`, `DO_CRAZY_EXPENSIVE_ASSERTS` (on Windows) macros.
## API generators
4coder uses several small programs to generate some headers and source files. Those do not run automatically, you must build them and run them when needed (which shouldn't really happen).
- `code\4ed_font_api.cpp` creates, in `code\generated`, `font_api.h`, `font_api.cpp`, `font_api_constructor.cpp` (not used) and `font_api_master_list.h` (not used);
- `code\4ed_graphics_api.cpp` creates, in `code\generated`, `graphics_api.h` and `graphics_api.cpp`, `graphics_api_constructor.cpp` (not used) and `graphics_api_master_list.h` (not used);
- `code\4ed_system_api.cpp` creates, in `code\custom\generated`, `system_api.h`, `system_api.cpp`, `system_api_constructor.cpp`, `system_api_master_list.h`;
- `code\4ed_api_parser_main.cpp` is a little different, as it parses source files passed as parameters to search for functions and type preceded by `api(some_api_name)` and creates 4 files in the `code\custom\generated`. It is used to generate `custom_api.h`, `custom_api.cpp`, `custom_api_constructor.cpp` and `custom_api_master_list.h` by passing `code\4ed_api_implementation.cpp` as a parameter.
You need to compile one of those file and run it from the `code` directory.
There is also `code\4ed_api_check.cpp` to verify the generated file but it's not clear at the moment what to check against.
- `code\4ed_generate_keycodes.cpp` is also a bit appart as it generates `code\custom\generated\4coder_event_codes.h` which are keyboard key codes and some event hook ids.
## Mac (Untested)
1. The steps should be the same as linux but replace the `*-linux.sh` with their `*-mac.sh` equivalents.

View File

@ -208,10 +208,7 @@ api_get_callable_name(Arena *arena, String_Const_u8 api_name, String_Const_u8 na
////////////////////////////////
function void
generate_api_master_list(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out, String_Const_u8 generated_by){
fprintf(out, "/* Generated by \"%.*s\" */\n\n", string_expand(generated_by));
generate_api_master_list(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
for (API_Call *call = api->first_call;
call != 0;
call = call->next){
@ -239,10 +236,7 @@ generate_api_master_list(Arena *scratch, API_Definition *api, API_Generation_Fla
}
function void
generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out, String_Const_u8 generated_by){
fprintf(out, "/* Generated by \"%.*s\" */\n\n", string_expand(generated_by));
generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
for (API_Call *call = api->first_call;
call != 0;
call = call->next){
@ -270,8 +264,6 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
fprintf(out, ")\n");
}
fprintf(out, "\n");
for (API_Call *call = api->first_call;
call != 0;
call = call->next){
@ -297,13 +289,11 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
fprintf(out, ");\n");
}
fprintf(out, "\n");
fprintf(out, "struct API_VTable_%.*s{\n", string_expand(api->name));
for (API_Call *call = api->first_call;
call != 0;
call = call->next){
fprintf(out, " %.*s_%.*s_type *",
fprintf(out, "%.*s_%.*s_type *",
string_expand(api->name),
string_expand(call->name));
fprintf(out, "%.*s",
@ -312,8 +302,6 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
}
fprintf(out, "};\n");
fprintf(out, "\n");
fprintf(out, "#if defined(STATIC_LINK_API)\n");
for (API_Call *call = api->first_call;
call != 0;
@ -340,7 +328,6 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
fprintf(out, ");\n");
}
fprintf(out, "#undef STATIC_LINK_API\n");
fprintf(out, "\n");
fprintf(out, "#elif defined(DYNAMIC_LINK_API)\n");
for (API_Call *call = api->first_call;
call != 0;
@ -356,10 +343,7 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
}
function void
generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out, String_Const_u8 generated_by){
fprintf(out, "/* Generated by \"%.*s\" */\n\n", string_expand(generated_by));
generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
fprintf(out, "function void\n");
fprintf(out, "%.*s_api_fill_vtable(API_VTable_%.*s *vtable){\n",
string_expand(api->name),
@ -368,12 +352,11 @@ generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FIL
call != 0;
call = call->next){
String_Const_u8 callable_name = api_get_callable_name(scratch, api->name, call->name, flags);
fprintf(out, " vtable->%.*s = %.*s;\n",
fprintf(out, "vtable->%.*s = %.*s;\n",
string_expand(call->name),
string_expand(callable_name));
}
fprintf(out, "}\n");
fprintf(out, "\n");
fprintf(out, "#if defined(DYNAMIC_LINK_API)\n");
fprintf(out, "function void\n");
@ -384,7 +367,7 @@ generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FIL
call != 0;
call = call->next){
String_Const_u8 callable_name = api_get_callable_name(scratch, api->name, call->name, flags);
fprintf(out, " %.*s = vtable->%.*s;\n",
fprintf(out, "%.*s = vtable->%.*s;\n",
string_expand(callable_name),
string_expand(call->name));
}
@ -394,21 +377,18 @@ generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FIL
}
function void
generate_constructor(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out, String_Const_u8 generated_by){
fprintf(out, "/* Generated by \"%.*s\" */\n\n", string_expand(generated_by));
generate_constructor(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
fprintf(out, "function API_Definition*\n");
fprintf(out, "%.*s_api_construct(Arena *arena){\n",
string_expand(api->name));
fprintf(out, " API_Definition *result = begin_api(arena, \"%.*s\");\n",
fprintf(out, "API_Definition *result = begin_api(arena, \"%.*s\");\n",
string_expand(api->name));
for (API_Call *call = api->first_call;
call != 0;
call = call->next){
fprintf(out, " {\n");
fprintf(out, " API_Call *call = api_call_with_location(arena, result, "
fprintf(out, "{\n");
fprintf(out, "API_Call *call = api_call_with_location(arena, result, "
"string_u8_litexpr(\"%.*s\"), "
"string_u8_litexpr(\"%.*s\"), "
"string_u8_litexpr(\"\"));\n",
@ -416,29 +396,29 @@ generate_constructor(Arena *scratch, API_Definition *api, API_Generation_Flag fl
string_expand(call->return_type));
if (call->params.count == 0){
fprintf(out, " (void)call;\n");
fprintf(out, "(void)call;\n");
}
else{
for (API_Param *param = call->params.first;
param != 0;
param = param->next){
fprintf(out, " api_param(arena, call, \"%.*s\", \"%.*s\");\n",
fprintf(out, "api_param(arena, call, \"%.*s\", \"%.*s\");\n",
string_expand(param->type_name),
string_expand(param->name));
}
}
fprintf(out, " }\n");
fprintf(out, "}\n");
}
fprintf(out, " return(result);\n");
fprintf(out, "return(result);\n");
fprintf(out, "}\n");
}
////////////////////////////////
function b32
api_definition_generate_api_includes(Arena *arena, API_Definition *api, Generated_Group group, API_Generation_Flag flags, String_Const_u8 generated_by){
api_definition_generate_api_includes(Arena *arena, API_Definition *api, Generated_Group group, API_Generation_Flag flags){
// NOTE(allen): Arrange output files
String_Const_u8 path_to_self = string_u8_litexpr(__FILE__);
@ -514,10 +494,10 @@ api_definition_generate_api_includes(Arena *arena, API_Definition *api, Generate
// NOTE(allen): Generate output
generate_api_master_list(arena, api, flags, out_file_ml, generated_by);
generate_header(arena, api, flags, out_file_h, generated_by);
generate_cpp(arena, api, flags, out_file_cpp, generated_by);
generate_constructor(arena, api, flags, out_file_con, generated_by);
generate_api_master_list(arena, api, flags, out_file_ml);
generate_header(arena, api, flags, out_file_h);
generate_cpp(arena, api, flags, out_file_cpp);
generate_constructor(arena, api, flags, out_file_con);
////////////////////////////////
@ -614,7 +594,7 @@ api_definition_check(Arena *arena, API_Definition *correct, API_Definition *remo
API_Call *correct_call = api_get_call(correct, call->name);
if (correct_call == 0 && report_extra){
api_definition_error(arena, error_list,
"remote call", call,
"remote call", call,
"does not exist in api master");
}
}

View File

@ -31,7 +31,7 @@ int
main(void){
Arena arena = make_arena_malloc();
API_Definition *api = define_api(&arena);
if (!api_definition_generate_api_includes(&arena, api, get_api_group(), 0, SCu8(GENERATED_BY))){
if (!api_definition_generate_api_includes(&arena, api, get_api_group(), 0)){
return(1);
}
return(0);

View File

@ -37,21 +37,9 @@ main(int argc, char **argv){
exit(1);
}
String_Const_u8 exe = SCu8("code/4ed_api_parser_main.exe");
u32 command_line_length = exe.size;
for (i32 i = 1; i < argc; i+=1){
command_line_length += 1 + cstring_length(argv[i]);
}
String_u8 command_line = string_u8_push(&arena, command_line_length );
string_append(&command_line, exe);
API_Definition_List list = {};
for (i32 i = 1; i < argc; i += 1){
char *file_name = argv[i];
string_append_character(&command_line, ' ');
string_append(&command_line, SCu8(argv[i]));
FILE *file = fopen(file_name, "rb");
if (file == 0){
printf("error: could not open input file: '%s'\n", argv[i]);
@ -69,7 +57,7 @@ main(int argc, char **argv){
for (API_Definition *node = list.first;
node != 0;
node = node->next){
api_definition_generate_api_includes(&arena, node, GeneratedGroup_Custom, APIGeneration_NoAPINameOnCallables, SCu8(command_line));
api_definition_generate_api_includes(&arena, node, GeneratedGroup_Custom, APIGeneration_NoAPINameOnCallables);
}
}

View File

@ -368,9 +368,6 @@ edit_change_current_history_state(Thread_Context *tctx, Models *models, Editing_
}
file->state.current_record_index = current;
if (file->state.saved_record_index == current){
RemFlag(file->state.dirty, DirtyState_UnsavedChanges);
}
}
}

View File

@ -155,7 +155,6 @@ save_file_to_name(Thread_Context *tctx, Models *models, Editing_File *file, u8 *
File_Attributes new_attributes = system_save_file(scratch, (char*)file_name, saveable_string);
if (new_attributes.last_write_time > 0 &&
using_actual_file_name){
file->state.saved_record_index = file->state.current_record_index;
file->state.save_state = FileSaveState_SavedWaitingForNotification;
file_clear_dirty_flags(file);
}

View File

@ -47,8 +47,6 @@ struct Editing_File_State{
History history;
i32 current_record_index;
i32 saved_record_index;
Dirty_State dirty;
File_Save_State save_state;

View File

@ -9,8 +9,6 @@
// TOP
#define GENERATED_BY "code/4ed_font_api.cpp"
#include "4ed_api_definition_main.cpp"
function API_Definition*

View File

@ -33,13 +33,13 @@ ft__load_flags(b32 use_hinting){
internal FT_Codepoint_Index_Pair_Array
ft__get_codepoint_index_pairs(Arena *arena, FT_Face face, u16 *maximum_index_out){
FT_Long glyph_count = face->num_glyphs;
FT_Codepoint_Index_Pair_Array array = {};
array.count = glyph_count;
array.vals = push_array(arena, FT_Codepoint_Index_Pair, glyph_count);
u16 maximum_index = 0;
i32 counter = 0;
FT_UInt index = 0;
FT_ULong codepoint = FT_Get_First_Char(face, &index);
@ -57,22 +57,22 @@ ft__get_codepoint_index_pairs(Arena *arena, FT_Face face, u16 *maximum_index_out
break;
}
}
*maximum_index_out = maximum_index;
return(array);
}
internal Codepoint_Index_Map
ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){
FT_Long glyph_count = face->num_glyphs;
Codepoint_Index_Map map = {};
map.zero_index = max_u16;
map.table = make_table_u32_u16(base_allocator, glyph_count*4);
u16 maximum_index = 0;
i32 counter = 0;
FT_UInt index = 0;
FT_ULong codepoint = FT_Get_First_Char(face, &index);
@ -94,9 +94,9 @@ ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){
break;
}
}
map.max_index = maximum_index;
return(map);
}
@ -125,50 +125,27 @@ ft__bad_rect_pack_end_line(Bad_Rect_Pack *pack){
internal Vec3_i32
ft__bad_rect_pack_next(Bad_Rect_Pack *pack, Vec2_i32 dim){
Vec3_i32 result = { };
// NOTE(simon, 28/02/24): Does this character fit in the texture if it's the only character ?
if ( dim.x <= pack->max_dim.x && dim.y <= pack->max_dim.y ){
b8 end_line = false;
if ( pack->p.x + dim.x > pack->max_dim.x ) {
// NOTE(simon, 28/02/24): Can't fit the character horizontally.
end_line = true;
Vec3_i32 result = {};
if (dim.x <= pack->max_dim.x && dim.y <= pack->max_dim.y){
if (pack->current_line_h < dim.y){
pack->current_line_h = dim.y;
}
if ( pack->current_line_h < dim.y && pack->p.y + dim.y > pack->max_dim.y ) {
// NOTE(simon, 28/02/24): Character doesn't fit in the current line height, AND we
// can't grow the line height.
end_line = true;
}
if ( end_line ) {
ft__bad_rect_pack_end_line( pack );
}
if ( pack->p.y + dim.y > pack->max_dim.y ) {
Assert( end_line );
// NOTE(simon, 28/02/24): We ended a line. There isn't enough space on a new line to
// fit the character vertically. We need to go to the next texture in the array.
// In a new texture the character is guaranteed to fit, because of the outer most if.
if (pack->current_line_h > pack->max_dim.y){
ft__bad_rect_pack_end_line(pack);
pack->p.y = 0;
pack->dim.z += 1;
pack->p.z += 1;
// NOTE(simon, 28/02/24): There are no checks on the z axis range, but texture arrays
// have a limit. At the moment it's 2048 on both OpenGL and DirectX.
}
// NOTE(simon, 28/02/24): We are now sure that the character will fit.
pack->current_line_h = Max(pack->current_line_h, dim.y);
else{
if (pack->p.x + dim.x > pack->max_dim.x){
ft__bad_rect_pack_end_line(pack);
}
result = pack->p;
pack->p.x += dim.x;
pack->dim.x = Max( pack->dim.x, pack->p.x );
pack->current_line_h = Max(pack->current_line_h, dim.y);
pack->dim.x = clamp_bot(pack->dim.x, pack->p.x);
}
}
return(result);
}
@ -186,31 +163,31 @@ ft__glyph_bounds_store_uv_raw(Vec3_i32 p, Vec2_i32 dim, Glyph_Bounds *bounds){
internal Face*
ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor){
String_Const_u8 file_name = push_string_copy(arena, description->font.file_name);
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face ft_face;
FT_Error error = FT_New_Face(ft, (char*)file_name.str, 0, &ft_face);
Face *face = 0;
if (error == 0){
face = push_array_zero(arena, Face, 1);
u32 pt_size_unscaled = Max(description->parameters.pt_size, 8);
u32 pt_size_unscaled = Max(description->parameters.pt_size, 8);
u32 pt_size = (u32)(pt_size_unscaled*scale_factor);
b32 hinting = description->parameters.hinting;
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = (pt_size << 6);
FT_Request_Size(ft_face, &size);
face->description.font.file_name = file_name;
face->description.parameters = description->parameters;
Face_Metrics *met = &face->metrics;
met->max_advance = f32_ceil32(ft_face->size->metrics.max_advance/64.f);
met->ascent = f32_ceil32(ft_face->size->metrics.ascender/64.f);
met->descent = f32_floor32(ft_face->size->metrics.descender/64.f);
@ -218,19 +195,19 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
met->line_skip = met->text_height - (met->ascent - met->descent);
met->line_skip = clamp_bot(1.f, met->line_skip);
met->line_height = met->text_height + met->line_skip;
{
f32 real_over_notional = met->line_height/(f32)ft_face->height;
f32 relative_center = -1.f*real_over_notional*ft_face->underline_position;
f32 relative_thickness = real_over_notional*ft_face->underline_thickness;
f32 center = f32_floor32(met->ascent + relative_center);
f32 thickness = clamp_bot(1.f, relative_thickness);
met->underline_yoff1 = center - thickness*0.5f;
met->underline_yoff2 = center + thickness*0.5f;
}
face->advance_map.codepoint_to_index =
ft__get_codepoint_index_map(arena->base_allocator, ft_face);
u16 index_count =
@ -238,40 +215,40 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
face->advance_map.index_count = index_count;
face->advance_map.advance = push_array_zero(arena, f32, index_count);
face->bounds = push_array(arena, Glyph_Bounds, index_count);
Temp_Memory_Block temp_memory(arena);
struct Bitmap{
Vec2_i32 dim;
u8 *data;
};
Bitmap *glyph_bitmaps = push_array(arena, Bitmap, index_count);
u32 load_flags = ft__load_flags(hinting);
for (u16 i = 0; i < index_count; i += 1){
Bitmap *bitmap = &glyph_bitmaps[i];
error = FT_Load_Glyph(ft_face, i, load_flags);
if (error == 0){
FT_GlyphSlot ft_glyph = ft_face->glyph;
Vec2_i32 dim = V2i32(ft_glyph->bitmap.width, ft_glyph->bitmap.rows);
bitmap->dim = dim;
bitmap->data = push_array(arena, u8, dim.x*dim.y);
face->bounds[i].xy_off.x0 = (f32)(ft_face->glyph->bitmap_left);
face->bounds[i].xy_off.y0 = (f32)(met->ascent - ft_face->glyph->bitmap_top);
face->bounds[i].xy_off.x1 = (f32)(face->bounds[i].xy_off.x0 + dim.x);
face->bounds[i].xy_off.y1 = (f32)(face->bounds[i].xy_off.y0 + dim.y);
switch (ft_glyph->bitmap.pixel_mode){
case FT_PIXEL_MODE_MONO:
{
NotImplemented;
}break;
case FT_PIXEL_MODE_GRAY:
{
b32 aa_1bit_mono = (description->parameters.aa_mode == FaceAntialiasingMode_1BitMono);
u8 *src_line = ft_glyph->bitmap.buffer;
if (ft_glyph->bitmap.pitch < 0){
src_line = ft_glyph->bitmap.buffer + (-ft_glyph->bitmap.pitch)*(dim.y - 1);
@ -296,28 +273,28 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
src_line += ft_glyph->bitmap.pitch;
}
}break;
default:
{
NotImplemented;
}break;
}
face->advance_map.advance[i] = f32_ceil32(ft_glyph->advance.x/64.0f);
}
}
u8 white_data[16] = {
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
};
Bitmap white = {};
white.dim = V2i32(4, 4);
white.data = white_data;
Bad_Rect_Pack pack = {};
ft__bad_rect_pack_init(&pack, V2i32(1024, 1024));
ft__glyph_bounds_store_uv_raw(ft__bad_rect_pack_next(&pack, white.dim), white.dim, &face->white);
@ -326,76 +303,69 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
ft__glyph_bounds_store_uv_raw(ft__bad_rect_pack_next(&pack, dim), dim, &face->bounds[i]);
}
ft__bad_rect_store_finish(&pack);
Texture_Kind texture_kind = TextureKind_Mono;
u32 texture = graphics_get_texture(pack.dim, texture_kind);
/* NOTE simon (06/01/25): This assumes that every platforms don't use 0 as a valid texture id.
This is valid for OpenGL and the DX11 implementaion. Someone needs to check the MAC versions. */
if (texture != 0 ){
face->texture_kind = texture_kind;
face->texture = texture;
Vec3_f32 texture_dim = V3f32(pack.dim);
face->texture_dim = texture_dim;
{
Vec3_i32 p = V3i32((i32)face->white.uv.x0, (i32)face->white.uv.y0, (i32)face->white.w);
Vec3_i32 dim = V3i32(white.dim.x, white.dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, white.data);
face->white.uv.x1 = (face->white.uv.x0 + face->white.uv.x1)/texture_dim.x;
face->white.uv.y1 = (face->white.uv.y0 + face->white.uv.y1)/texture_dim.y;
face->white.uv.x0 = face->white.uv.x0/texture_dim.x;
face->white.uv.y0 = face->white.uv.y0/texture_dim.y;
}
for (u16 i = 0; i < index_count; i += 1){
Vec3_i32 p = V3i32((i32)face->bounds[i].uv.x0, (i32)face->bounds[i].uv.y0, (i32)face->bounds[i].w);
Vec3_i32 dim = V3i32(glyph_bitmaps[i].dim.x, glyph_bitmaps[i].dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, glyph_bitmaps[i].data);
face->bounds[i].uv.x1 = (face->bounds[i].uv.x0 + face->bounds[i].uv.x1)/texture_dim.x;
face->bounds[i].uv.y1 = (face->bounds[i].uv.y0 + face->bounds[i].uv.y1)/texture_dim.y;
face->bounds[i].uv.x0 = face->bounds[i].uv.x0/texture_dim.x;
face->bounds[i].uv.y0 = face->bounds[i].uv.y0/texture_dim.y;
}
{
Face_Advance_Map *advance_map = &face->advance_map;
met->space_advance = font_get_glyph_advance(advance_map, met, ' ', 0);
met->decimal_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, '0', '9', 0);
met->hex_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, 'A', 'F', 0);
met->hex_digit_advance =
Max(met->hex_digit_advance, met->decimal_digit_advance);
met->byte_sub_advances[0] =
font_get_glyph_advance(advance_map, met, '\\', 0);
met->byte_sub_advances[1] = met->hex_digit_advance;
met->byte_sub_advances[2] = met->hex_digit_advance;
met->byte_advance =
met->byte_sub_advances[0] +
met->byte_sub_advances[1] +
met->byte_sub_advances[2];
met->normal_lowercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'a', 'z', 0);
met->normal_uppercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'A', 'Z', 0);
met->normal_advance = (26*met->normal_lowercase_advance +
26*met->normal_uppercase_advance +
10*met->decimal_digit_advance)/62.f;
}
} else {
pop_array(arena, Face, 1);
face = 0;
face->texture_kind = texture_kind;
face->texture = texture;
Vec3_f32 texture_dim = V3f32(pack.dim);
face->texture_dim = texture_dim;
{
Vec3_i32 p = V3i32((i32)face->white.uv.x0, (i32)face->white.uv.y0, (i32)face->white.w);
Vec3_i32 dim = V3i32(white.dim.x, white.dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, white.data);
face->white.uv.x1 = (face->white.uv.x0 + face->white.uv.x1)/texture_dim.x;
face->white.uv.y1 = (face->white.uv.y0 + face->white.uv.y1)/texture_dim.y;
face->white.uv.x0 = face->white.uv.x0/texture_dim.x;
face->white.uv.y0 = face->white.uv.y0/texture_dim.y;
face->white.w /= texture_dim.z;
}
for (u16 i = 0; i < index_count; i += 1){
Vec3_i32 p = V3i32((i32)face->bounds[i].uv.x0, (i32)face->bounds[i].uv.y0, (i32)face->bounds[i].w);
Vec3_i32 dim = V3i32(glyph_bitmaps[i].dim.x, glyph_bitmaps[i].dim.y, 1);
graphics_fill_texture(texture_kind, texture, p, dim, glyph_bitmaps[i].data);
face->bounds[i].uv.x1 = (face->bounds[i].uv.x0 + face->bounds[i].uv.x1)/texture_dim.x;
face->bounds[i].uv.y1 = (face->bounds[i].uv.y0 + face->bounds[i].uv.y1)/texture_dim.y;
face->bounds[i].uv.x0 = face->bounds[i].uv.x0/texture_dim.x;
face->bounds[i].uv.y0 = face->bounds[i].uv.y0/texture_dim.y;
face->bounds[i].w /= texture_dim.z;
}
{
Face_Advance_Map *advance_map = &face->advance_map;
met->space_advance = font_get_glyph_advance(advance_map, met, ' ', 0);
met->decimal_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, '0', '9', 0);
met->hex_digit_advance =
font_get_max_glyph_advance_range(advance_map, met, 'A', 'F', 0);
met->hex_digit_advance =
Max(met->hex_digit_advance, met->decimal_digit_advance);
met->byte_sub_advances[0] =
font_get_glyph_advance(advance_map, met, '\\', 0);
met->byte_sub_advances[1] = met->hex_digit_advance;
met->byte_sub_advances[2] = met->hex_digit_advance;
met->byte_advance =
met->byte_sub_advances[0] +
met->byte_sub_advances[1] +
met->byte_sub_advances[2];
met->normal_lowercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'a', 'z', 0);
met->normal_uppercase_advance =
font_get_average_glyph_advance_range(advance_map, met, 'A', 'Z', 0);
met->normal_advance = (26*met->normal_lowercase_advance +
26*met->normal_uppercase_advance +
10*met->decimal_digit_advance)/62.f;
}
}
FT_Done_FreeType(ft);
return(face);
}
// BOTTOM

View File

@ -153,9 +153,6 @@ font_set_modify_face(Font_Set *set, Face_ID id, Face_Description *description){
Arena arena = make_arena_system();
Face *face = font_make_face(&arena, description, set->scale_factor);
if (face != 0){
if (slot->face->texture != 0){
graphics_free_texture(slot->face->texture);
}
linalloc_clear(&slot->arena);
slot->arena = arena;
slot->face = face;

View File

@ -45,20 +45,20 @@ generate_codes(Arena *scratch, Event_Code_List *list, FILE *out){
for (Event_Code *code = list->first;
code != 0;
code = code->next){
fprintf(out, " %.*s_%.*s = %d,\n",
fprintf(out, "%.*s_%.*s = %d,\n",
string_expand(code_prefix), string_expand(code->name), counter);
counter += 1;
}
fprintf(out, " %.*s_COUNT = %d,\n", string_expand(code_prefix), counter);
fprintf(out, "%.*s_COUNT = %d,\n", string_expand(code_prefix), counter);
fprintf(out, "};\n");
fprintf(out, "global char* %.*s[%.*s_COUNT] = {\n",
string_expand(name_table), string_expand(code_prefix));
fprintf(out, " \"None\",\n");
fprintf(out, "\"None\",\n");
for (Event_Code *code = list->first;
code != 0;
code = code->next){
fprintf(out, " \"%.*s\",\n", string_expand(code->name));
fprintf(out, "\"%.*s\",\n", string_expand(code->name));
counter += 1;
}
fprintf(out, "};\n");
@ -188,9 +188,6 @@ main(void){
exit(1);
}
fprintf(out, "/* Generated by: " __FILE__ );
fprintf(out, " */\n" );
generate_codes(&arena, &key_list, out);
generate_codes(&arena, &mouse_list, out);
generate_codes(&arena, &core_list, out);

View File

@ -9,8 +9,6 @@
// TOP
#define GENERATED_BY "code/4ed_graphics_api.cpp"
#include "4ed_api_definition_main.cpp"
function API_Definition*
@ -32,11 +30,6 @@ define_api(Arena *arena){
api_param(arena, call, "void*", "data");
}
{
API_Call *call = api_call(arena, api, "free_texture", "void");
api_param(arena, call, "u32", "texid");
}
return(api);
}

View File

@ -132,32 +132,27 @@ end_render_section(Render_Target *target){
internal void
draw_rectangle_outline(Render_Target *target, Rect_f32 rect, f32 roundness, f32 thickness, u32 color){
if ( rect_overlap(rect, target->current_clip_box) ) {
if (roundness < epsilon_f32){
roundness = 0.f;
}
thickness = clamp_bot(1.f, thickness);
f32 half_thickness = thickness*0.5f;
Render_Vertex vertices[6] = {};
vertices[0].xy = V2f32(rect.x0, rect.y0);
vertices[1].xy = V2f32(rect.x1, rect.y0);
vertices[2].xy = V2f32(rect.x0, rect.y1);
vertices[3].xy = V2f32(rect.x1, rect.y0);
vertices[4].xy = V2f32(rect.x0, rect.y1);
vertices[5].xy = V2f32(rect.x1, rect.y1);
Vec2_f32 center = rect_center(rect);
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
vertices[i].uvw = V3f32(center.x, center.y, roundness);
vertices[i].color = color;
vertices[i].half_thickness = half_thickness;
}
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
if (roundness < epsilon_f32){
roundness = 0.f;
}
thickness = clamp_bot(1.f, thickness);
f32 half_thickness = thickness*0.5f;
Render_Vertex vertices[6] = {};
vertices[0].xy = V2f32(rect.x0, rect.y0);
vertices[1].xy = V2f32(rect.x1, rect.y0);
vertices[2].xy = V2f32(rect.x0, rect.y1);
vertices[3].xy = V2f32(rect.x1, rect.y0);
vertices[4].xy = V2f32(rect.x0, rect.y1);
vertices[5].xy = V2f32(rect.x1, rect.y1);
Vec2_f32 center = rect_center(rect);
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
vertices[i].uvw = V3f32(center.x, center.y, roundness);
vertices[i].color = color;
vertices[i].half_thickness = half_thickness;
}
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
}
internal void
@ -199,62 +194,53 @@ draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p,
vertices[2].xy = p_x_min + y_max;
vertices[5].xy = p_x_max + y_max;
/* NOTE simon (26/09/24): We don't use rect_overlap here because the text rect is not guaranteed to be axis aligned. */
b32 draw = rect_contains_point( target->current_clip_box, vertices[ 0 ].xy );
draw = draw || rect_contains_point( target->current_clip_box, vertices[ 1 ].xy );
draw = draw || rect_contains_point( target->current_clip_box, vertices[ 2 ].xy );
draw = draw || rect_contains_point( target->current_clip_box, vertices[ 5 ].xy );
#if 0
Vec2_f32 xy_min = p + bounds.xy_off.x0*x_axis + bounds.xy_off.y0*y_axis;
Vec2_f32 xy_max = p + bounds.xy_off.x1*x_axis + bounds.xy_off.y1*y_axis;
if ( draw ) {
vertices[0].xy = V2f32(xy_min.x, xy_min.y);
vertices[1].xy = V2f32(xy_max.x, xy_min.y);
vertices[2].xy = V2f32(xy_min.x, xy_max.y);
vertices[5].xy = V2f32(xy_max.x, xy_max.y);
#endif
#if 0
Vec2_f32 xy_min = p + bounds.xy_off.x0*x_axis + bounds.xy_off.y0*y_axis;
Vec2_f32 xy_max = p + bounds.xy_off.x1*x_axis + bounds.xy_off.y1*y_axis;
if (!HasFlag(flags, GlyphFlag_Rotate90)){
Rect_f32 xy = Rf32(p + bounds.xy_off.p0, p + bounds.xy_off.p1);
vertices[0].xy = V2f32(xy_min.x, xy_min.y);
vertices[1].xy = V2f32(xy_max.x, xy_min.y);
vertices[2].xy = V2f32(xy_min.x, xy_max.y);
vertices[5].xy = V2f32(xy_max.x, xy_max.y);
#endif
#if 0
if (!HasFlag(flags, GlyphFlag_Rotate90)){
Rect_f32 xy = Rf32(p + bounds.xy_off.p0, p + bounds.xy_off.p1);
vertices[0].xy = V2f32(xy.x0, xy.y1);
vertices[0].uvw = V3f32(uv.x0, uv.y1, bounds.w);
vertices[1].xy = V2f32(xy.x1, xy.y1);
vertices[1].uvw = V3f32(uv.x1, uv.y1, bounds.w);
vertices[2].xy = V2f32(xy.x0, xy.y0);
vertices[2].uvw = V3f32(uv.x0, uv.y0, bounds.w);
vertices[5].xy = V2f32(xy.x1, xy.y0);
vertices[5].uvw = V3f32(uv.x1, uv.y0, bounds.w);
}
else{
Rect_f32 xy = Rf32(p.x - bounds.xy_off.y1, p.y + bounds.xy_off.x0,
p.x - bounds.xy_off.y0, p.y + bounds.xy_off.x1);
vertices[0].xy = V2f32(xy.x0, xy.y1);
vertices[0].uvw = V3f32(uv.x1, uv.y1, bounds.w);
vertices[1].xy = V2f32(xy.x1, xy.y1);
vertices[1].uvw = V3f32(uv.x1, uv.y0, bounds.w);
vertices[2].xy = V2f32(xy.x0, xy.y0);
vertices[2].uvw = V3f32(uv.x0, uv.y1, bounds.w);
vertices[5].xy = V2f32(xy.x1, xy.y0);
vertices[5].uvw = V3f32(uv.x0, uv.y0, bounds.w);
}
#endif
vertices[3] = vertices[1];
vertices[4] = vertices[2];
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
vertices[i].color = color;
vertices[i].half_thickness = 0.f;
}
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
vertices[0].xy = V2f32(xy.x0, xy.y1);
vertices[0].uvw = V3f32(uv.x0, uv.y1, bounds.w);
vertices[1].xy = V2f32(xy.x1, xy.y1);
vertices[1].uvw = V3f32(uv.x1, uv.y1, bounds.w);
vertices[2].xy = V2f32(xy.x0, xy.y0);
vertices[2].uvw = V3f32(uv.x0, uv.y0, bounds.w);
vertices[5].xy = V2f32(xy.x1, xy.y0);
vertices[5].uvw = V3f32(uv.x1, uv.y0, bounds.w);
}
else{
Rect_f32 xy = Rf32(p.x - bounds.xy_off.y1, p.y + bounds.xy_off.x0,
p.x - bounds.xy_off.y0, p.y + bounds.xy_off.x1);
vertices[0].xy = V2f32(xy.x0, xy.y1);
vertices[0].uvw = V3f32(uv.x1, uv.y1, bounds.w);
vertices[1].xy = V2f32(xy.x1, xy.y1);
vertices[1].uvw = V3f32(uv.x1, uv.y0, bounds.w);
vertices[2].xy = V2f32(xy.x0, xy.y0);
vertices[2].uvw = V3f32(uv.x0, uv.y1, bounds.w);
vertices[5].xy = V2f32(xy.x1, xy.y0);
vertices[5].uvw = V3f32(uv.x0, uv.y0, bounds.w);
}
#endif
vertices[3] = vertices[1];
vertices[4] = vertices[2];
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
vertices[i].color = color;
vertices[i].half_thickness = 0.f;
}
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
}
////////////////////////////////

View File

@ -9,8 +9,6 @@
// TOP
#define GENERATED_BY "code/4ed_system_api.cpp"
#include "4ed_api_definition_main.cpp"
function API_Definition*

View File

@ -185,7 +185,7 @@ get_defines_from_flags(Arena *arena, u32 flags){
"-wd4611 -wd4189 -WX -GR- -EHa- -nologo -FC"
#define CL_LIBS_COMMON \
"user32.lib winmm.lib gdi32.lib comdlg32.lib userenv.lib "
"user32.lib winmm.lib gdi32.lib opengl32.lib comdlg32.lib userenv.lib "
#define CL_LIBS_X64 CL_LIBS_COMMON FOREIGN_WIN "\\x64\\freetype.lib"
#define CL_LIBS_X86 CL_LIBS_COMMON FOREIGN_WIN "\\x86\\freetype.lib"

View File

@ -1,4 +1,3 @@
/* Generated by: 4ed_generate_keycodes.cpp */
enum{
KeyCode_A = 1,
KeyCode_B = 2,

View File

@ -1,370 +1,367 @@
/* Generated by "code/4ed_api_parser_main.exe 4ed_api_implementation.cpp" */
function void
custom_api_fill_vtable(API_VTable_custom *vtable){
vtable->global_set_setting = global_set_setting;
vtable->global_get_screen_rectangle = global_get_screen_rectangle;
vtable->get_thread_context = get_thread_context;
vtable->create_child_process = create_child_process;
vtable->child_process_set_target_buffer = child_process_set_target_buffer;
vtable->buffer_get_attached_child_process = buffer_get_attached_child_process;
vtable->child_process_get_attached_buffer = child_process_get_attached_buffer;
vtable->child_process_get_state = child_process_get_state;
vtable->enqueue_virtual_event = enqueue_virtual_event;
vtable->get_buffer_count = get_buffer_count;
vtable->get_buffer_next = get_buffer_next;
vtable->get_buffer_by_name = get_buffer_by_name;
vtable->get_buffer_by_file_name = get_buffer_by_file_name;
vtable->buffer_read_range = buffer_read_range;
vtable->buffer_replace_range = buffer_replace_range;
vtable->buffer_batch_edit = buffer_batch_edit;
vtable->buffer_seek_string = buffer_seek_string;
vtable->buffer_seek_character_class = buffer_seek_character_class;
vtable->buffer_line_y_difference = buffer_line_y_difference;
vtable->buffer_line_shift_y = buffer_line_shift_y;
vtable->buffer_pos_at_relative_xy = buffer_pos_at_relative_xy;
vtable->buffer_relative_box_of_pos = buffer_relative_box_of_pos;
vtable->buffer_padded_box_of_pos = buffer_padded_box_of_pos;
vtable->buffer_relative_character_from_pos = buffer_relative_character_from_pos;
vtable->buffer_pos_from_relative_character = buffer_pos_from_relative_character;
vtable->view_line_y_difference = view_line_y_difference;
vtable->view_line_shift_y = view_line_shift_y;
vtable->view_pos_at_relative_xy = view_pos_at_relative_xy;
vtable->view_relative_box_of_pos = view_relative_box_of_pos;
vtable->view_padded_box_of_pos = view_padded_box_of_pos;
vtable->view_relative_character_from_pos = view_relative_character_from_pos;
vtable->view_pos_from_relative_character = view_pos_from_relative_character;
vtable->buffer_exists = buffer_exists;
vtable->buffer_get_access_flags = buffer_get_access_flags;
vtable->buffer_get_size = buffer_get_size;
vtable->buffer_get_line_count = buffer_get_line_count;
vtable->push_buffer_base_name = push_buffer_base_name;
vtable->push_buffer_unique_name = push_buffer_unique_name;
vtable->push_buffer_file_name = push_buffer_file_name;
vtable->buffer_get_dirty_state = buffer_get_dirty_state;
vtable->buffer_set_dirty_state = buffer_set_dirty_state;
vtable->buffer_set_layout = buffer_set_layout;
vtable->buffer_clear_layout_cache = buffer_clear_layout_cache;
vtable->buffer_get_layout = buffer_get_layout;
vtable->buffer_get_setting = buffer_get_setting;
vtable->buffer_set_setting = buffer_set_setting;
vtable->buffer_get_managed_scope = buffer_get_managed_scope;
vtable->buffer_send_end_signal = buffer_send_end_signal;
vtable->create_buffer = create_buffer;
vtable->buffer_save = buffer_save;
vtable->buffer_kill = buffer_kill;
vtable->buffer_reopen = buffer_reopen;
vtable->buffer_get_file_attributes = buffer_get_file_attributes;
vtable->get_view_next = get_view_next;
vtable->get_view_prev = get_view_prev;
vtable->get_this_ctx_view = get_this_ctx_view;
vtable->get_active_view = get_active_view;
vtable->view_exists = view_exists;
vtable->view_get_buffer = view_get_buffer;
vtable->view_get_cursor_pos = view_get_cursor_pos;
vtable->view_get_mark_pos = view_get_mark_pos;
vtable->view_get_preferred_x = view_get_preferred_x;
vtable->view_set_preferred_x = view_set_preferred_x;
vtable->view_get_screen_rect = view_get_screen_rect;
vtable->view_get_panel = view_get_panel;
vtable->panel_get_view = panel_get_view;
vtable->panel_is_split = panel_is_split;
vtable->panel_is_leaf = panel_is_leaf;
vtable->panel_split = panel_split;
vtable->panel_set_split = panel_set_split;
vtable->panel_swap_children = panel_swap_children;
vtable->panel_get_root = panel_get_root;
vtable->panel_get_parent = panel_get_parent;
vtable->panel_get_child = panel_get_child;
vtable->view_close = view_close;
vtable->view_get_buffer_region = view_get_buffer_region;
vtable->view_get_buffer_scroll = view_get_buffer_scroll;
vtable->view_set_active = view_set_active;
vtable->view_enqueue_command_function = view_enqueue_command_function;
vtable->view_get_setting = view_get_setting;
vtable->view_set_setting = view_set_setting;
vtable->view_get_managed_scope = view_get_managed_scope;
vtable->buffer_compute_cursor = buffer_compute_cursor;
vtable->view_compute_cursor = view_compute_cursor;
vtable->view_set_camera_bounds = view_set_camera_bounds;
vtable->view_get_camera_bounds = view_get_camera_bounds;
vtable->view_set_cursor = view_set_cursor;
vtable->view_set_buffer_scroll = view_set_buffer_scroll;
vtable->view_set_mark = view_set_mark;
vtable->view_quit_ui = view_quit_ui;
vtable->view_set_buffer = view_set_buffer;
vtable->view_push_context = view_push_context;
vtable->view_pop_context = view_pop_context;
vtable->view_alter_context = view_alter_context;
vtable->view_current_context = view_current_context;
vtable->view_current_context_hook_memory = view_current_context_hook_memory;
vtable->create_user_managed_scope = create_user_managed_scope;
vtable->destroy_user_managed_scope = destroy_user_managed_scope;
vtable->get_global_managed_scope = get_global_managed_scope;
vtable->get_managed_scope_with_multiple_dependencies = get_managed_scope_with_multiple_dependencies;
vtable->managed_scope_clear_contents = managed_scope_clear_contents;
vtable->managed_scope_clear_self_all_dependent_scopes = managed_scope_clear_self_all_dependent_scopes;
vtable->managed_scope_allocator = managed_scope_allocator;
vtable->managed_id_group_highest_id = managed_id_group_highest_id;
vtable->managed_id_declare = managed_id_declare;
vtable->managed_id_get = managed_id_get;
vtable->managed_scope_get_attachment = managed_scope_get_attachment;
vtable->managed_scope_attachment_erase = managed_scope_attachment_erase;
vtable->alloc_managed_memory_in_scope = alloc_managed_memory_in_scope;
vtable->alloc_buffer_markers_on_buffer = alloc_buffer_markers_on_buffer;
vtable->managed_object_get_item_size = managed_object_get_item_size;
vtable->managed_object_get_item_count = managed_object_get_item_count;
vtable->managed_object_get_pointer = managed_object_get_pointer;
vtable->managed_object_get_type = managed_object_get_type;
vtable->managed_object_get_containing_scope = managed_object_get_containing_scope;
vtable->managed_object_free = managed_object_free;
vtable->managed_object_store_data = managed_object_store_data;
vtable->managed_object_load_data = managed_object_load_data;
vtable->get_next_input_raw = get_next_input_raw;
vtable->get_current_input_sequence_number = get_current_input_sequence_number;
vtable->get_current_input = get_current_input;
vtable->set_current_input = set_current_input;
vtable->leave_current_input_unhandled = leave_current_input_unhandled;
vtable->set_custom_hook = set_custom_hook;
vtable->get_custom_hook = get_custom_hook;
vtable->set_custom_hook_memory_size = set_custom_hook_memory_size;
vtable->get_mouse_state = get_mouse_state;
vtable->get_active_query_bars = get_active_query_bars;
vtable->start_query_bar = start_query_bar;
vtable->end_query_bar = end_query_bar;
vtable->clear_all_query_bars = clear_all_query_bars;
vtable->print_message = print_message;
vtable->log_string = log_string;
vtable->get_largest_face_id = get_largest_face_id;
vtable->set_global_face = set_global_face;
vtable->buffer_history_get_max_record_index = buffer_history_get_max_record_index;
vtable->buffer_history_get_record_info = buffer_history_get_record_info;
vtable->buffer_history_get_group_sub_record = buffer_history_get_group_sub_record;
vtable->buffer_history_get_current_state_index = buffer_history_get_current_state_index;
vtable->buffer_history_set_current_state_index = buffer_history_set_current_state_index;
vtable->buffer_history_merge_record_range = buffer_history_merge_record_range;
vtable->buffer_history_clear_after_current_state = buffer_history_clear_after_current_state;
vtable->global_history_edit_group_begin = global_history_edit_group_begin;
vtable->global_history_edit_group_end = global_history_edit_group_end;
vtable->buffer_set_face = buffer_set_face;
vtable->get_face_description = get_face_description;
vtable->get_face_metrics = get_face_metrics;
vtable->get_face_advance_map = get_face_advance_map;
vtable->get_face_id = get_face_id;
vtable->try_create_new_face = try_create_new_face;
vtable->try_modify_face = try_modify_face;
vtable->try_release_face = try_release_face;
vtable->push_hot_directory = push_hot_directory;
vtable->set_hot_directory = set_hot_directory;
vtable->send_exit_signal = send_exit_signal;
vtable->hard_exit = hard_exit;
vtable->set_window_title = set_window_title;
vtable->acquire_global_frame_mutex = acquire_global_frame_mutex;
vtable->release_global_frame_mutex = release_global_frame_mutex;
vtable->draw_string_oriented = draw_string_oriented;
vtable->get_string_advance = get_string_advance;
vtable->draw_rectangle = draw_rectangle;
vtable->draw_rectangle_outline = draw_rectangle_outline;
vtable->draw_set_clip = draw_set_clip;
vtable->text_layout_create = text_layout_create;
vtable->text_layout_region = text_layout_region;
vtable->text_layout_get_buffer = text_layout_get_buffer;
vtable->text_layout_get_visible_range = text_layout_get_visible_range;
vtable->text_layout_line_on_screen = text_layout_line_on_screen;
vtable->text_layout_character_on_screen = text_layout_character_on_screen;
vtable->paint_text_color = paint_text_color;
vtable->paint_text_color_blend = paint_text_color_blend;
vtable->text_layout_free = text_layout_free;
vtable->draw_text_layout = draw_text_layout;
vtable->open_color_picker = open_color_picker;
vtable->animate_in_n_milliseconds = animate_in_n_milliseconds;
vtable->buffer_find_all_matches = buffer_find_all_matches;
vtable->get_core_profile_list = get_core_profile_list;
vtable->get_custom_layer_boundary_docs = get_custom_layer_boundary_docs;
vtable->global_set_setting = global_set_setting;
vtable->global_get_screen_rectangle = global_get_screen_rectangle;
vtable->get_thread_context = get_thread_context;
vtable->create_child_process = create_child_process;
vtable->child_process_set_target_buffer = child_process_set_target_buffer;
vtable->buffer_get_attached_child_process = buffer_get_attached_child_process;
vtable->child_process_get_attached_buffer = child_process_get_attached_buffer;
vtable->child_process_get_state = child_process_get_state;
vtable->enqueue_virtual_event = enqueue_virtual_event;
vtable->get_buffer_count = get_buffer_count;
vtable->get_buffer_next = get_buffer_next;
vtable->get_buffer_by_name = get_buffer_by_name;
vtable->get_buffer_by_file_name = get_buffer_by_file_name;
vtable->buffer_read_range = buffer_read_range;
vtable->buffer_replace_range = buffer_replace_range;
vtable->buffer_batch_edit = buffer_batch_edit;
vtable->buffer_seek_string = buffer_seek_string;
vtable->buffer_seek_character_class = buffer_seek_character_class;
vtable->buffer_line_y_difference = buffer_line_y_difference;
vtable->buffer_line_shift_y = buffer_line_shift_y;
vtable->buffer_pos_at_relative_xy = buffer_pos_at_relative_xy;
vtable->buffer_relative_box_of_pos = buffer_relative_box_of_pos;
vtable->buffer_padded_box_of_pos = buffer_padded_box_of_pos;
vtable->buffer_relative_character_from_pos = buffer_relative_character_from_pos;
vtable->buffer_pos_from_relative_character = buffer_pos_from_relative_character;
vtable->view_line_y_difference = view_line_y_difference;
vtable->view_line_shift_y = view_line_shift_y;
vtable->view_pos_at_relative_xy = view_pos_at_relative_xy;
vtable->view_relative_box_of_pos = view_relative_box_of_pos;
vtable->view_padded_box_of_pos = view_padded_box_of_pos;
vtable->view_relative_character_from_pos = view_relative_character_from_pos;
vtable->view_pos_from_relative_character = view_pos_from_relative_character;
vtable->buffer_exists = buffer_exists;
vtable->buffer_get_access_flags = buffer_get_access_flags;
vtable->buffer_get_size = buffer_get_size;
vtable->buffer_get_line_count = buffer_get_line_count;
vtable->push_buffer_base_name = push_buffer_base_name;
vtable->push_buffer_unique_name = push_buffer_unique_name;
vtable->push_buffer_file_name = push_buffer_file_name;
vtable->buffer_get_dirty_state = buffer_get_dirty_state;
vtable->buffer_set_dirty_state = buffer_set_dirty_state;
vtable->buffer_set_layout = buffer_set_layout;
vtable->buffer_clear_layout_cache = buffer_clear_layout_cache;
vtable->buffer_get_layout = buffer_get_layout;
vtable->buffer_get_setting = buffer_get_setting;
vtable->buffer_set_setting = buffer_set_setting;
vtable->buffer_get_managed_scope = buffer_get_managed_scope;
vtable->buffer_send_end_signal = buffer_send_end_signal;
vtable->create_buffer = create_buffer;
vtable->buffer_save = buffer_save;
vtable->buffer_kill = buffer_kill;
vtable->buffer_reopen = buffer_reopen;
vtable->buffer_get_file_attributes = buffer_get_file_attributes;
vtable->get_view_next = get_view_next;
vtable->get_view_prev = get_view_prev;
vtable->get_this_ctx_view = get_this_ctx_view;
vtable->get_active_view = get_active_view;
vtable->view_exists = view_exists;
vtable->view_get_buffer = view_get_buffer;
vtable->view_get_cursor_pos = view_get_cursor_pos;
vtable->view_get_mark_pos = view_get_mark_pos;
vtable->view_get_preferred_x = view_get_preferred_x;
vtable->view_set_preferred_x = view_set_preferred_x;
vtable->view_get_screen_rect = view_get_screen_rect;
vtable->view_get_panel = view_get_panel;
vtable->panel_get_view = panel_get_view;
vtable->panel_is_split = panel_is_split;
vtable->panel_is_leaf = panel_is_leaf;
vtable->panel_split = panel_split;
vtable->panel_set_split = panel_set_split;
vtable->panel_swap_children = panel_swap_children;
vtable->panel_get_root = panel_get_root;
vtable->panel_get_parent = panel_get_parent;
vtable->panel_get_child = panel_get_child;
vtable->view_close = view_close;
vtable->view_get_buffer_region = view_get_buffer_region;
vtable->view_get_buffer_scroll = view_get_buffer_scroll;
vtable->view_set_active = view_set_active;
vtable->view_enqueue_command_function = view_enqueue_command_function;
vtable->view_get_setting = view_get_setting;
vtable->view_set_setting = view_set_setting;
vtable->view_get_managed_scope = view_get_managed_scope;
vtable->buffer_compute_cursor = buffer_compute_cursor;
vtable->view_compute_cursor = view_compute_cursor;
vtable->view_set_camera_bounds = view_set_camera_bounds;
vtable->view_get_camera_bounds = view_get_camera_bounds;
vtable->view_set_cursor = view_set_cursor;
vtable->view_set_buffer_scroll = view_set_buffer_scroll;
vtable->view_set_mark = view_set_mark;
vtable->view_quit_ui = view_quit_ui;
vtable->view_set_buffer = view_set_buffer;
vtable->view_push_context = view_push_context;
vtable->view_pop_context = view_pop_context;
vtable->view_alter_context = view_alter_context;
vtable->view_current_context = view_current_context;
vtable->view_current_context_hook_memory = view_current_context_hook_memory;
vtable->create_user_managed_scope = create_user_managed_scope;
vtable->destroy_user_managed_scope = destroy_user_managed_scope;
vtable->get_global_managed_scope = get_global_managed_scope;
vtable->get_managed_scope_with_multiple_dependencies = get_managed_scope_with_multiple_dependencies;
vtable->managed_scope_clear_contents = managed_scope_clear_contents;
vtable->managed_scope_clear_self_all_dependent_scopes = managed_scope_clear_self_all_dependent_scopes;
vtable->managed_scope_allocator = managed_scope_allocator;
vtable->managed_id_group_highest_id = managed_id_group_highest_id;
vtable->managed_id_declare = managed_id_declare;
vtable->managed_id_get = managed_id_get;
vtable->managed_scope_get_attachment = managed_scope_get_attachment;
vtable->managed_scope_attachment_erase = managed_scope_attachment_erase;
vtable->alloc_managed_memory_in_scope = alloc_managed_memory_in_scope;
vtable->alloc_buffer_markers_on_buffer = alloc_buffer_markers_on_buffer;
vtable->managed_object_get_item_size = managed_object_get_item_size;
vtable->managed_object_get_item_count = managed_object_get_item_count;
vtable->managed_object_get_pointer = managed_object_get_pointer;
vtable->managed_object_get_type = managed_object_get_type;
vtable->managed_object_get_containing_scope = managed_object_get_containing_scope;
vtable->managed_object_free = managed_object_free;
vtable->managed_object_store_data = managed_object_store_data;
vtable->managed_object_load_data = managed_object_load_data;
vtable->get_next_input_raw = get_next_input_raw;
vtable->get_current_input_sequence_number = get_current_input_sequence_number;
vtable->get_current_input = get_current_input;
vtable->set_current_input = set_current_input;
vtable->leave_current_input_unhandled = leave_current_input_unhandled;
vtable->set_custom_hook = set_custom_hook;
vtable->get_custom_hook = get_custom_hook;
vtable->set_custom_hook_memory_size = set_custom_hook_memory_size;
vtable->get_mouse_state = get_mouse_state;
vtable->get_active_query_bars = get_active_query_bars;
vtable->start_query_bar = start_query_bar;
vtable->end_query_bar = end_query_bar;
vtable->clear_all_query_bars = clear_all_query_bars;
vtable->print_message = print_message;
vtable->log_string = log_string;
vtable->get_largest_face_id = get_largest_face_id;
vtable->set_global_face = set_global_face;
vtable->buffer_history_get_max_record_index = buffer_history_get_max_record_index;
vtable->buffer_history_get_record_info = buffer_history_get_record_info;
vtable->buffer_history_get_group_sub_record = buffer_history_get_group_sub_record;
vtable->buffer_history_get_current_state_index = buffer_history_get_current_state_index;
vtable->buffer_history_set_current_state_index = buffer_history_set_current_state_index;
vtable->buffer_history_merge_record_range = buffer_history_merge_record_range;
vtable->buffer_history_clear_after_current_state = buffer_history_clear_after_current_state;
vtable->global_history_edit_group_begin = global_history_edit_group_begin;
vtable->global_history_edit_group_end = global_history_edit_group_end;
vtable->buffer_set_face = buffer_set_face;
vtable->get_face_description = get_face_description;
vtable->get_face_metrics = get_face_metrics;
vtable->get_face_advance_map = get_face_advance_map;
vtable->get_face_id = get_face_id;
vtable->try_create_new_face = try_create_new_face;
vtable->try_modify_face = try_modify_face;
vtable->try_release_face = try_release_face;
vtable->push_hot_directory = push_hot_directory;
vtable->set_hot_directory = set_hot_directory;
vtable->send_exit_signal = send_exit_signal;
vtable->hard_exit = hard_exit;
vtable->set_window_title = set_window_title;
vtable->acquire_global_frame_mutex = acquire_global_frame_mutex;
vtable->release_global_frame_mutex = release_global_frame_mutex;
vtable->draw_string_oriented = draw_string_oriented;
vtable->get_string_advance = get_string_advance;
vtable->draw_rectangle = draw_rectangle;
vtable->draw_rectangle_outline = draw_rectangle_outline;
vtable->draw_set_clip = draw_set_clip;
vtable->text_layout_create = text_layout_create;
vtable->text_layout_region = text_layout_region;
vtable->text_layout_get_buffer = text_layout_get_buffer;
vtable->text_layout_get_visible_range = text_layout_get_visible_range;
vtable->text_layout_line_on_screen = text_layout_line_on_screen;
vtable->text_layout_character_on_screen = text_layout_character_on_screen;
vtable->paint_text_color = paint_text_color;
vtable->paint_text_color_blend = paint_text_color_blend;
vtable->text_layout_free = text_layout_free;
vtable->draw_text_layout = draw_text_layout;
vtable->open_color_picker = open_color_picker;
vtable->animate_in_n_milliseconds = animate_in_n_milliseconds;
vtable->buffer_find_all_matches = buffer_find_all_matches;
vtable->get_core_profile_list = get_core_profile_list;
vtable->get_custom_layer_boundary_docs = get_custom_layer_boundary_docs;
}
#if defined(DYNAMIC_LINK_API)
function void
custom_api_read_vtable(API_VTable_custom *vtable){
global_set_setting = vtable->global_set_setting;
global_get_screen_rectangle = vtable->global_get_screen_rectangle;
get_thread_context = vtable->get_thread_context;
create_child_process = vtable->create_child_process;
child_process_set_target_buffer = vtable->child_process_set_target_buffer;
buffer_get_attached_child_process = vtable->buffer_get_attached_child_process;
child_process_get_attached_buffer = vtable->child_process_get_attached_buffer;
child_process_get_state = vtable->child_process_get_state;
enqueue_virtual_event = vtable->enqueue_virtual_event;
get_buffer_count = vtable->get_buffer_count;
get_buffer_next = vtable->get_buffer_next;
get_buffer_by_name = vtable->get_buffer_by_name;
get_buffer_by_file_name = vtable->get_buffer_by_file_name;
buffer_read_range = vtable->buffer_read_range;
buffer_replace_range = vtable->buffer_replace_range;
buffer_batch_edit = vtable->buffer_batch_edit;
buffer_seek_string = vtable->buffer_seek_string;
buffer_seek_character_class = vtable->buffer_seek_character_class;
buffer_line_y_difference = vtable->buffer_line_y_difference;
buffer_line_shift_y = vtable->buffer_line_shift_y;
buffer_pos_at_relative_xy = vtable->buffer_pos_at_relative_xy;
buffer_relative_box_of_pos = vtable->buffer_relative_box_of_pos;
buffer_padded_box_of_pos = vtable->buffer_padded_box_of_pos;
buffer_relative_character_from_pos = vtable->buffer_relative_character_from_pos;
buffer_pos_from_relative_character = vtable->buffer_pos_from_relative_character;
view_line_y_difference = vtable->view_line_y_difference;
view_line_shift_y = vtable->view_line_shift_y;
view_pos_at_relative_xy = vtable->view_pos_at_relative_xy;
view_relative_box_of_pos = vtable->view_relative_box_of_pos;
view_padded_box_of_pos = vtable->view_padded_box_of_pos;
view_relative_character_from_pos = vtable->view_relative_character_from_pos;
view_pos_from_relative_character = vtable->view_pos_from_relative_character;
buffer_exists = vtable->buffer_exists;
buffer_get_access_flags = vtable->buffer_get_access_flags;
buffer_get_size = vtable->buffer_get_size;
buffer_get_line_count = vtable->buffer_get_line_count;
push_buffer_base_name = vtable->push_buffer_base_name;
push_buffer_unique_name = vtable->push_buffer_unique_name;
push_buffer_file_name = vtable->push_buffer_file_name;
buffer_get_dirty_state = vtable->buffer_get_dirty_state;
buffer_set_dirty_state = vtable->buffer_set_dirty_state;
buffer_set_layout = vtable->buffer_set_layout;
buffer_clear_layout_cache = vtable->buffer_clear_layout_cache;
buffer_get_layout = vtable->buffer_get_layout;
buffer_get_setting = vtable->buffer_get_setting;
buffer_set_setting = vtable->buffer_set_setting;
buffer_get_managed_scope = vtable->buffer_get_managed_scope;
buffer_send_end_signal = vtable->buffer_send_end_signal;
create_buffer = vtable->create_buffer;
buffer_save = vtable->buffer_save;
buffer_kill = vtable->buffer_kill;
buffer_reopen = vtable->buffer_reopen;
buffer_get_file_attributes = vtable->buffer_get_file_attributes;
get_view_next = vtable->get_view_next;
get_view_prev = vtable->get_view_prev;
get_this_ctx_view = vtable->get_this_ctx_view;
get_active_view = vtable->get_active_view;
view_exists = vtable->view_exists;
view_get_buffer = vtable->view_get_buffer;
view_get_cursor_pos = vtable->view_get_cursor_pos;
view_get_mark_pos = vtable->view_get_mark_pos;
view_get_preferred_x = vtable->view_get_preferred_x;
view_set_preferred_x = vtable->view_set_preferred_x;
view_get_screen_rect = vtable->view_get_screen_rect;
view_get_panel = vtable->view_get_panel;
panel_get_view = vtable->panel_get_view;
panel_is_split = vtable->panel_is_split;
panel_is_leaf = vtable->panel_is_leaf;
panel_split = vtable->panel_split;
panel_set_split = vtable->panel_set_split;
panel_swap_children = vtable->panel_swap_children;
panel_get_root = vtable->panel_get_root;
panel_get_parent = vtable->panel_get_parent;
panel_get_child = vtable->panel_get_child;
view_close = vtable->view_close;
view_get_buffer_region = vtable->view_get_buffer_region;
view_get_buffer_scroll = vtable->view_get_buffer_scroll;
view_set_active = vtable->view_set_active;
view_enqueue_command_function = vtable->view_enqueue_command_function;
view_get_setting = vtable->view_get_setting;
view_set_setting = vtable->view_set_setting;
view_get_managed_scope = vtable->view_get_managed_scope;
buffer_compute_cursor = vtable->buffer_compute_cursor;
view_compute_cursor = vtable->view_compute_cursor;
view_set_camera_bounds = vtable->view_set_camera_bounds;
view_get_camera_bounds = vtable->view_get_camera_bounds;
view_set_cursor = vtable->view_set_cursor;
view_set_buffer_scroll = vtable->view_set_buffer_scroll;
view_set_mark = vtable->view_set_mark;
view_quit_ui = vtable->view_quit_ui;
view_set_buffer = vtable->view_set_buffer;
view_push_context = vtable->view_push_context;
view_pop_context = vtable->view_pop_context;
view_alter_context = vtable->view_alter_context;
view_current_context = vtable->view_current_context;
view_current_context_hook_memory = vtable->view_current_context_hook_memory;
create_user_managed_scope = vtable->create_user_managed_scope;
destroy_user_managed_scope = vtable->destroy_user_managed_scope;
get_global_managed_scope = vtable->get_global_managed_scope;
get_managed_scope_with_multiple_dependencies = vtable->get_managed_scope_with_multiple_dependencies;
managed_scope_clear_contents = vtable->managed_scope_clear_contents;
managed_scope_clear_self_all_dependent_scopes = vtable->managed_scope_clear_self_all_dependent_scopes;
managed_scope_allocator = vtable->managed_scope_allocator;
managed_id_group_highest_id = vtable->managed_id_group_highest_id;
managed_id_declare = vtable->managed_id_declare;
managed_id_get = vtable->managed_id_get;
managed_scope_get_attachment = vtable->managed_scope_get_attachment;
managed_scope_attachment_erase = vtable->managed_scope_attachment_erase;
alloc_managed_memory_in_scope = vtable->alloc_managed_memory_in_scope;
alloc_buffer_markers_on_buffer = vtable->alloc_buffer_markers_on_buffer;
managed_object_get_item_size = vtable->managed_object_get_item_size;
managed_object_get_item_count = vtable->managed_object_get_item_count;
managed_object_get_pointer = vtable->managed_object_get_pointer;
managed_object_get_type = vtable->managed_object_get_type;
managed_object_get_containing_scope = vtable->managed_object_get_containing_scope;
managed_object_free = vtable->managed_object_free;
managed_object_store_data = vtable->managed_object_store_data;
managed_object_load_data = vtable->managed_object_load_data;
get_next_input_raw = vtable->get_next_input_raw;
get_current_input_sequence_number = vtable->get_current_input_sequence_number;
get_current_input = vtable->get_current_input;
set_current_input = vtable->set_current_input;
leave_current_input_unhandled = vtable->leave_current_input_unhandled;
set_custom_hook = vtable->set_custom_hook;
get_custom_hook = vtable->get_custom_hook;
set_custom_hook_memory_size = vtable->set_custom_hook_memory_size;
get_mouse_state = vtable->get_mouse_state;
get_active_query_bars = vtable->get_active_query_bars;
start_query_bar = vtable->start_query_bar;
end_query_bar = vtable->end_query_bar;
clear_all_query_bars = vtable->clear_all_query_bars;
print_message = vtable->print_message;
log_string = vtable->log_string;
get_largest_face_id = vtable->get_largest_face_id;
set_global_face = vtable->set_global_face;
buffer_history_get_max_record_index = vtable->buffer_history_get_max_record_index;
buffer_history_get_record_info = vtable->buffer_history_get_record_info;
buffer_history_get_group_sub_record = vtable->buffer_history_get_group_sub_record;
buffer_history_get_current_state_index = vtable->buffer_history_get_current_state_index;
buffer_history_set_current_state_index = vtable->buffer_history_set_current_state_index;
buffer_history_merge_record_range = vtable->buffer_history_merge_record_range;
buffer_history_clear_after_current_state = vtable->buffer_history_clear_after_current_state;
global_history_edit_group_begin = vtable->global_history_edit_group_begin;
global_history_edit_group_end = vtable->global_history_edit_group_end;
buffer_set_face = vtable->buffer_set_face;
get_face_description = vtable->get_face_description;
get_face_metrics = vtable->get_face_metrics;
get_face_advance_map = vtable->get_face_advance_map;
get_face_id = vtable->get_face_id;
try_create_new_face = vtable->try_create_new_face;
try_modify_face = vtable->try_modify_face;
try_release_face = vtable->try_release_face;
push_hot_directory = vtable->push_hot_directory;
set_hot_directory = vtable->set_hot_directory;
send_exit_signal = vtable->send_exit_signal;
hard_exit = vtable->hard_exit;
set_window_title = vtable->set_window_title;
acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
release_global_frame_mutex = vtable->release_global_frame_mutex;
draw_string_oriented = vtable->draw_string_oriented;
get_string_advance = vtable->get_string_advance;
draw_rectangle = vtable->draw_rectangle;
draw_rectangle_outline = vtable->draw_rectangle_outline;
draw_set_clip = vtable->draw_set_clip;
text_layout_create = vtable->text_layout_create;
text_layout_region = vtable->text_layout_region;
text_layout_get_buffer = vtable->text_layout_get_buffer;
text_layout_get_visible_range = vtable->text_layout_get_visible_range;
text_layout_line_on_screen = vtable->text_layout_line_on_screen;
text_layout_character_on_screen = vtable->text_layout_character_on_screen;
paint_text_color = vtable->paint_text_color;
paint_text_color_blend = vtable->paint_text_color_blend;
text_layout_free = vtable->text_layout_free;
draw_text_layout = vtable->draw_text_layout;
open_color_picker = vtable->open_color_picker;
animate_in_n_milliseconds = vtable->animate_in_n_milliseconds;
buffer_find_all_matches = vtable->buffer_find_all_matches;
get_core_profile_list = vtable->get_core_profile_list;
get_custom_layer_boundary_docs = vtable->get_custom_layer_boundary_docs;
global_set_setting = vtable->global_set_setting;
global_get_screen_rectangle = vtable->global_get_screen_rectangle;
get_thread_context = vtable->get_thread_context;
create_child_process = vtable->create_child_process;
child_process_set_target_buffer = vtable->child_process_set_target_buffer;
buffer_get_attached_child_process = vtable->buffer_get_attached_child_process;
child_process_get_attached_buffer = vtable->child_process_get_attached_buffer;
child_process_get_state = vtable->child_process_get_state;
enqueue_virtual_event = vtable->enqueue_virtual_event;
get_buffer_count = vtable->get_buffer_count;
get_buffer_next = vtable->get_buffer_next;
get_buffer_by_name = vtable->get_buffer_by_name;
get_buffer_by_file_name = vtable->get_buffer_by_file_name;
buffer_read_range = vtable->buffer_read_range;
buffer_replace_range = vtable->buffer_replace_range;
buffer_batch_edit = vtable->buffer_batch_edit;
buffer_seek_string = vtable->buffer_seek_string;
buffer_seek_character_class = vtable->buffer_seek_character_class;
buffer_line_y_difference = vtable->buffer_line_y_difference;
buffer_line_shift_y = vtable->buffer_line_shift_y;
buffer_pos_at_relative_xy = vtable->buffer_pos_at_relative_xy;
buffer_relative_box_of_pos = vtable->buffer_relative_box_of_pos;
buffer_padded_box_of_pos = vtable->buffer_padded_box_of_pos;
buffer_relative_character_from_pos = vtable->buffer_relative_character_from_pos;
buffer_pos_from_relative_character = vtable->buffer_pos_from_relative_character;
view_line_y_difference = vtable->view_line_y_difference;
view_line_shift_y = vtable->view_line_shift_y;
view_pos_at_relative_xy = vtable->view_pos_at_relative_xy;
view_relative_box_of_pos = vtable->view_relative_box_of_pos;
view_padded_box_of_pos = vtable->view_padded_box_of_pos;
view_relative_character_from_pos = vtable->view_relative_character_from_pos;
view_pos_from_relative_character = vtable->view_pos_from_relative_character;
buffer_exists = vtable->buffer_exists;
buffer_get_access_flags = vtable->buffer_get_access_flags;
buffer_get_size = vtable->buffer_get_size;
buffer_get_line_count = vtable->buffer_get_line_count;
push_buffer_base_name = vtable->push_buffer_base_name;
push_buffer_unique_name = vtable->push_buffer_unique_name;
push_buffer_file_name = vtable->push_buffer_file_name;
buffer_get_dirty_state = vtable->buffer_get_dirty_state;
buffer_set_dirty_state = vtable->buffer_set_dirty_state;
buffer_set_layout = vtable->buffer_set_layout;
buffer_clear_layout_cache = vtable->buffer_clear_layout_cache;
buffer_get_layout = vtable->buffer_get_layout;
buffer_get_setting = vtable->buffer_get_setting;
buffer_set_setting = vtable->buffer_set_setting;
buffer_get_managed_scope = vtable->buffer_get_managed_scope;
buffer_send_end_signal = vtable->buffer_send_end_signal;
create_buffer = vtable->create_buffer;
buffer_save = vtable->buffer_save;
buffer_kill = vtable->buffer_kill;
buffer_reopen = vtable->buffer_reopen;
buffer_get_file_attributes = vtable->buffer_get_file_attributes;
get_view_next = vtable->get_view_next;
get_view_prev = vtable->get_view_prev;
get_this_ctx_view = vtable->get_this_ctx_view;
get_active_view = vtable->get_active_view;
view_exists = vtable->view_exists;
view_get_buffer = vtable->view_get_buffer;
view_get_cursor_pos = vtable->view_get_cursor_pos;
view_get_mark_pos = vtable->view_get_mark_pos;
view_get_preferred_x = vtable->view_get_preferred_x;
view_set_preferred_x = vtable->view_set_preferred_x;
view_get_screen_rect = vtable->view_get_screen_rect;
view_get_panel = vtable->view_get_panel;
panel_get_view = vtable->panel_get_view;
panel_is_split = vtable->panel_is_split;
panel_is_leaf = vtable->panel_is_leaf;
panel_split = vtable->panel_split;
panel_set_split = vtable->panel_set_split;
panel_swap_children = vtable->panel_swap_children;
panel_get_root = vtable->panel_get_root;
panel_get_parent = vtable->panel_get_parent;
panel_get_child = vtable->panel_get_child;
view_close = vtable->view_close;
view_get_buffer_region = vtable->view_get_buffer_region;
view_get_buffer_scroll = vtable->view_get_buffer_scroll;
view_set_active = vtable->view_set_active;
view_enqueue_command_function = vtable->view_enqueue_command_function;
view_get_setting = vtable->view_get_setting;
view_set_setting = vtable->view_set_setting;
view_get_managed_scope = vtable->view_get_managed_scope;
buffer_compute_cursor = vtable->buffer_compute_cursor;
view_compute_cursor = vtable->view_compute_cursor;
view_set_camera_bounds = vtable->view_set_camera_bounds;
view_get_camera_bounds = vtable->view_get_camera_bounds;
view_set_cursor = vtable->view_set_cursor;
view_set_buffer_scroll = vtable->view_set_buffer_scroll;
view_set_mark = vtable->view_set_mark;
view_quit_ui = vtable->view_quit_ui;
view_set_buffer = vtable->view_set_buffer;
view_push_context = vtable->view_push_context;
view_pop_context = vtable->view_pop_context;
view_alter_context = vtable->view_alter_context;
view_current_context = vtable->view_current_context;
view_current_context_hook_memory = vtable->view_current_context_hook_memory;
create_user_managed_scope = vtable->create_user_managed_scope;
destroy_user_managed_scope = vtable->destroy_user_managed_scope;
get_global_managed_scope = vtable->get_global_managed_scope;
get_managed_scope_with_multiple_dependencies = vtable->get_managed_scope_with_multiple_dependencies;
managed_scope_clear_contents = vtable->managed_scope_clear_contents;
managed_scope_clear_self_all_dependent_scopes = vtable->managed_scope_clear_self_all_dependent_scopes;
managed_scope_allocator = vtable->managed_scope_allocator;
managed_id_group_highest_id = vtable->managed_id_group_highest_id;
managed_id_declare = vtable->managed_id_declare;
managed_id_get = vtable->managed_id_get;
managed_scope_get_attachment = vtable->managed_scope_get_attachment;
managed_scope_attachment_erase = vtable->managed_scope_attachment_erase;
alloc_managed_memory_in_scope = vtable->alloc_managed_memory_in_scope;
alloc_buffer_markers_on_buffer = vtable->alloc_buffer_markers_on_buffer;
managed_object_get_item_size = vtable->managed_object_get_item_size;
managed_object_get_item_count = vtable->managed_object_get_item_count;
managed_object_get_pointer = vtable->managed_object_get_pointer;
managed_object_get_type = vtable->managed_object_get_type;
managed_object_get_containing_scope = vtable->managed_object_get_containing_scope;
managed_object_free = vtable->managed_object_free;
managed_object_store_data = vtable->managed_object_store_data;
managed_object_load_data = vtable->managed_object_load_data;
get_next_input_raw = vtable->get_next_input_raw;
get_current_input_sequence_number = vtable->get_current_input_sequence_number;
get_current_input = vtable->get_current_input;
set_current_input = vtable->set_current_input;
leave_current_input_unhandled = vtable->leave_current_input_unhandled;
set_custom_hook = vtable->set_custom_hook;
get_custom_hook = vtable->get_custom_hook;
set_custom_hook_memory_size = vtable->set_custom_hook_memory_size;
get_mouse_state = vtable->get_mouse_state;
get_active_query_bars = vtable->get_active_query_bars;
start_query_bar = vtable->start_query_bar;
end_query_bar = vtable->end_query_bar;
clear_all_query_bars = vtable->clear_all_query_bars;
print_message = vtable->print_message;
log_string = vtable->log_string;
get_largest_face_id = vtable->get_largest_face_id;
set_global_face = vtable->set_global_face;
buffer_history_get_max_record_index = vtable->buffer_history_get_max_record_index;
buffer_history_get_record_info = vtable->buffer_history_get_record_info;
buffer_history_get_group_sub_record = vtable->buffer_history_get_group_sub_record;
buffer_history_get_current_state_index = vtable->buffer_history_get_current_state_index;
buffer_history_set_current_state_index = vtable->buffer_history_set_current_state_index;
buffer_history_merge_record_range = vtable->buffer_history_merge_record_range;
buffer_history_clear_after_current_state = vtable->buffer_history_clear_after_current_state;
global_history_edit_group_begin = vtable->global_history_edit_group_begin;
global_history_edit_group_end = vtable->global_history_edit_group_end;
buffer_set_face = vtable->buffer_set_face;
get_face_description = vtable->get_face_description;
get_face_metrics = vtable->get_face_metrics;
get_face_advance_map = vtable->get_face_advance_map;
get_face_id = vtable->get_face_id;
try_create_new_face = vtable->try_create_new_face;
try_modify_face = vtable->try_modify_face;
try_release_face = vtable->try_release_face;
push_hot_directory = vtable->push_hot_directory;
set_hot_directory = vtable->set_hot_directory;
send_exit_signal = vtable->send_exit_signal;
hard_exit = vtable->hard_exit;
set_window_title = vtable->set_window_title;
acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
release_global_frame_mutex = vtable->release_global_frame_mutex;
draw_string_oriented = vtable->draw_string_oriented;
get_string_advance = vtable->get_string_advance;
draw_rectangle = vtable->draw_rectangle;
draw_rectangle_outline = vtable->draw_rectangle_outline;
draw_set_clip = vtable->draw_set_clip;
text_layout_create = vtable->text_layout_create;
text_layout_region = vtable->text_layout_region;
text_layout_get_buffer = vtable->text_layout_get_buffer;
text_layout_get_visible_range = vtable->text_layout_get_visible_range;
text_layout_line_on_screen = vtable->text_layout_line_on_screen;
text_layout_character_on_screen = vtable->text_layout_character_on_screen;
paint_text_color = vtable->paint_text_color;
paint_text_color_blend = vtable->paint_text_color_blend;
text_layout_free = vtable->text_layout_free;
draw_text_layout = vtable->draw_text_layout;
open_color_picker = vtable->open_color_picker;
animate_in_n_milliseconds = vtable->animate_in_n_milliseconds;
buffer_find_all_matches = vtable->buffer_find_all_matches;
get_core_profile_list = vtable->get_core_profile_list;
get_custom_layer_boundary_docs = vtable->get_custom_layer_boundary_docs;
}
#undef DYNAMIC_LINK_API
#endif

View File

@ -1,5 +1,3 @@
/* Generated by "code/4ed_api_parser_main.exe 4ed_api_implementation.cpp" */
#define custom_global_set_setting_sig() b32 custom_global_set_setting(Application_Links* app, Global_Setting_ID setting, i64 value)
#define custom_global_get_screen_rectangle_sig() Rect_f32 custom_global_get_screen_rectangle(Application_Links* app)
#define custom_get_thread_context_sig() Thread_Context* custom_get_thread_context(Application_Links* app)
@ -179,7 +177,6 @@
#define custom_buffer_find_all_matches_sig() String_Match_List custom_buffer_find_all_matches(Application_Links* app, Arena* arena, Buffer_ID buffer, i32 string_id, Range_i64 range, String_Const_u8 needle, Character_Predicate* predicate, Scan_Direction direction)
#define custom_get_core_profile_list_sig() Profile_Global_List* custom_get_core_profile_list(Application_Links* app)
#define custom_get_custom_layer_boundary_docs_sig() Doc_Cluster* custom_get_custom_layer_boundary_docs(Application_Links* app, Arena* arena)
typedef b32 custom_global_set_setting_type(Application_Links* app, Global_Setting_ID setting, i64 value);
typedef Rect_f32 custom_global_get_screen_rectangle_type(Application_Links* app);
typedef Thread_Context* custom_get_thread_context_type(Application_Links* app);
@ -359,189 +356,187 @@ typedef void custom_animate_in_n_milliseconds_type(Application_Links* app, u32 n
typedef String_Match_List custom_buffer_find_all_matches_type(Application_Links* app, Arena* arena, Buffer_ID buffer, i32 string_id, Range_i64 range, String_Const_u8 needle, Character_Predicate* predicate, Scan_Direction direction);
typedef Profile_Global_List* custom_get_core_profile_list_type(Application_Links* app);
typedef Doc_Cluster* custom_get_custom_layer_boundary_docs_type(Application_Links* app, Arena* arena);
struct API_VTable_custom{
custom_global_set_setting_type *global_set_setting;
custom_global_get_screen_rectangle_type *global_get_screen_rectangle;
custom_get_thread_context_type *get_thread_context;
custom_create_child_process_type *create_child_process;
custom_child_process_set_target_buffer_type *child_process_set_target_buffer;
custom_buffer_get_attached_child_process_type *buffer_get_attached_child_process;
custom_child_process_get_attached_buffer_type *child_process_get_attached_buffer;
custom_child_process_get_state_type *child_process_get_state;
custom_enqueue_virtual_event_type *enqueue_virtual_event;
custom_get_buffer_count_type *get_buffer_count;
custom_get_buffer_next_type *get_buffer_next;
custom_get_buffer_by_name_type *get_buffer_by_name;
custom_get_buffer_by_file_name_type *get_buffer_by_file_name;
custom_buffer_read_range_type *buffer_read_range;
custom_buffer_replace_range_type *buffer_replace_range;
custom_buffer_batch_edit_type *buffer_batch_edit;
custom_buffer_seek_string_type *buffer_seek_string;
custom_buffer_seek_character_class_type *buffer_seek_character_class;
custom_buffer_line_y_difference_type *buffer_line_y_difference;
custom_buffer_line_shift_y_type *buffer_line_shift_y;
custom_buffer_pos_at_relative_xy_type *buffer_pos_at_relative_xy;
custom_buffer_relative_box_of_pos_type *buffer_relative_box_of_pos;
custom_buffer_padded_box_of_pos_type *buffer_padded_box_of_pos;
custom_buffer_relative_character_from_pos_type *buffer_relative_character_from_pos;
custom_buffer_pos_from_relative_character_type *buffer_pos_from_relative_character;
custom_view_line_y_difference_type *view_line_y_difference;
custom_view_line_shift_y_type *view_line_shift_y;
custom_view_pos_at_relative_xy_type *view_pos_at_relative_xy;
custom_view_relative_box_of_pos_type *view_relative_box_of_pos;
custom_view_padded_box_of_pos_type *view_padded_box_of_pos;
custom_view_relative_character_from_pos_type *view_relative_character_from_pos;
custom_view_pos_from_relative_character_type *view_pos_from_relative_character;
custom_buffer_exists_type *buffer_exists;
custom_buffer_get_access_flags_type *buffer_get_access_flags;
custom_buffer_get_size_type *buffer_get_size;
custom_buffer_get_line_count_type *buffer_get_line_count;
custom_push_buffer_base_name_type *push_buffer_base_name;
custom_push_buffer_unique_name_type *push_buffer_unique_name;
custom_push_buffer_file_name_type *push_buffer_file_name;
custom_buffer_get_dirty_state_type *buffer_get_dirty_state;
custom_buffer_set_dirty_state_type *buffer_set_dirty_state;
custom_buffer_set_layout_type *buffer_set_layout;
custom_buffer_clear_layout_cache_type *buffer_clear_layout_cache;
custom_buffer_get_layout_type *buffer_get_layout;
custom_buffer_get_setting_type *buffer_get_setting;
custom_buffer_set_setting_type *buffer_set_setting;
custom_buffer_get_managed_scope_type *buffer_get_managed_scope;
custom_buffer_send_end_signal_type *buffer_send_end_signal;
custom_create_buffer_type *create_buffer;
custom_buffer_save_type *buffer_save;
custom_buffer_kill_type *buffer_kill;
custom_buffer_reopen_type *buffer_reopen;
custom_buffer_get_file_attributes_type *buffer_get_file_attributes;
custom_get_view_next_type *get_view_next;
custom_get_view_prev_type *get_view_prev;
custom_get_this_ctx_view_type *get_this_ctx_view;
custom_get_active_view_type *get_active_view;
custom_view_exists_type *view_exists;
custom_view_get_buffer_type *view_get_buffer;
custom_view_get_cursor_pos_type *view_get_cursor_pos;
custom_view_get_mark_pos_type *view_get_mark_pos;
custom_view_get_preferred_x_type *view_get_preferred_x;
custom_view_set_preferred_x_type *view_set_preferred_x;
custom_view_get_screen_rect_type *view_get_screen_rect;
custom_view_get_panel_type *view_get_panel;
custom_panel_get_view_type *panel_get_view;
custom_panel_is_split_type *panel_is_split;
custom_panel_is_leaf_type *panel_is_leaf;
custom_panel_split_type *panel_split;
custom_panel_set_split_type *panel_set_split;
custom_panel_swap_children_type *panel_swap_children;
custom_panel_get_root_type *panel_get_root;
custom_panel_get_parent_type *panel_get_parent;
custom_panel_get_child_type *panel_get_child;
custom_view_close_type *view_close;
custom_view_get_buffer_region_type *view_get_buffer_region;
custom_view_get_buffer_scroll_type *view_get_buffer_scroll;
custom_view_set_active_type *view_set_active;
custom_view_enqueue_command_function_type *view_enqueue_command_function;
custom_view_get_setting_type *view_get_setting;
custom_view_set_setting_type *view_set_setting;
custom_view_get_managed_scope_type *view_get_managed_scope;
custom_buffer_compute_cursor_type *buffer_compute_cursor;
custom_view_compute_cursor_type *view_compute_cursor;
custom_view_set_camera_bounds_type *view_set_camera_bounds;
custom_view_get_camera_bounds_type *view_get_camera_bounds;
custom_view_set_cursor_type *view_set_cursor;
custom_view_set_buffer_scroll_type *view_set_buffer_scroll;
custom_view_set_mark_type *view_set_mark;
custom_view_quit_ui_type *view_quit_ui;
custom_view_set_buffer_type *view_set_buffer;
custom_view_push_context_type *view_push_context;
custom_view_pop_context_type *view_pop_context;
custom_view_alter_context_type *view_alter_context;
custom_view_current_context_type *view_current_context;
custom_view_current_context_hook_memory_type *view_current_context_hook_memory;
custom_create_user_managed_scope_type *create_user_managed_scope;
custom_destroy_user_managed_scope_type *destroy_user_managed_scope;
custom_get_global_managed_scope_type *get_global_managed_scope;
custom_get_managed_scope_with_multiple_dependencies_type *get_managed_scope_with_multiple_dependencies;
custom_managed_scope_clear_contents_type *managed_scope_clear_contents;
custom_managed_scope_clear_self_all_dependent_scopes_type *managed_scope_clear_self_all_dependent_scopes;
custom_managed_scope_allocator_type *managed_scope_allocator;
custom_managed_id_group_highest_id_type *managed_id_group_highest_id;
custom_managed_id_declare_type *managed_id_declare;
custom_managed_id_get_type *managed_id_get;
custom_managed_scope_get_attachment_type *managed_scope_get_attachment;
custom_managed_scope_attachment_erase_type *managed_scope_attachment_erase;
custom_alloc_managed_memory_in_scope_type *alloc_managed_memory_in_scope;
custom_alloc_buffer_markers_on_buffer_type *alloc_buffer_markers_on_buffer;
custom_managed_object_get_item_size_type *managed_object_get_item_size;
custom_managed_object_get_item_count_type *managed_object_get_item_count;
custom_managed_object_get_pointer_type *managed_object_get_pointer;
custom_managed_object_get_type_type *managed_object_get_type;
custom_managed_object_get_containing_scope_type *managed_object_get_containing_scope;
custom_managed_object_free_type *managed_object_free;
custom_managed_object_store_data_type *managed_object_store_data;
custom_managed_object_load_data_type *managed_object_load_data;
custom_get_next_input_raw_type *get_next_input_raw;
custom_get_current_input_sequence_number_type *get_current_input_sequence_number;
custom_get_current_input_type *get_current_input;
custom_set_current_input_type *set_current_input;
custom_leave_current_input_unhandled_type *leave_current_input_unhandled;
custom_set_custom_hook_type *set_custom_hook;
custom_get_custom_hook_type *get_custom_hook;
custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size;
custom_get_mouse_state_type *get_mouse_state;
custom_get_active_query_bars_type *get_active_query_bars;
custom_start_query_bar_type *start_query_bar;
custom_end_query_bar_type *end_query_bar;
custom_clear_all_query_bars_type *clear_all_query_bars;
custom_print_message_type *print_message;
custom_log_string_type *log_string;
custom_get_largest_face_id_type *get_largest_face_id;
custom_set_global_face_type *set_global_face;
custom_buffer_history_get_max_record_index_type *buffer_history_get_max_record_index;
custom_buffer_history_get_record_info_type *buffer_history_get_record_info;
custom_buffer_history_get_group_sub_record_type *buffer_history_get_group_sub_record;
custom_buffer_history_get_current_state_index_type *buffer_history_get_current_state_index;
custom_buffer_history_set_current_state_index_type *buffer_history_set_current_state_index;
custom_buffer_history_merge_record_range_type *buffer_history_merge_record_range;
custom_buffer_history_clear_after_current_state_type *buffer_history_clear_after_current_state;
custom_global_history_edit_group_begin_type *global_history_edit_group_begin;
custom_global_history_edit_group_end_type *global_history_edit_group_end;
custom_buffer_set_face_type *buffer_set_face;
custom_get_face_description_type *get_face_description;
custom_get_face_metrics_type *get_face_metrics;
custom_get_face_advance_map_type *get_face_advance_map;
custom_get_face_id_type *get_face_id;
custom_try_create_new_face_type *try_create_new_face;
custom_try_modify_face_type *try_modify_face;
custom_try_release_face_type *try_release_face;
custom_push_hot_directory_type *push_hot_directory;
custom_set_hot_directory_type *set_hot_directory;
custom_send_exit_signal_type *send_exit_signal;
custom_hard_exit_type *hard_exit;
custom_set_window_title_type *set_window_title;
custom_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
custom_release_global_frame_mutex_type *release_global_frame_mutex;
custom_draw_string_oriented_type *draw_string_oriented;
custom_get_string_advance_type *get_string_advance;
custom_draw_rectangle_type *draw_rectangle;
custom_draw_rectangle_outline_type *draw_rectangle_outline;
custom_draw_set_clip_type *draw_set_clip;
custom_text_layout_create_type *text_layout_create;
custom_text_layout_region_type *text_layout_region;
custom_text_layout_get_buffer_type *text_layout_get_buffer;
custom_text_layout_get_visible_range_type *text_layout_get_visible_range;
custom_text_layout_line_on_screen_type *text_layout_line_on_screen;
custom_text_layout_character_on_screen_type *text_layout_character_on_screen;
custom_paint_text_color_type *paint_text_color;
custom_paint_text_color_blend_type *paint_text_color_blend;
custom_text_layout_free_type *text_layout_free;
custom_draw_text_layout_type *draw_text_layout;
custom_open_color_picker_type *open_color_picker;
custom_animate_in_n_milliseconds_type *animate_in_n_milliseconds;
custom_buffer_find_all_matches_type *buffer_find_all_matches;
custom_get_core_profile_list_type *get_core_profile_list;
custom_get_custom_layer_boundary_docs_type *get_custom_layer_boundary_docs;
custom_global_set_setting_type *global_set_setting;
custom_global_get_screen_rectangle_type *global_get_screen_rectangle;
custom_get_thread_context_type *get_thread_context;
custom_create_child_process_type *create_child_process;
custom_child_process_set_target_buffer_type *child_process_set_target_buffer;
custom_buffer_get_attached_child_process_type *buffer_get_attached_child_process;
custom_child_process_get_attached_buffer_type *child_process_get_attached_buffer;
custom_child_process_get_state_type *child_process_get_state;
custom_enqueue_virtual_event_type *enqueue_virtual_event;
custom_get_buffer_count_type *get_buffer_count;
custom_get_buffer_next_type *get_buffer_next;
custom_get_buffer_by_name_type *get_buffer_by_name;
custom_get_buffer_by_file_name_type *get_buffer_by_file_name;
custom_buffer_read_range_type *buffer_read_range;
custom_buffer_replace_range_type *buffer_replace_range;
custom_buffer_batch_edit_type *buffer_batch_edit;
custom_buffer_seek_string_type *buffer_seek_string;
custom_buffer_seek_character_class_type *buffer_seek_character_class;
custom_buffer_line_y_difference_type *buffer_line_y_difference;
custom_buffer_line_shift_y_type *buffer_line_shift_y;
custom_buffer_pos_at_relative_xy_type *buffer_pos_at_relative_xy;
custom_buffer_relative_box_of_pos_type *buffer_relative_box_of_pos;
custom_buffer_padded_box_of_pos_type *buffer_padded_box_of_pos;
custom_buffer_relative_character_from_pos_type *buffer_relative_character_from_pos;
custom_buffer_pos_from_relative_character_type *buffer_pos_from_relative_character;
custom_view_line_y_difference_type *view_line_y_difference;
custom_view_line_shift_y_type *view_line_shift_y;
custom_view_pos_at_relative_xy_type *view_pos_at_relative_xy;
custom_view_relative_box_of_pos_type *view_relative_box_of_pos;
custom_view_padded_box_of_pos_type *view_padded_box_of_pos;
custom_view_relative_character_from_pos_type *view_relative_character_from_pos;
custom_view_pos_from_relative_character_type *view_pos_from_relative_character;
custom_buffer_exists_type *buffer_exists;
custom_buffer_get_access_flags_type *buffer_get_access_flags;
custom_buffer_get_size_type *buffer_get_size;
custom_buffer_get_line_count_type *buffer_get_line_count;
custom_push_buffer_base_name_type *push_buffer_base_name;
custom_push_buffer_unique_name_type *push_buffer_unique_name;
custom_push_buffer_file_name_type *push_buffer_file_name;
custom_buffer_get_dirty_state_type *buffer_get_dirty_state;
custom_buffer_set_dirty_state_type *buffer_set_dirty_state;
custom_buffer_set_layout_type *buffer_set_layout;
custom_buffer_clear_layout_cache_type *buffer_clear_layout_cache;
custom_buffer_get_layout_type *buffer_get_layout;
custom_buffer_get_setting_type *buffer_get_setting;
custom_buffer_set_setting_type *buffer_set_setting;
custom_buffer_get_managed_scope_type *buffer_get_managed_scope;
custom_buffer_send_end_signal_type *buffer_send_end_signal;
custom_create_buffer_type *create_buffer;
custom_buffer_save_type *buffer_save;
custom_buffer_kill_type *buffer_kill;
custom_buffer_reopen_type *buffer_reopen;
custom_buffer_get_file_attributes_type *buffer_get_file_attributes;
custom_get_view_next_type *get_view_next;
custom_get_view_prev_type *get_view_prev;
custom_get_this_ctx_view_type *get_this_ctx_view;
custom_get_active_view_type *get_active_view;
custom_view_exists_type *view_exists;
custom_view_get_buffer_type *view_get_buffer;
custom_view_get_cursor_pos_type *view_get_cursor_pos;
custom_view_get_mark_pos_type *view_get_mark_pos;
custom_view_get_preferred_x_type *view_get_preferred_x;
custom_view_set_preferred_x_type *view_set_preferred_x;
custom_view_get_screen_rect_type *view_get_screen_rect;
custom_view_get_panel_type *view_get_panel;
custom_panel_get_view_type *panel_get_view;
custom_panel_is_split_type *panel_is_split;
custom_panel_is_leaf_type *panel_is_leaf;
custom_panel_split_type *panel_split;
custom_panel_set_split_type *panel_set_split;
custom_panel_swap_children_type *panel_swap_children;
custom_panel_get_root_type *panel_get_root;
custom_panel_get_parent_type *panel_get_parent;
custom_panel_get_child_type *panel_get_child;
custom_view_close_type *view_close;
custom_view_get_buffer_region_type *view_get_buffer_region;
custom_view_get_buffer_scroll_type *view_get_buffer_scroll;
custom_view_set_active_type *view_set_active;
custom_view_enqueue_command_function_type *view_enqueue_command_function;
custom_view_get_setting_type *view_get_setting;
custom_view_set_setting_type *view_set_setting;
custom_view_get_managed_scope_type *view_get_managed_scope;
custom_buffer_compute_cursor_type *buffer_compute_cursor;
custom_view_compute_cursor_type *view_compute_cursor;
custom_view_set_camera_bounds_type *view_set_camera_bounds;
custom_view_get_camera_bounds_type *view_get_camera_bounds;
custom_view_set_cursor_type *view_set_cursor;
custom_view_set_buffer_scroll_type *view_set_buffer_scroll;
custom_view_set_mark_type *view_set_mark;
custom_view_quit_ui_type *view_quit_ui;
custom_view_set_buffer_type *view_set_buffer;
custom_view_push_context_type *view_push_context;
custom_view_pop_context_type *view_pop_context;
custom_view_alter_context_type *view_alter_context;
custom_view_current_context_type *view_current_context;
custom_view_current_context_hook_memory_type *view_current_context_hook_memory;
custom_create_user_managed_scope_type *create_user_managed_scope;
custom_destroy_user_managed_scope_type *destroy_user_managed_scope;
custom_get_global_managed_scope_type *get_global_managed_scope;
custom_get_managed_scope_with_multiple_dependencies_type *get_managed_scope_with_multiple_dependencies;
custom_managed_scope_clear_contents_type *managed_scope_clear_contents;
custom_managed_scope_clear_self_all_dependent_scopes_type *managed_scope_clear_self_all_dependent_scopes;
custom_managed_scope_allocator_type *managed_scope_allocator;
custom_managed_id_group_highest_id_type *managed_id_group_highest_id;
custom_managed_id_declare_type *managed_id_declare;
custom_managed_id_get_type *managed_id_get;
custom_managed_scope_get_attachment_type *managed_scope_get_attachment;
custom_managed_scope_attachment_erase_type *managed_scope_attachment_erase;
custom_alloc_managed_memory_in_scope_type *alloc_managed_memory_in_scope;
custom_alloc_buffer_markers_on_buffer_type *alloc_buffer_markers_on_buffer;
custom_managed_object_get_item_size_type *managed_object_get_item_size;
custom_managed_object_get_item_count_type *managed_object_get_item_count;
custom_managed_object_get_pointer_type *managed_object_get_pointer;
custom_managed_object_get_type_type *managed_object_get_type;
custom_managed_object_get_containing_scope_type *managed_object_get_containing_scope;
custom_managed_object_free_type *managed_object_free;
custom_managed_object_store_data_type *managed_object_store_data;
custom_managed_object_load_data_type *managed_object_load_data;
custom_get_next_input_raw_type *get_next_input_raw;
custom_get_current_input_sequence_number_type *get_current_input_sequence_number;
custom_get_current_input_type *get_current_input;
custom_set_current_input_type *set_current_input;
custom_leave_current_input_unhandled_type *leave_current_input_unhandled;
custom_set_custom_hook_type *set_custom_hook;
custom_get_custom_hook_type *get_custom_hook;
custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size;
custom_get_mouse_state_type *get_mouse_state;
custom_get_active_query_bars_type *get_active_query_bars;
custom_start_query_bar_type *start_query_bar;
custom_end_query_bar_type *end_query_bar;
custom_clear_all_query_bars_type *clear_all_query_bars;
custom_print_message_type *print_message;
custom_log_string_type *log_string;
custom_get_largest_face_id_type *get_largest_face_id;
custom_set_global_face_type *set_global_face;
custom_buffer_history_get_max_record_index_type *buffer_history_get_max_record_index;
custom_buffer_history_get_record_info_type *buffer_history_get_record_info;
custom_buffer_history_get_group_sub_record_type *buffer_history_get_group_sub_record;
custom_buffer_history_get_current_state_index_type *buffer_history_get_current_state_index;
custom_buffer_history_set_current_state_index_type *buffer_history_set_current_state_index;
custom_buffer_history_merge_record_range_type *buffer_history_merge_record_range;
custom_buffer_history_clear_after_current_state_type *buffer_history_clear_after_current_state;
custom_global_history_edit_group_begin_type *global_history_edit_group_begin;
custom_global_history_edit_group_end_type *global_history_edit_group_end;
custom_buffer_set_face_type *buffer_set_face;
custom_get_face_description_type *get_face_description;
custom_get_face_metrics_type *get_face_metrics;
custom_get_face_advance_map_type *get_face_advance_map;
custom_get_face_id_type *get_face_id;
custom_try_create_new_face_type *try_create_new_face;
custom_try_modify_face_type *try_modify_face;
custom_try_release_face_type *try_release_face;
custom_push_hot_directory_type *push_hot_directory;
custom_set_hot_directory_type *set_hot_directory;
custom_send_exit_signal_type *send_exit_signal;
custom_hard_exit_type *hard_exit;
custom_set_window_title_type *set_window_title;
custom_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
custom_release_global_frame_mutex_type *release_global_frame_mutex;
custom_draw_string_oriented_type *draw_string_oriented;
custom_get_string_advance_type *get_string_advance;
custom_draw_rectangle_type *draw_rectangle;
custom_draw_rectangle_outline_type *draw_rectangle_outline;
custom_draw_set_clip_type *draw_set_clip;
custom_text_layout_create_type *text_layout_create;
custom_text_layout_region_type *text_layout_region;
custom_text_layout_get_buffer_type *text_layout_get_buffer;
custom_text_layout_get_visible_range_type *text_layout_get_visible_range;
custom_text_layout_line_on_screen_type *text_layout_line_on_screen;
custom_text_layout_character_on_screen_type *text_layout_character_on_screen;
custom_paint_text_color_type *paint_text_color;
custom_paint_text_color_blend_type *paint_text_color_blend;
custom_text_layout_free_type *text_layout_free;
custom_draw_text_layout_type *draw_text_layout;
custom_open_color_picker_type *open_color_picker;
custom_animate_in_n_milliseconds_type *animate_in_n_milliseconds;
custom_buffer_find_all_matches_type *buffer_find_all_matches;
custom_get_core_profile_list_type *get_core_profile_list;
custom_get_custom_layer_boundary_docs_type *get_custom_layer_boundary_docs;
};
#if defined(STATIC_LINK_API)
internal b32 global_set_setting(Application_Links* app, Global_Setting_ID setting, i64 value);
internal Rect_f32 global_get_screen_rectangle(Application_Links* app);
@ -723,7 +718,6 @@ internal String_Match_List buffer_find_all_matches(Application_Links* app, Arena
internal Profile_Global_List* get_core_profile_list(Application_Links* app);
internal Doc_Cluster* get_custom_layer_boundary_docs(Application_Links* app, Arena* arena);
#undef STATIC_LINK_API
#elif defined(DYNAMIC_LINK_API)
global custom_global_set_setting_type *global_set_setting = 0;
global custom_global_get_screen_rectangle_type *global_get_screen_rectangle = 0;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,3 @@
/* Generated by "code/4ed_api_parser_main.exe 4ed_api_implementation.cpp" */
api(custom) function b32 global_set_setting(Application_Links* app, Global_Setting_ID setting, i64 value);
api(custom) function Rect_f32 global_get_screen_rectangle(Application_Links* app);
api(custom) function Thread_Context* get_thread_context(Application_Links* app);

View File

@ -1,126 +1,123 @@
/* Generated by "code/4ed_system_api.cpp" */
function void
system_api_fill_vtable(API_VTable_system *vtable){
vtable->error_box = system_error_box;
vtable->get_path = system_get_path;
vtable->get_canonical = system_get_canonical;
vtable->get_file_list = system_get_file_list;
vtable->quick_file_attributes = system_quick_file_attributes;
vtable->load_handle = system_load_handle;
vtable->load_attributes = system_load_attributes;
vtable->load_file = system_load_file;
vtable->load_close = system_load_close;
vtable->save_file = system_save_file;
vtable->load_library = system_load_library;
vtable->release_library = system_release_library;
vtable->get_proc = system_get_proc;
vtable->now_time = system_now_time;
vtable->now_date_time_universal = system_now_date_time_universal;
vtable->local_date_time_from_universal = system_local_date_time_from_universal;
vtable->universal_date_time_from_local = system_universal_date_time_from_local;
vtable->wake_up_timer_create = system_wake_up_timer_create;
vtable->wake_up_timer_release = system_wake_up_timer_release;
vtable->wake_up_timer_set = system_wake_up_timer_set;
vtable->signal_step = system_signal_step;
vtable->sleep = system_sleep;
vtable->get_clipboard = system_get_clipboard;
vtable->post_clipboard = system_post_clipboard;
vtable->set_clipboard_catch_all = system_set_clipboard_catch_all;
vtable->get_clipboard_catch_all = system_get_clipboard_catch_all;
vtable->cli_call = system_cli_call;
vtable->cli_begin_update = system_cli_begin_update;
vtable->cli_update_step = system_cli_update_step;
vtable->cli_end_update = system_cli_end_update;
vtable->open_color_picker = system_open_color_picker;
vtable->get_screen_scale_factor = system_get_screen_scale_factor;
vtable->thread_launch = system_thread_launch;
vtable->thread_join = system_thread_join;
vtable->thread_free = system_thread_free;
vtable->thread_get_id = system_thread_get_id;
vtable->acquire_global_frame_mutex = system_acquire_global_frame_mutex;
vtable->release_global_frame_mutex = system_release_global_frame_mutex;
vtable->mutex_make = system_mutex_make;
vtable->mutex_acquire = system_mutex_acquire;
vtable->mutex_release = system_mutex_release;
vtable->mutex_free = system_mutex_free;
vtable->condition_variable_make = system_condition_variable_make;
vtable->condition_variable_wait = system_condition_variable_wait;
vtable->condition_variable_signal = system_condition_variable_signal;
vtable->condition_variable_free = system_condition_variable_free;
vtable->memory_allocate = system_memory_allocate;
vtable->memory_set_protection = system_memory_set_protection;
vtable->memory_free = system_memory_free;
vtable->memory_annotation = system_memory_annotation;
vtable->show_mouse_cursor = system_show_mouse_cursor;
vtable->set_fullscreen = system_set_fullscreen;
vtable->is_fullscreen = system_is_fullscreen;
vtable->get_keyboard_modifiers = system_get_keyboard_modifiers;
vtable->set_key_mode = system_set_key_mode;
vtable->set_source_mixer = system_set_source_mixer;
vtable->set_destination_mixer = system_set_destination_mixer;
vtable->error_box = system_error_box;
vtable->get_path = system_get_path;
vtable->get_canonical = system_get_canonical;
vtable->get_file_list = system_get_file_list;
vtable->quick_file_attributes = system_quick_file_attributes;
vtable->load_handle = system_load_handle;
vtable->load_attributes = system_load_attributes;
vtable->load_file = system_load_file;
vtable->load_close = system_load_close;
vtable->save_file = system_save_file;
vtable->load_library = system_load_library;
vtable->release_library = system_release_library;
vtable->get_proc = system_get_proc;
vtable->now_time = system_now_time;
vtable->now_date_time_universal = system_now_date_time_universal;
vtable->local_date_time_from_universal = system_local_date_time_from_universal;
vtable->universal_date_time_from_local = system_universal_date_time_from_local;
vtable->wake_up_timer_create = system_wake_up_timer_create;
vtable->wake_up_timer_release = system_wake_up_timer_release;
vtable->wake_up_timer_set = system_wake_up_timer_set;
vtable->signal_step = system_signal_step;
vtable->sleep = system_sleep;
vtable->get_clipboard = system_get_clipboard;
vtable->post_clipboard = system_post_clipboard;
vtable->set_clipboard_catch_all = system_set_clipboard_catch_all;
vtable->get_clipboard_catch_all = system_get_clipboard_catch_all;
vtable->cli_call = system_cli_call;
vtable->cli_begin_update = system_cli_begin_update;
vtable->cli_update_step = system_cli_update_step;
vtable->cli_end_update = system_cli_end_update;
vtable->open_color_picker = system_open_color_picker;
vtable->get_screen_scale_factor = system_get_screen_scale_factor;
vtable->thread_launch = system_thread_launch;
vtable->thread_join = system_thread_join;
vtable->thread_free = system_thread_free;
vtable->thread_get_id = system_thread_get_id;
vtable->acquire_global_frame_mutex = system_acquire_global_frame_mutex;
vtable->release_global_frame_mutex = system_release_global_frame_mutex;
vtable->mutex_make = system_mutex_make;
vtable->mutex_acquire = system_mutex_acquire;
vtable->mutex_release = system_mutex_release;
vtable->mutex_free = system_mutex_free;
vtable->condition_variable_make = system_condition_variable_make;
vtable->condition_variable_wait = system_condition_variable_wait;
vtable->condition_variable_signal = system_condition_variable_signal;
vtable->condition_variable_free = system_condition_variable_free;
vtable->memory_allocate = system_memory_allocate;
vtable->memory_set_protection = system_memory_set_protection;
vtable->memory_free = system_memory_free;
vtable->memory_annotation = system_memory_annotation;
vtable->show_mouse_cursor = system_show_mouse_cursor;
vtable->set_fullscreen = system_set_fullscreen;
vtable->is_fullscreen = system_is_fullscreen;
vtable->get_keyboard_modifiers = system_get_keyboard_modifiers;
vtable->set_key_mode = system_set_key_mode;
vtable->set_source_mixer = system_set_source_mixer;
vtable->set_destination_mixer = system_set_destination_mixer;
}
#if defined(DYNAMIC_LINK_API)
function void
system_api_read_vtable(API_VTable_system *vtable){
system_error_box = vtable->error_box;
system_get_path = vtable->get_path;
system_get_canonical = vtable->get_canonical;
system_get_file_list = vtable->get_file_list;
system_quick_file_attributes = vtable->quick_file_attributes;
system_load_handle = vtable->load_handle;
system_load_attributes = vtable->load_attributes;
system_load_file = vtable->load_file;
system_load_close = vtable->load_close;
system_save_file = vtable->save_file;
system_load_library = vtable->load_library;
system_release_library = vtable->release_library;
system_get_proc = vtable->get_proc;
system_now_time = vtable->now_time;
system_now_date_time_universal = vtable->now_date_time_universal;
system_local_date_time_from_universal = vtable->local_date_time_from_universal;
system_universal_date_time_from_local = vtable->universal_date_time_from_local;
system_wake_up_timer_create = vtable->wake_up_timer_create;
system_wake_up_timer_release = vtable->wake_up_timer_release;
system_wake_up_timer_set = vtable->wake_up_timer_set;
system_signal_step = vtable->signal_step;
system_sleep = vtable->sleep;
system_get_clipboard = vtable->get_clipboard;
system_post_clipboard = vtable->post_clipboard;
system_set_clipboard_catch_all = vtable->set_clipboard_catch_all;
system_get_clipboard_catch_all = vtable->get_clipboard_catch_all;
system_cli_call = vtable->cli_call;
system_cli_begin_update = vtable->cli_begin_update;
system_cli_update_step = vtable->cli_update_step;
system_cli_end_update = vtable->cli_end_update;
system_open_color_picker = vtable->open_color_picker;
system_get_screen_scale_factor = vtable->get_screen_scale_factor;
system_thread_launch = vtable->thread_launch;
system_thread_join = vtable->thread_join;
system_thread_free = vtable->thread_free;
system_thread_get_id = vtable->thread_get_id;
system_acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
system_release_global_frame_mutex = vtable->release_global_frame_mutex;
system_mutex_make = vtable->mutex_make;
system_mutex_acquire = vtable->mutex_acquire;
system_mutex_release = vtable->mutex_release;
system_mutex_free = vtable->mutex_free;
system_condition_variable_make = vtable->condition_variable_make;
system_condition_variable_wait = vtable->condition_variable_wait;
system_condition_variable_signal = vtable->condition_variable_signal;
system_condition_variable_free = vtable->condition_variable_free;
system_memory_allocate = vtable->memory_allocate;
system_memory_set_protection = vtable->memory_set_protection;
system_memory_free = vtable->memory_free;
system_memory_annotation = vtable->memory_annotation;
system_show_mouse_cursor = vtable->show_mouse_cursor;
system_set_fullscreen = vtable->set_fullscreen;
system_is_fullscreen = vtable->is_fullscreen;
system_get_keyboard_modifiers = vtable->get_keyboard_modifiers;
system_set_key_mode = vtable->set_key_mode;
system_set_source_mixer = vtable->set_source_mixer;
system_set_destination_mixer = vtable->set_destination_mixer;
system_error_box = vtable->error_box;
system_get_path = vtable->get_path;
system_get_canonical = vtable->get_canonical;
system_get_file_list = vtable->get_file_list;
system_quick_file_attributes = vtable->quick_file_attributes;
system_load_handle = vtable->load_handle;
system_load_attributes = vtable->load_attributes;
system_load_file = vtable->load_file;
system_load_close = vtable->load_close;
system_save_file = vtable->save_file;
system_load_library = vtable->load_library;
system_release_library = vtable->release_library;
system_get_proc = vtable->get_proc;
system_now_time = vtable->now_time;
system_now_date_time_universal = vtable->now_date_time_universal;
system_local_date_time_from_universal = vtable->local_date_time_from_universal;
system_universal_date_time_from_local = vtable->universal_date_time_from_local;
system_wake_up_timer_create = vtable->wake_up_timer_create;
system_wake_up_timer_release = vtable->wake_up_timer_release;
system_wake_up_timer_set = vtable->wake_up_timer_set;
system_signal_step = vtable->signal_step;
system_sleep = vtable->sleep;
system_get_clipboard = vtable->get_clipboard;
system_post_clipboard = vtable->post_clipboard;
system_set_clipboard_catch_all = vtable->set_clipboard_catch_all;
system_get_clipboard_catch_all = vtable->get_clipboard_catch_all;
system_cli_call = vtable->cli_call;
system_cli_begin_update = vtable->cli_begin_update;
system_cli_update_step = vtable->cli_update_step;
system_cli_end_update = vtable->cli_end_update;
system_open_color_picker = vtable->open_color_picker;
system_get_screen_scale_factor = vtable->get_screen_scale_factor;
system_thread_launch = vtable->thread_launch;
system_thread_join = vtable->thread_join;
system_thread_free = vtable->thread_free;
system_thread_get_id = vtable->thread_get_id;
system_acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
system_release_global_frame_mutex = vtable->release_global_frame_mutex;
system_mutex_make = vtable->mutex_make;
system_mutex_acquire = vtable->mutex_acquire;
system_mutex_release = vtable->mutex_release;
system_mutex_free = vtable->mutex_free;
system_condition_variable_make = vtable->condition_variable_make;
system_condition_variable_wait = vtable->condition_variable_wait;
system_condition_variable_signal = vtable->condition_variable_signal;
system_condition_variable_free = vtable->condition_variable_free;
system_memory_allocate = vtable->memory_allocate;
system_memory_set_protection = vtable->memory_set_protection;
system_memory_free = vtable->memory_free;
system_memory_annotation = vtable->memory_annotation;
system_show_mouse_cursor = vtable->show_mouse_cursor;
system_set_fullscreen = vtable->set_fullscreen;
system_is_fullscreen = vtable->is_fullscreen;
system_get_keyboard_modifiers = vtable->get_keyboard_modifiers;
system_set_key_mode = vtable->set_key_mode;
system_set_source_mixer = vtable->set_source_mixer;
system_set_destination_mixer = vtable->set_destination_mixer;
}
#undef DYNAMIC_LINK_API
#endif

View File

@ -1,5 +1,3 @@
/* Generated by "code/4ed_system_api.cpp" */
#define system_error_box_sig() void system_error_box(char* msg)
#define system_get_path_sig() String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code)
#define system_get_canonical_sig() String_Const_u8 system_get_canonical(Arena* arena, String_Const_u8 name)
@ -57,7 +55,6 @@
#define system_set_key_mode_sig() void system_set_key_mode(Key_Mode mode)
#define system_set_source_mixer_sig() void system_set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func)
#define system_set_destination_mixer_sig() void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func)
typedef void system_error_box_type(char* msg);
typedef String_Const_u8 system_get_path_type(Arena* arena, System_Path_Code path_code);
typedef String_Const_u8 system_get_canonical_type(Arena* arena, String_Const_u8 name);
@ -115,67 +112,65 @@ typedef Input_Modifier_Set system_get_keyboard_modifiers_type(Arena* arena);
typedef void system_set_key_mode_type(Key_Mode mode);
typedef void system_set_source_mixer_type(void* ctx, Audio_Mix_Sources_Function* mix_func);
typedef void system_set_destination_mixer_type(Audio_Mix_Destination_Function* mix_func);
struct API_VTable_system{
system_error_box_type *error_box;
system_get_path_type *get_path;
system_get_canonical_type *get_canonical;
system_get_file_list_type *get_file_list;
system_quick_file_attributes_type *quick_file_attributes;
system_load_handle_type *load_handle;
system_load_attributes_type *load_attributes;
system_load_file_type *load_file;
system_load_close_type *load_close;
system_save_file_type *save_file;
system_load_library_type *load_library;
system_release_library_type *release_library;
system_get_proc_type *get_proc;
system_now_time_type *now_time;
system_now_date_time_universal_type *now_date_time_universal;
system_local_date_time_from_universal_type *local_date_time_from_universal;
system_universal_date_time_from_local_type *universal_date_time_from_local;
system_wake_up_timer_create_type *wake_up_timer_create;
system_wake_up_timer_release_type *wake_up_timer_release;
system_wake_up_timer_set_type *wake_up_timer_set;
system_signal_step_type *signal_step;
system_sleep_type *sleep;
system_get_clipboard_type *get_clipboard;
system_post_clipboard_type *post_clipboard;
system_set_clipboard_catch_all_type *set_clipboard_catch_all;
system_get_clipboard_catch_all_type *get_clipboard_catch_all;
system_cli_call_type *cli_call;
system_cli_begin_update_type *cli_begin_update;
system_cli_update_step_type *cli_update_step;
system_cli_end_update_type *cli_end_update;
system_open_color_picker_type *open_color_picker;
system_get_screen_scale_factor_type *get_screen_scale_factor;
system_thread_launch_type *thread_launch;
system_thread_join_type *thread_join;
system_thread_free_type *thread_free;
system_thread_get_id_type *thread_get_id;
system_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
system_release_global_frame_mutex_type *release_global_frame_mutex;
system_mutex_make_type *mutex_make;
system_mutex_acquire_type *mutex_acquire;
system_mutex_release_type *mutex_release;
system_mutex_free_type *mutex_free;
system_condition_variable_make_type *condition_variable_make;
system_condition_variable_wait_type *condition_variable_wait;
system_condition_variable_signal_type *condition_variable_signal;
system_condition_variable_free_type *condition_variable_free;
system_memory_allocate_type *memory_allocate;
system_memory_set_protection_type *memory_set_protection;
system_memory_free_type *memory_free;
system_memory_annotation_type *memory_annotation;
system_show_mouse_cursor_type *show_mouse_cursor;
system_set_fullscreen_type *set_fullscreen;
system_is_fullscreen_type *is_fullscreen;
system_get_keyboard_modifiers_type *get_keyboard_modifiers;
system_set_key_mode_type *set_key_mode;
system_set_source_mixer_type *set_source_mixer;
system_set_destination_mixer_type *set_destination_mixer;
system_error_box_type *error_box;
system_get_path_type *get_path;
system_get_canonical_type *get_canonical;
system_get_file_list_type *get_file_list;
system_quick_file_attributes_type *quick_file_attributes;
system_load_handle_type *load_handle;
system_load_attributes_type *load_attributes;
system_load_file_type *load_file;
system_load_close_type *load_close;
system_save_file_type *save_file;
system_load_library_type *load_library;
system_release_library_type *release_library;
system_get_proc_type *get_proc;
system_now_time_type *now_time;
system_now_date_time_universal_type *now_date_time_universal;
system_local_date_time_from_universal_type *local_date_time_from_universal;
system_universal_date_time_from_local_type *universal_date_time_from_local;
system_wake_up_timer_create_type *wake_up_timer_create;
system_wake_up_timer_release_type *wake_up_timer_release;
system_wake_up_timer_set_type *wake_up_timer_set;
system_signal_step_type *signal_step;
system_sleep_type *sleep;
system_get_clipboard_type *get_clipboard;
system_post_clipboard_type *post_clipboard;
system_set_clipboard_catch_all_type *set_clipboard_catch_all;
system_get_clipboard_catch_all_type *get_clipboard_catch_all;
system_cli_call_type *cli_call;
system_cli_begin_update_type *cli_begin_update;
system_cli_update_step_type *cli_update_step;
system_cli_end_update_type *cli_end_update;
system_open_color_picker_type *open_color_picker;
system_get_screen_scale_factor_type *get_screen_scale_factor;
system_thread_launch_type *thread_launch;
system_thread_join_type *thread_join;
system_thread_free_type *thread_free;
system_thread_get_id_type *thread_get_id;
system_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
system_release_global_frame_mutex_type *release_global_frame_mutex;
system_mutex_make_type *mutex_make;
system_mutex_acquire_type *mutex_acquire;
system_mutex_release_type *mutex_release;
system_mutex_free_type *mutex_free;
system_condition_variable_make_type *condition_variable_make;
system_condition_variable_wait_type *condition_variable_wait;
system_condition_variable_signal_type *condition_variable_signal;
system_condition_variable_free_type *condition_variable_free;
system_memory_allocate_type *memory_allocate;
system_memory_set_protection_type *memory_set_protection;
system_memory_free_type *memory_free;
system_memory_annotation_type *memory_annotation;
system_show_mouse_cursor_type *show_mouse_cursor;
system_set_fullscreen_type *set_fullscreen;
system_is_fullscreen_type *is_fullscreen;
system_get_keyboard_modifiers_type *get_keyboard_modifiers;
system_set_key_mode_type *set_key_mode;
system_set_source_mixer_type *set_source_mixer;
system_set_destination_mixer_type *set_destination_mixer;
};
#if defined(STATIC_LINK_API)
internal void system_error_box(char* msg);
internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code);
@ -235,7 +230,6 @@ internal void system_set_key_mode(Key_Mode mode);
internal void system_set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func);
internal void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func);
#undef STATIC_LINK_API
#elif defined(DYNAMIC_LINK_API)
global system_error_box_type *system_error_box = 0;
global system_get_path_type *system_get_path = 0;

View File

@ -1,264 +1,262 @@
/* Generated by "code/4ed_system_api.cpp" */
function API_Definition*
system_api_construct(Arena *arena){
API_Definition *result = begin_api(arena, "system");
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("error_box"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "char*", "msg");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_path"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "System_Path_Code", "path_code");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_canonical"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "String_Const_u8", "name");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_file_list"), string_u8_litexpr("File_List"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "String_Const_u8", "directory");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("quick_file_attributes"), string_u8_litexpr("File_Attributes"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "String_Const_u8", "file_name");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_handle"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "char*", "file_name");
api_param(arena, call, "Plat_Handle*", "out");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_attributes"), string_u8_litexpr("File_Attributes"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_file"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
api_param(arena, call, "char*", "buffer");
api_param(arena, call, "u32", "size");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_close"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("save_file"), string_u8_litexpr("File_Attributes"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "char*", "file_name");
api_param(arena, call, "String_Const_u8", "data");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_library"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "String_Const_u8", "file_name");
api_param(arena, call, "System_Library*", "out");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("release_library"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "System_Library", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_proc"), string_u8_litexpr("Void_Func*"), string_u8_litexpr(""));
api_param(arena, call, "System_Library", "handle");
api_param(arena, call, "char*", "proc_name");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("now_time"), string_u8_litexpr("u64"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("now_date_time_universal"), string_u8_litexpr("Date_Time"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("local_date_time_from_universal"), string_u8_litexpr("Date_Time"), string_u8_litexpr(""));
api_param(arena, call, "Date_Time*", "date_time");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("universal_date_time_from_local"), string_u8_litexpr("Date_Time"), string_u8_litexpr(""));
api_param(arena, call, "Date_Time*", "date_time");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("wake_up_timer_create"), string_u8_litexpr("Plat_Handle"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("wake_up_timer_release"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("wake_up_timer_set"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
api_param(arena, call, "u32", "time_milliseconds");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("signal_step"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "u32", "code");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("sleep"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "u64", "microseconds");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_clipboard"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "i32", "index");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("post_clipboard"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "String_Const_u8", "str");
api_param(arena, call, "i32", "index");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_clipboard_catch_all"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "b32", "enabled");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_clipboard_catch_all"), string_u8_litexpr("b32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_call"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "char*", "path");
api_param(arena, call, "char*", "script");
api_param(arena, call, "CLI_Handles*", "cli_out");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_begin_update"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "CLI_Handles*", "cli");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_update_step"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "CLI_Handles*", "cli");
api_param(arena, call, "char*", "dest");
api_param(arena, call, "u32", "max");
api_param(arena, call, "u32*", "amount");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_end_update"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "CLI_Handles*", "cli");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("open_color_picker"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Color_Picker*", "picker");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_screen_scale_factor"), string_u8_litexpr("f32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_launch"), string_u8_litexpr("System_Thread"), string_u8_litexpr(""));
api_param(arena, call, "Thread_Function*", "proc");
api_param(arena, call, "void*", "ptr");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_join"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Thread", "thread");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Thread", "thread");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_get_id"), string_u8_litexpr("i32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("acquire_global_frame_mutex"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Thread_Context*", "tctx");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("release_global_frame_mutex"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Thread_Context*", "tctx");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_make"), string_u8_litexpr("System_Mutex"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_acquire"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_release"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_make"), string_u8_litexpr("System_Condition_Variable"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_wait"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Condition_Variable", "cv");
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_signal"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Condition_Variable", "cv");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Condition_Variable", "cv");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_allocate"), string_u8_litexpr("void*"), string_u8_litexpr(""));
api_param(arena, call, "u64", "size");
api_param(arena, call, "String_Const_u8", "location");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_set_protection"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "void*", "ptr");
api_param(arena, call, "u64", "size");
api_param(arena, call, "u32", "flags");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "void*", "ptr");
api_param(arena, call, "u64", "size");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_annotation"), string_u8_litexpr("Memory_Annotation"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("show_mouse_cursor"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "i32", "show");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_fullscreen"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "b32", "full_screen");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("is_fullscreen"), string_u8_litexpr("b32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_keyboard_modifiers"), string_u8_litexpr("Input_Modifier_Set"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_key_mode"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Key_Mode", "mode");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_source_mixer"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "void*", "ctx");
api_param(arena, call, "Audio_Mix_Sources_Function*", "mix_func");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_destination_mixer"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Audio_Mix_Destination_Function*", "mix_func");
}
return(result);
API_Definition *result = begin_api(arena, "system");
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("error_box"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "char*", "msg");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_path"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "System_Path_Code", "path_code");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_canonical"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "String_Const_u8", "name");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_file_list"), string_u8_litexpr("File_List"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "String_Const_u8", "directory");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("quick_file_attributes"), string_u8_litexpr("File_Attributes"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "String_Const_u8", "file_name");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_handle"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "char*", "file_name");
api_param(arena, call, "Plat_Handle*", "out");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_attributes"), string_u8_litexpr("File_Attributes"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_file"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
api_param(arena, call, "char*", "buffer");
api_param(arena, call, "u32", "size");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_close"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("save_file"), string_u8_litexpr("File_Attributes"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "char*", "file_name");
api_param(arena, call, "String_Const_u8", "data");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("load_library"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "String_Const_u8", "file_name");
api_param(arena, call, "System_Library*", "out");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("release_library"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "System_Library", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_proc"), string_u8_litexpr("Void_Func*"), string_u8_litexpr(""));
api_param(arena, call, "System_Library", "handle");
api_param(arena, call, "char*", "proc_name");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("now_time"), string_u8_litexpr("u64"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("now_date_time_universal"), string_u8_litexpr("Date_Time"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("local_date_time_from_universal"), string_u8_litexpr("Date_Time"), string_u8_litexpr(""));
api_param(arena, call, "Date_Time*", "date_time");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("universal_date_time_from_local"), string_u8_litexpr("Date_Time"), string_u8_litexpr(""));
api_param(arena, call, "Date_Time*", "date_time");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("wake_up_timer_create"), string_u8_litexpr("Plat_Handle"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("wake_up_timer_release"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("wake_up_timer_set"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Plat_Handle", "handle");
api_param(arena, call, "u32", "time_milliseconds");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("signal_step"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "u32", "code");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("sleep"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "u64", "microseconds");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_clipboard"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "i32", "index");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("post_clipboard"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "String_Const_u8", "str");
api_param(arena, call, "i32", "index");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_clipboard_catch_all"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "b32", "enabled");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_clipboard_catch_all"), string_u8_litexpr("b32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_call"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "scratch");
api_param(arena, call, "char*", "path");
api_param(arena, call, "char*", "script");
api_param(arena, call, "CLI_Handles*", "cli_out");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_begin_update"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "CLI_Handles*", "cli");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_update_step"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "CLI_Handles*", "cli");
api_param(arena, call, "char*", "dest");
api_param(arena, call, "u32", "max");
api_param(arena, call, "u32*", "amount");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_end_update"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "CLI_Handles*", "cli");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("open_color_picker"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Color_Picker*", "picker");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_screen_scale_factor"), string_u8_litexpr("f32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_launch"), string_u8_litexpr("System_Thread"), string_u8_litexpr(""));
api_param(arena, call, "Thread_Function*", "proc");
api_param(arena, call, "void*", "ptr");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_join"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Thread", "thread");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Thread", "thread");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_get_id"), string_u8_litexpr("i32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("acquire_global_frame_mutex"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Thread_Context*", "tctx");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("release_global_frame_mutex"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Thread_Context*", "tctx");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_make"), string_u8_litexpr("System_Mutex"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_acquire"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_release"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_make"), string_u8_litexpr("System_Condition_Variable"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_wait"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Condition_Variable", "cv");
api_param(arena, call, "System_Mutex", "mutex");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_signal"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Condition_Variable", "cv");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("condition_variable_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "System_Condition_Variable", "cv");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_allocate"), string_u8_litexpr("void*"), string_u8_litexpr(""));
api_param(arena, call, "u64", "size");
api_param(arena, call, "String_Const_u8", "location");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_set_protection"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "void*", "ptr");
api_param(arena, call, "u64", "size");
api_param(arena, call, "u32", "flags");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_free"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "void*", "ptr");
api_param(arena, call, "u64", "size");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("memory_annotation"), string_u8_litexpr("Memory_Annotation"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("show_mouse_cursor"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "i32", "show");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_fullscreen"), string_u8_litexpr("b32"), string_u8_litexpr(""));
api_param(arena, call, "b32", "full_screen");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("is_fullscreen"), string_u8_litexpr("b32"), string_u8_litexpr(""));
(void)call;
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_keyboard_modifiers"), string_u8_litexpr("Input_Modifier_Set"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_key_mode"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Key_Mode", "mode");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_source_mixer"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "void*", "ctx");
api_param(arena, call, "Audio_Mix_Sources_Function*", "mix_func");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("set_destination_mixer"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "Audio_Mix_Destination_Function*", "mix_func");
}
return(result);
}

View File

@ -1,5 +1,3 @@
/* Generated by "code/4ed_system_api.cpp" */
api(system) function void error_box(char* msg);
api(system) function String_Const_u8 get_path(Arena* arena, System_Path_Code path_code);
api(system) function String_Const_u8 get_canonical(Arena* arena, String_Const_u8 name);

View File

@ -1,14 +1,11 @@
/* Generated by "code/4ed_font_api.cpp" */
function void
font_api_fill_vtable(API_VTable_font *vtable){
vtable->make_face = font_make_face;
vtable->make_face = font_make_face;
}
#if defined(DYNAMIC_LINK_API)
function void
font_api_read_vtable(API_VTable_font *vtable){
font_make_face = vtable->make_face;
font_make_face = vtable->make_face;
}
#undef DYNAMIC_LINK_API
#endif

View File

@ -1,17 +1,11 @@
/* Generated by "code/4ed_font_api.cpp" */
#define font_make_face_sig() Face* font_make_face(Arena* arena, Face_Description* description, f32 scale_factor)
typedef Face* font_make_face_type(Arena* arena, Face_Description* description, f32 scale_factor);
struct API_VTable_font{
font_make_face_type *make_face;
font_make_face_type *make_face;
};
#if defined(STATIC_LINK_API)
internal Face* font_make_face(Arena* arena, Face_Description* description, f32 scale_factor);
#undef STATIC_LINK_API
#elif defined(DYNAMIC_LINK_API)
global font_make_face_type *font_make_face = 0;
#undef DYNAMIC_LINK_API

View File

@ -1,18 +1,13 @@
/* Generated by "code/4ed_graphics_api.cpp" */
function void
graphics_api_fill_vtable(API_VTable_graphics *vtable){
vtable->get_texture = graphics_get_texture;
vtable->fill_texture = graphics_fill_texture;
vtable->free_texture = graphics_free_texture;
vtable->get_texture = graphics_get_texture;
vtable->fill_texture = graphics_fill_texture;
}
#if defined(DYNAMIC_LINK_API)
function void
graphics_api_read_vtable(API_VTable_graphics *vtable){
graphics_get_texture = vtable->get_texture;
graphics_fill_texture = vtable->fill_texture;
graphics_free_texture = vtable->free_texture;
graphics_get_texture = vtable->get_texture;
graphics_fill_texture = vtable->fill_texture;
}
#undef DYNAMIC_LINK_API
#endif

View File

@ -1,28 +1,17 @@
/* Generated by "code/4ed_graphics_api.cpp" */
#define graphics_get_texture_sig() u32 graphics_get_texture(Vec3_i32 dim, Texture_Kind texture_kind)
#define graphics_fill_texture_sig() b32 graphics_fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void* data)
#define graphics_free_texture_sig() void graphics_free_texture(u32 texid)
typedef u32 graphics_get_texture_type(Vec3_i32 dim, Texture_Kind texture_kind);
typedef b32 graphics_fill_texture_type(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void* data);
typedef void graphics_free_texture_type(u32 texid);
struct API_VTable_graphics{
graphics_get_texture_type *get_texture;
graphics_fill_texture_type *fill_texture;
graphics_free_texture_type *free_texture;
graphics_get_texture_type *get_texture;
graphics_fill_texture_type *fill_texture;
};
#if defined(STATIC_LINK_API)
internal u32 graphics_get_texture(Vec3_i32 dim, Texture_Kind texture_kind);
internal b32 graphics_fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void* data);
internal void graphics_free_texture(u32 texid);
#undef STATIC_LINK_API
#elif defined(DYNAMIC_LINK_API)
global graphics_get_texture_type *graphics_get_texture = 0;
global graphics_fill_texture_type *graphics_fill_texture = 0;
global graphics_free_texture_type *graphics_free_texture = 0;
#undef DYNAMIC_LINK_API
#endif

View File

@ -10,7 +10,7 @@
struct Metal_Buffer{
Node node;
id<MTLBuffer> buffer;
u32 size;
u64 last_reuse_time;
@ -23,7 +23,7 @@ typedef id<MTLTexture> Metal_Texture;
// NOTE(yuval): This is a locator used to describe where a specific slot is located.
union Metal_Texture_Slot_Locator{
u32 packed;
struct{
u16 bucket_index;
u16 slot_index;
@ -34,7 +34,7 @@ union Metal_Texture_Slot_Locator{
struct Metal_Texture_Slot{
// NOTE(yuval): This is a pointer to the next texture in the free texture slots list
Metal_Texture_Slot *next;
Metal_Texture texture;
Metal_Texture_Slot_Locator locator;
};
@ -52,12 +52,12 @@ struct Metal_Texture_Slot_List{
Metal_Texture_Slot_Bucket *first_bucket;
Metal_Texture_Slot_Bucket *last_bucket;
u16 bucket_count;
Metal_Texture_Slot *first_free_slot;
Metal_Texture_Slot *last_free_slot;
};
global_const u32 metal__invalid_texture_slot_locator = 0;
global_const u32 metal__invalid_texture_slot_locator = (u32)-1;
////////////////////////////////
@ -67,7 +67,6 @@ global_const u32 metal__invalid_texture_slot_locator = 0;
- (u32)get_texture_of_dim:(Vec3_i32)dim kind:(Texture_Kind)kind;
- (b32)fill_texture:(u32)texture kind:(Texture_Kind)kind pos:(Vec3_i32)p dim:(Vec3_i32)dim data:(void*)data;
- (void)bind_texture:(u32)handle encoder:(id<MTLRenderCommandEncoder>)render_encoder;
- (void)free_texture:(u32)handle;
- (Metal_Texture_Slot*)get_texture_slot_at_locator:(Metal_Texture_Slot_Locator)locator;
- (Metal_Texture_Slot*)get_texture_slot_at_handle:(u32)handle;
@ -176,15 +175,15 @@ return(out_color);
function Metal_Buffer*
metal__make_buffer(u32 size, id<MTLDevice> device){
Metal_Buffer *result = (Metal_Buffer*)malloc(sizeof(Metal_Buffer));
// NOTE(yuval): Create the vertex buffer
MTLResourceOptions options = MTLCPUCacheModeWriteCombined|MTLResourceStorageModeManaged;
result->buffer = [device newBufferWithLength:size options:options];
result->size = size;
// NOTE(yuval): Set the last_reuse_time to the current time
result->last_reuse_time = system_now_time();
return result;
}
@ -192,15 +191,15 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
@implementation Metal_Renderer{
Render_Target *_target;
id<MTLDevice> _device;
id<MTLRenderPipelineState> _pipeline_state;
id<MTLCommandQueue> _command_queue;
id<MTLCaptureScope> _capture_scope;
Node _buffer_cache;
u64 _last_buffer_cache_purge_time;
Metal_Texture_Slot_List _texture_slots;
}
@ -209,33 +208,33 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
if (self == nil){
return(nil);
}
_target = target;
NSError *error = nil;
_device = mtk_view.device;
// NOTE(yuval): Compile the shaders
id<MTLFunction> vertex_function = nil;
id<MTLFunction> fragment_function = nil;
{
NSString *shaders_source_str = [NSString stringWithUTF8String:metal__shaders_source];
MTLCompileOptions *options = [[MTLCompileOptions alloc] init];
options.fastMathEnabled = YES;
id<MTLLibrary> shader_library = [_device newLibraryWithSource:shaders_source_str
options:options error:&error];
vertex_function = [shader_library newFunctionWithName:@"vertex_shader"];
fragment_function = [shader_library newFunctionWithName:@"fragment_shader"];
[options release];
}
Assert(error == nil);
Assert((vertex_function != nil) && (fragment_function != nil));
// NOTE(yuval): Configure the pipeline descriptor
{
MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
@ -254,7 +253,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
vertexDescriptor.layouts[0].stepRate = 1;
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
vertexDescriptor.layouts[0].stride = sizeof(Render_Vertex);
MTLRenderPipelineDescriptor *pipeline_state_descriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipeline_state_descriptor.label = @"4coder Metal Renderer Pipeline";
pipeline_state_descriptor.vertexFunction = vertex_function;
@ -268,28 +267,23 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
pipeline_state_descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
pipeline_state_descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
pipeline_state_descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
_pipeline_state = [_device newRenderPipelineStateWithDescriptor:pipeline_state_descriptor
error:&error];
}
Assert(error == nil);
// NOTE(yuval): Create the command queue
_command_queue = [_device newCommandQueue];
// NOTE(yuval): Initialize buffer caching
dll_init_sentinel(&_buffer_cache);
_last_buffer_cache_purge_time = system_now_time();
// NOTE(yuval): Initialize the texture slot list
block_zero_struct(&_texture_slots);
// NOTE(simon): Other platforms use 0 as invalid handle, so we allocate the first texture here (it should be 0),
// and never use it so we can use 0 as the invalid handle.
u32 reserved_texture_slot_do_not_use = [self get_texture_of_dim:V3i32(2, 2, 1) kind:TextureKind_Mono];
Assert( reserved_texture_slot_do_not_use == 0 );
// NOTE(yuval): Create the fallback texture
_target->fallback_texture_id = [self get_texture_of_dim:V3i32(2, 2, 1)
kind:TextureKind_Mono];
@ -299,12 +293,12 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
pos:V3i32(0, 0, 0)
dim:V3i32(2, 2, 1)
data:white_block];
// NOTE(yuval): Create a capture scope for gpu frame capture
_capture_scope = [[MTLCaptureManager sharedCaptureManager]
newCaptureScopeWithDevice:_device];
_capture_scope.label = @"4coder Metal Capture Scope";
return(self);
}
@ -316,14 +310,14 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
#if FRED_INTERNAL
[_capture_scope beginScope];
#endif
// HACK(yuval): This is the best way I found to force valid width and height without drawing on the next draw cycle (1 frame delay).
CGSize drawable_size = [view drawableSize];
i32 width = (i32)Min(_target->width, drawable_size.width);
i32 height = (i32)Min(_target->height, drawable_size.height);
Font_Set *font_set = (Font_Set*)_target->font_set;
// NOTE(yuval): Free any textures in the target's texture free list
for (Render_Free_Texture *free_texture = _target->free_texture_first;
free_texture;
@ -335,27 +329,27 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
}
_target->free_texture_first = 0;
_target->free_texture_last = 0;
// NOTE(yuval): Create the command buffer
id<MTLCommandBuffer> command_buffer = [_command_queue commandBuffer];
command_buffer.label = @"4coder Metal Render Command";
// NOTE(yuval): Obtain the render pass descriptor from the renderer's view
MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor;
if (render_pass_descriptor != nil){
render_pass_descriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f);
// NOTE(yuval): Create the render command encoder
id<MTLRenderCommandEncoder> render_encoder =
[command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor];
render_encoder.label = @"4coder Render Encoder";
// NOTE(yuval): Set the region of the drawable to draw into
[render_encoder setViewport:(MTLViewport){0.0, 0.0, (double)width, (double)height, 0.0, 1.0}];
// NOTE(yuval): Set the render pipeline to use for drawing
[render_encoder setRenderPipelineState:_pipeline_state];
// NOTE(yuval): Calculate the projection matrix
float left = 0, right = (float)width;
float bottom = (float)height, top = 0;
@ -367,7 +361,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)),
-(near_depth / (far_depth - near_depth)), 1.0f
};
// NOTE(yuval): Calculate required vertex buffer size
i32 all_vertex_count = 0;
for (Render_Group *group = _target->group_first;
@ -375,22 +369,22 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
group = group->next){
all_vertex_count += group->vertex_list.vertex_count;
}
u32 vertex_buffer_size = (all_vertex_count * sizeof(Render_Vertex));
// NOTE(yuval): Find & Get a vertex buffer matching the required size
Metal_Buffer *buffer = [self get_reusable_buffer_with_size:vertex_buffer_size];
// NOTE(yuval): Pass the vertex buffer to the vertex shader
[render_encoder setVertexBuffer:buffer->buffer
offset:0
atIndex:0];
// NOTE(yuval): Pass the projection matrix to the vertex shader
[render_encoder setVertexBytes:&proj
length:sizeof(proj)
atIndex:1];
u32 buffer_offset = 0;
for (Render_Group *group = _target->group_first;
group;
@ -398,21 +392,21 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
// NOTE(yuval): Set scissor rect
{
Rect_i32 box = Ri32(group->clip_box);
NSUInteger x0 = (NSUInteger)Min(Max(0, box.x0), width - 1);
NSUInteger x1 = (NSUInteger)Min(Max(0, box.x1), width);
NSUInteger y0 = (NSUInteger)Min(Max(0, box.y0), height - 1);
NSUInteger y1 = (NSUInteger)Min(Max(0, box.y1), height);
MTLScissorRect scissor_rect;
scissor_rect.x = x0;
scissor_rect.y = y0;
scissor_rect.width = (x1 - x0);
scissor_rect.height = (y1 - y0);
[render_encoder setScissorRect:scissor_rect];
}
i32 vertex_count = group->vertex_list.vertex_count;
if (vertex_count > 0){
// NOTE(yuval): Bind a texture
@ -428,10 +422,10 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
encoder:render_encoder];
}
}
// NOTE(yuval): Copy the vertex data to the vertex buffer
{
u8 *group_buffer_contents = (u8*)[buffer->buffer contents] + buffer_offset;
u8 *cursor = group_buffer_contents;
for (Render_Vertex_Array_Node *node = group->vertex_list.first;
@ -441,39 +435,39 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
memcpy(cursor, node->vertices, size);
cursor += size;
}
NSUInteger data_size = (NSUInteger)(cursor - group_buffer_contents);
NSRange modify_range = NSMakeRange(buffer_offset, data_size);
[buffer->buffer didModifyRange:modify_range];
}
// NOTE(yuval): Set the vertex buffer offset to the beginning of the group's vertices
[render_encoder setVertexBufferOffset:buffer_offset atIndex:0];
// NOTE(yuval): Draw the vertices
[render_encoder drawPrimitives:MTLPrimitiveTypeTriangle
vertexStart:0
vertexCount:vertex_count];
buffer_offset += (vertex_count * sizeof(Render_Vertex));
}
}
[render_encoder endEncoding];
// NOTE(yuval): Schedule a present once the framebuffer is complete using the current drawable
[command_buffer presentDrawable:view.currentDrawable];
[command_buffer addCompletedHandler:^(id<MTLCommandBuffer>){
dispatch_async(dispatch_get_main_queue(), ^{
[self add_reusable_buffer:buffer];
});
}];
}
// NOTE(yuval): Finalize rendering here and push the command buffer to the GPU
[command_buffer commit];
#if FRED_INTERNAL
[_capture_scope endScope];
#endif
@ -481,14 +475,14 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
- (u32)get_texture_of_dim:(Vec3_i32)dim kind:(Texture_Kind)kind{
u32 handle = metal__invalid_texture_slot_locator;
// NOTE(yuval): Check for a free texture slot and allocate another slot bucket if no free slot has been found
if (!_texture_slots.first_free_slot){
// NOTE(yuval): Assert that the next bucket's index can fit in a u16
Assert(_texture_slots.bucket_count < ((u16)-1));
Metal_Texture_Slot_Bucket *bucket = (Metal_Texture_Slot_Bucket*)system_memory_allocate(sizeof(Metal_Texture_Slot_Bucket), file_name_line_number_lit_u8);
for (u16 slot_index = 0;
slot_index < ArrayCount(bucket->slots);
++slot_index){
@ -496,67 +490,63 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
block_zero_struct(slot);
slot->locator.bucket_index = _texture_slots.bucket_count;
slot->locator.slot_index = slot_index;
sll_queue_push(_texture_slots.first_free_slot, _texture_slots.last_free_slot, slot);
}
sll_queue_push(_texture_slots.first_bucket, _texture_slots.last_bucket, bucket);
_texture_slots.bucket_count += 1;
}
// NOTE(yuval): Get the first free texture slot and remove it from the free list (a slot is guarenteed to exist because we assert that above).
if (_texture_slots.first_free_slot){
Metal_Texture_Slot *texture_slot = _texture_slots.first_free_slot;
sll_queue_pop(_texture_slots.first_free_slot, _texture_slots.last_free_slot);
texture_slot->next = 0;
// NOTE(yuval): Create a texture descriptor.
MTLTextureDescriptor *texture_descriptor = [[MTLTextureDescriptor alloc] init];
texture_descriptor.textureType = MTLTextureType2DArray;
texture_descriptor.pixelFormat = MTLPixelFormatR8Unorm;
texture_descriptor.width = dim.x;
texture_descriptor.height = dim.y;
texture_descriptor.arrayLength = dim.z;
texture_descriptor.depth = dim.z;
// NOTE(yuval): Create the texture from the device using the descriptor and add it to the textures array.
Metal_Texture texture = [_device newTextureWithDescriptor:texture_descriptor];
texture_slot->texture = texture;
handle = texture_slot->locator.packed;
}
return handle;
}
- (b32)fill_texture:(u32)handle kind:(Texture_Kind)kind pos:(Vec3_i32)p dim:(Vec3_i32)dim data:(void*)data{
b32 result = false;
if (data){
Metal_Texture_Slot *texture_slot = [self get_texture_slot_at_handle:handle];
if (texture_slot){
Metal_Texture texture = texture_slot->texture;
if (texture != 0){
// https://developer.apple.com/documentation/metal/mtlregion
// for 2d texture origin.z is 0, and depth is 1
MTLRegion replace_region = {
{(NSUInteger)p.x, (NSUInteger)p.y, 0},
{(NSUInteger)dim.x, (NSUInteger)dim.y, 1}
{(NSUInteger)p.x, (NSUInteger)p.y, (NSUInteger)p.z},
{(NSUInteger)dim.x, (NSUInteger)dim.y, (NSUInteger)dim.z}
};
// NOTE(yuval): Fill the texture with data
[texture replaceRegion:replace_region
mipmapLevel:0
slice:p.z
withBytes:data
bytesPerRow:dim.x
bytesPerImage:0];
bytesPerRow:dim.x];
result = true;
}
}
}
return(result);
}
@ -571,49 +561,41 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
}
}
- (void)free_texture:(u32)handle{
Metal_Texture_Slot *texture_slot = [self get_texture_slot_at_handle:handle];
if (texture_slot){
sll_queue_push(_texture_slots.first_free_slot, _texture_slots.last_free_slot, texture_slot);
}
}
- (Metal_Texture_Slot*)get_texture_slot_at_locator:(Metal_Texture_Slot_Locator)locator{
Metal_Texture_Slot *result = 0;
if (locator.packed != metal__invalid_texture_slot_locator){
Metal_Texture_Slot_Bucket *bucket = _texture_slots.first_bucket;
for (u16 bucket_index = 0;
(bucket_index < locator.bucket_index) && bucket;
++bucket_index, bucket = bucket->next);
if (bucket && (locator.slot_index < metal__texture_slots_per_bucket)){
result = &bucket->slots[locator.slot_index];
}
}
return(result);
}
- (Metal_Texture_Slot*)get_texture_slot_at_handle:(u32)handle{
Metal_Texture_Slot_Locator locator;
locator.packed = handle;
Metal_Texture_Slot *result = [self get_texture_slot_at_locator:locator];
return(result);
}
- (Metal_Buffer*)get_reusable_buffer_with_size:(NSUInteger)size{
// NOTE(yuval): This routine is a modified version of Dear ImGui's MetalContext::dequeueReusableBufferOfLength in imgui_impl_metal.mm
u64 now = system_now_time();
// NOTE(yuval): Purge old buffers that haven't been useful for a while
if ((now - _last_buffer_cache_purge_time) > 1000000){
Node prev_buffer_cache = _buffer_cache;
dll_init_sentinel(&_buffer_cache);
for (Node *node = prev_buffer_cache.next;
node != &_buffer_cache;
node = node->next){
@ -622,10 +604,10 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
dll_insert(&_buffer_cache, node);
}
}
_last_buffer_cache_purge_time = now;
}
// NOTE(yuval): See if we have a buffer we can reuse
Metal_Buffer *best_candidate = 0;
for (Node *node = _buffer_cache.next;
@ -636,7 +618,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
best_candidate = candidate;
}
}
Metal_Buffer *result;
if (best_candidate){
// NOTE(yuval): A best candidate has been found! Remove it from the buffer list and set its last reuse time.
@ -647,13 +629,13 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
// NOTE(yuval): No luck; make a new buffer.
result = metal__make_buffer(size, _device);
}
return(result);
}
- (void)add_reusable_buffer:(Metal_Buffer*)buffer{
// NOTE(yuval): This routine is a modified version of Dear ImGui's MetalContext::enqueueReusableBuffer in imgui_impl_metal.mm
dll_insert(&_buffer_cache, &buffer->node);
}
@end
@end

View File

@ -53,11 +53,6 @@ gl__fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 di
return(result);
}
internal void
gl__free_texture(u32 texture){
glDeleteTextures(1, &texture);
}
internal void
gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam){
switch (id){
@ -73,7 +68,7 @@ gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsiz
}
}
char *gl__header = R"foo(#version 150
char *gl__header = R"foo(#version 130
)foo";
char *gl__vertex = R"foo(
@ -112,20 +107,20 @@ char *gl__fragment = R"foo(
smooth in float half_thickness;
uniform sampler2DArray sampler;
out vec4 out_color;
float rectangle_sd(vec2 p, vec2 b){
vec2 d = abs(p) - b;
return(length(max(d, vec2(0.0, 0.0))) + min(max(d.x, d.y), 0.0));
}
void main(void)
{
float has_thickness = (step(0.49, half_thickness));
float does_not_have_thickness = 1.0 - has_thickness;
float sample_value = texture(sampler, uvw).r;
sample_value *= does_not_have_thickness;
vec2 center = uvw.xy;
float roundness = uvw.z;
float sd = rectangle_sd(xy - center, adjusted_half_dim);
@ -133,7 +128,7 @@ char *gl__fragment = R"foo(
sd = abs(sd + half_thickness) - half_thickness;
float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd);
shape_value *= has_thickness;
out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value));
}
)foo";

View File

@ -588,11 +588,6 @@ graphics_fill_texture_sig(){
return(gl__fill_texture(texture_kind, texture, p, dim, data));
}
internal
graphics_free_texture_sig(){
gl__free_texture(texid);
}
////////////////////////////
internal Face*
@ -705,8 +700,8 @@ glx_create_context(GLXFBConfig fb_config){
ctx = glXCreateNewContext(linuxvars.dpy, fb_config, GLX_RGBA_TYPE, 0, True);
} else {
static const int context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
#if GL_DEBUG_MODE
GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB,
@ -714,6 +709,7 @@ glx_create_context(GLXFBConfig fb_config){
None
};
//LOG("Creating GL 2.1 context... ");
ctx = glXCreateContextAttribsARB(linuxvars.dpy, fb_config, 0, True, context_attribs);
}

View File

@ -976,11 +976,6 @@ graphics_fill_texture_sig(){
return(result);
}
function
graphics_free_texture_sig(){
renderer->free_texture(renderer, texid);
}
////////////////////////////////
/******************/

View File

@ -44,12 +44,6 @@ mac_fill_texture_sig(mac_metal__fill_texture){
return(result);
}
function
mac_free_texture_sig(mac_metal__free_texture){
Mac_Metal *metal = (Mac_Metal*)renderer;
[metal->renderer free_texture:texture];
}
function Mac_Metal*
mac_metal__init(NSWindow *window, Render_Target *target){
// NOTE(yuval): Create the Mac Metal rendere
@ -58,8 +52,7 @@ mac_metal__init(NSWindow *window, Render_Target *target){
metal->base.render = mac_metal__render;
metal->base.get_texture = mac_metal__get_texture;
metal->base.fill_texture = mac_metal__fill_texture;
metal->base.free_texture = mac_metal__free_texture;
// NOTE(yuval): Create the Metal view
NSView *content_view = [window contentView];

View File

@ -144,11 +144,6 @@ mac_fill_texture_sig(mac_gl__fill_texture){
return(result);
}
function
mac_free_texture_sig(mac_gl__free_texture){
gl__free_texture(texture);
}
function Mac_OpenGL*
mac_gl__init(NSWindow *window, Render_Target *target){
// NOTE(yuval): Create the Mac OpenGL Renderer
@ -157,7 +152,6 @@ mac_gl__init(NSWindow *window, Render_Target *target){
gl->base.render = mac_gl__render;
gl->base.get_texture = mac_gl__get_texture;
gl->base.fill_texture = mac_gl__fill_texture;
gl->base.free_texture = mac_gl__free_texture;
// NOTE(yuval): Create the OpenGL view
NSView *content_view = [window contentView];

View File

@ -18,9 +18,6 @@ typedef mac_get_texture_sig(mac_get_texture_type);
#define mac_fill_texture_sig(name) b32 name(Mac_Renderer *renderer, Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void* data)
typedef mac_fill_texture_sig(mac_fill_texture_type);
#define mac_free_texture_sig(name) void name(Mac_Renderer *renderer, u32 texture)
typedef mac_free_texture_sig(mac_free_texture_type);
typedef i32 Mac_Renderer_Kind;
enum{
MacRenderer_OpenGL,
@ -34,7 +31,6 @@ struct Mac_Renderer{
mac_get_texture_type *get_texture;
mac_fill_texture_type *fill_texture;
mac_free_texture_type *free_texture;
};
////////////////////////////////

View File

@ -1,658 +0,0 @@
#define DX11_MAX_TEXTURE_COUNT 32
struct DX11Texture {
ID3D11Texture2D* pointer;
ID3D11ShaderResourceView* view;
};
struct GL_Program {
ID3D11VertexShader* vertex;
ID3D11InputLayout* layout;
ID3D11PixelShader* pixel;
b8 valid;
};
struct DX11 {
b8 initialized;
ID3D11Device1* device;
ID3D11DeviceContext1* context;
IDXGISwapChain1* swap_chain;
ID3D11SamplerState* sampler;
ID3D11RenderTargetView* render_target_view;
GL_Program gpu_program;
ID3D11Buffer* vertex_buffer;
ID3D11Buffer* constants_buffer;
// NOTE(simon, 28/02/24): To keep the API the same since the OpenGL texture handle are store in
// other places than the graphics parts (e.g. in the font Face struct), we create an array of
// textures, and use the indices as texture handles.
DX11Texture textures[ DX11_MAX_TEXTURE_COUNT + 1 ];
// NOTE(simon, 28/02/24): The first slot in the array should not be used so we can consider an
// index of 0 to be invalid. OpenGL should not return 0 for texture handle, so we sort of do
// the same.
u32 texture_count;
};
global DX11 g_dx11 = { };
// NOTE(simon, 28/02/24): Passing 0 for texid use the reserved texture in the array, and passing a
// resource view of zero unbinds the resource.
internal void
gl__bind_texture(Render_Target *t, i32 texid){
if (t->bound_texture != texid){
DX11Texture* texture = g_dx11.textures + texid;
g_dx11.context->PSSetShaderResources( 0, 1, &texture->view );
t->bound_texture = texid;
}
}
internal void
gl__bind_any_texture(Render_Target *t){
if (t->bound_texture == 0){
Assert(t->fallback_texture_id != 0);
DX11Texture* texture = g_dx11.textures + t->fallback_texture_id;
g_dx11.context->PSSetShaderResources( 0, 1, &texture->view );
t->bound_texture = t->fallback_texture_id;
}
}
internal u32
gl__get_texture(Vec3_i32 dim, Texture_Kind texture_kind){
u32 texid = 0;
if ( g_dx11.texture_count < ArrayCount( g_dx11.textures ) ) {
texid = g_dx11.texture_count;
g_dx11.texture_count++;
} else {
for ( u32 i = 1; i < g_dx11.texture_count; i++ ) {
DX11Texture* texture = g_dx11.textures + i;
if ( !texture->pointer && !texture->view ) {
texid = i;
break;
}
}
}
if ( texid ) {
DX11Texture* texture = g_dx11.textures + texid;
Assert( texture->pointer == 0 );
Assert( texture->view == 0 );
D3D11_TEXTURE2D_DESC texture_desc = { 0 };
texture_desc.Width = dim.x;
texture_desc.Height = dim.y;
texture_desc.MipLevels = 1;
texture_desc.ArraySize = dim.z;
texture_desc.Format = DXGI_FORMAT_A8_UNORM;
texture_desc.SampleDesc.Count = 1;
texture_desc.Usage = D3D11_USAGE_DEFAULT;
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texture_desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
// NOTE(simon, 28/02/24): I initialize the texture with zeros. In practice it doesn't seem
// to matter, but since the shader use a bilinear filter, the unitialized data in the
// texture could change the result of the filtering for texel at the edge of a character.
// I did some tests with the rectangle packer to have a border around character but got the
// exact same render, so It doesn't matter much.
D3D11_SUBRESOURCE_DATA* texture_data = push_array_zero( &win32vars.frame_arena, D3D11_SUBRESOURCE_DATA, dim.z );
u8* initial_data = push_array_zero( &win32vars.frame_arena, u8, dim.x * dim.y );
for ( i32 i = 0; i < dim.z; i++ ) {
texture_data[ i ].pSysMem = initial_data;
texture_data[ i ].SysMemPitch = dim.x;
}
HRESULT hr = g_dx11.device->CreateTexture2D( &texture_desc, texture_data, &texture->pointer );
pop_array( &win32vars.frame_arena, u8, dim.x * dim.y );
pop_array( &win32vars.frame_arena, D3D11_SUBRESOURCE_DATA, dim.z );
if ( SUCCEEDED( hr ) ) {
hr = g_dx11.device->CreateShaderResourceView( ( ID3D11Resource* ) texture->pointer, 0, &texture->view );
}
if ( FAILED( hr ) ) {
// NOTE(simon, 28/02/24): When we fail, we donc decrement the texture count, but the
// loop at the beginning of the function will reuse texture when
// texture_count == DX11_MAX_TEXTURE_COUNT.
texid = 0;
if ( texture->pointer ) {
texture->pointer->Release( );
texture->pointer = 0;
}
if ( texture->view ) {
texture->view->Release( );
texture->view = 0;
}
}
}
return(texid);
}
internal b32
gl__fill_texture(Texture_Kind texture_kind, u32 texid, Vec3_i32 p, Vec3_i32 dim, void *data){
// NOTE(simon, 28/02/24): The OpenGL version always returns false.
b32 result = false;
// NOTE(simon, 28/02/24): In the OpenGL version, if we pass zero as texture handle, the
// function works on the currently bound texture. In directx we need to get the texture pointer.
// We could retrieve that from Render_Target->bound_texture, but we don't have that as a
// parameter to this function and don't want to change the signature since it's used by the
// font rendering code and other platforms. Fortunately the only call that specified 0 for the
// texture handle was for the creation of the fallback texture in gl_render, and we can modify
// that call to pass the fallback texture handle.
Assert( texid != 0 );
if (dim.x > 0 && dim.y > 0 && dim.z > 0){
DX11Texture* texture = g_dx11.textures + texid;
D3D11_BOX box = { };
box.left = p.x;
box.right = p.x + dim.x;
box.top = p.y;
box.bottom = p.y + dim.y;
box.front = 0;
box.back = 1;
u32 sub_resource_index = D3D11CalcSubresource( 0 /* MipSlice */, p.z /* ArraySlice */, 1 /* MipLevels */ );
g_dx11.context->UpdateSubresource( texture->pointer, sub_resource_index, &box, data, dim.x, dim.x * dim.y );
}
return(result);
}
internal void gl__free_texture( u32 texid ) {
if ( texid ) {
DX11Texture* texture = g_dx11.textures + texid;
if ( texture->view ) {
texture->view->Release( );
texture->view = 0;
}
if ( texture->pointer ) {
texture->pointer->Release( );
texture->pointer = 0;
}
}
}
char *gl__vertex = R"foo(
// NOTE(simon, 28/02/24): The layout of this is (constants are store in 16 bytes vectors (4 floats))
// vector1: view_m._11, view_m._12, 0, 0
// vector2: view_m._21, view_m._22, view_t.x, view_t.y
cbuffer constants : register( b0 ) {
row_major float2x2 view_m;
float2 view_t;
}
struct input_t {
float2 vertex_p : POSITION;
float3 vertex_t : UVW;
float4 vertex_c : COLOR;
float vertex_ht : THICKNESS;
};
struct output_t {
float4 position : SV_POSITION;
float4 color : COLOR;
float3 uvw : UVW;
float2 xy : XY;
float2 adjusted_half_dim: HALF_DIM;
float half_thickness : THICKNESS;
};
output_t main(input_t input) {
output_t output;
output.position = float4( mul( view_m, ( input.vertex_p - view_t ) ), 0.0, 1.0 );
// NOTE(simon, 28/02/24): The input colors are BGRA, we need them as RGBA.
output.color = input.vertex_c.zyxw;
output.uvw = input.vertex_t;
output.xy = input.vertex_p;
output.half_thickness = input.vertex_ht;
float2 center = input.vertex_t.xy;
float2 half_dim = abs( input.vertex_p - center );
output.adjusted_half_dim = half_dim - input.vertex_t.zz + float2( 0.5, 0.5 );
return output;
}
)foo";
char *gl__fragment = R"foo(
struct input_t {
float4 position : SV_POSITION;
float4 color : COLOR;
float3 uvw : UVW;
float2 xy : XY;
float2 adjusted_half_dim: HALF_DIM;
float half_thickness : THICKNESS;
};
Texture2DArray alpha : register( t0 );
SamplerState alpha_sampler : register( s0 );
float rectangle_sd( float2 p, float2 b ) {
float2 d = abs( p ) - b;
return( length( max( d, float2( 0.0, 0.0 ) ) ) + min( max( d.x, d.y ), 0.0 ) );
}
float4 main( input_t input ) : SV_TARGET {
float has_thickness = step( 0.49, input.half_thickness );
float does_not_have_thickness = 1.0 - has_thickness;
float sample_value = alpha.Sample( alpha_sampler, input.uvw ).a;
sample_value *= does_not_have_thickness;
float2 center = input.uvw.xy;
float roundness = input.uvw.z;
float sd = rectangle_sd( input.xy - center, input.adjusted_half_dim );
sd = sd - roundness;
sd = abs( sd + input.half_thickness ) - input.half_thickness;
float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd);
shape_value *= has_thickness;
float4 result = float4( input.color.xyz, input.color.a * ( sample_value + shape_value ) );
return result;
}
)foo";
// NOTE(simon, 28/02/24): This function is not generic. It can compile any shader, but the vertex
// input layout is fixed. 4coder only has one vertex format and shader, so we could remove this
// function and move its content in the win32_gl_create_window. I removed the header parameter as
// it's not useful in directx.
internal GL_Program
gl__make_program( char* vertex, char* pixel ) {
GL_Program result = { };
u32 vertex_length = 0;
while ( vertex && vertex[ vertex_length ] != 0 ) {
vertex_length++;
}
u32 pixel_length = 0;
while ( pixel && pixel[ pixel_length ] != 0 ) {
pixel_length++;
}
ID3DBlob* vs_blob = 0;
ID3DBlob* vs_error_blob = 0;
ID3D11VertexShader* vertex_shader = 0;
ID3D11InputLayout* input_layout = 0;
ID3DBlob* ps_blob = 0;
ID3DBlob* ps_error_blob = 0;
ID3D11PixelShader* pixel_shader = 0;
do {
HRESULT hr = D3DCompile( vertex, vertex_length, 0, 0, 0, "main", "vs_5_0", 0, 0, &vs_blob, &vs_error_blob );
if ( FAILED( hr ) ) {
log_os( "Failed to compile vertex shader.\n" );
if ( vs_error_blob ) {
u8* error_message = ( u8* ) vs_error_blob->GetBufferPointer( );
u32 length = ( u32 ) vs_error_blob->GetBufferSize( );
log_os( "vertex shader error:\n%.*s\n", length, error_message );
}
break;
}
hr = g_dx11.device->CreateVertexShader( vs_blob->GetBufferPointer( ), vs_blob->GetBufferSize( ), 0, &vertex_shader );
if ( FAILED( hr ) ) {
log_os( "Failed to create a vertex shader.\n" );
break;
}
D3D11_INPUT_ELEMENT_DESC layout_desc[ 4 ] = { };
layout_desc[ 0 ].SemanticName = "POSITION";
layout_desc[ 0 ].Format = DXGI_FORMAT_R32G32_FLOAT;
layout_desc[ 0 ].AlignedByteOffset = 0;
layout_desc[ 0 ].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
layout_desc[ 1 ].SemanticName = "UVW";
layout_desc[ 1 ].Format = DXGI_FORMAT_R32G32B32_FLOAT;
layout_desc[ 1 ].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
layout_desc[ 1 ].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
layout_desc[ 2 ].SemanticName = "COLOR";
layout_desc[ 2 ].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
layout_desc[ 2 ].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
layout_desc[ 2 ].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
layout_desc[ 3 ].SemanticName = "THICKNESS";
layout_desc[ 3 ].Format = DXGI_FORMAT_R32_FLOAT;
layout_desc[ 3 ].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
layout_desc[ 3 ].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
hr = g_dx11.device->CreateInputLayout( layout_desc, ArrayCount( layout_desc ), vs_blob->GetBufferPointer( ), vs_blob->GetBufferSize( ), &input_layout );
if ( FAILED( hr ) ) {
log_os( "Failed to create input layout.\n" );
break;
}
hr = D3DCompile( pixel, pixel_length, 0, 0, 0, "main", "ps_5_0", 0, 0, &ps_blob, &ps_error_blob );
if ( FAILED( hr ) ) {
log_os( "Failed to compile pixel shader.\n" );
if ( ps_error_blob ) {
u8* error_message = ( u8* ) ps_error_blob->GetBufferPointer( );
u32 length = ( u32 ) ps_error_blob->GetBufferSize( );
log_os( "pixel shader error:\n%.*s\n", length, error_message );
}
break;
}
hr = g_dx11.device->CreatePixelShader( ps_blob->GetBufferPointer( ), ps_blob->GetBufferSize( ), 0, &pixel_shader );
if ( FAILED( hr ) ) {
log_os( "Failed to create a pixel shader.\n" );
break;
}
result.vertex = vertex_shader;
result.layout = input_layout;
result.pixel = pixel_shader;
result.valid = true;
} while ( 0 );
if ( vs_blob ) {
vs_blob->Release( );
vs_blob = 0;
}
if ( vs_error_blob ) {
vs_error_blob->Release( );
vs_error_blob = 0;
}
if ( ps_blob ) {
ps_blob->Release( );
ps_blob = 0;
}
if ( ps_error_blob ) {
ps_error_blob->Release( );
ps_error_blob = 0;
}
if ( !result.valid ) {
if ( vertex_shader ) {
vertex_shader->Release( );
vertex_shader = 0;
}
if ( input_layout ) {
input_layout->Release( );
input_layout = 0;
}
if ( pixel_shader ) {
pixel_shader->Release( );
pixel_shader = 0;
}
os_popup_error( "Error", "Shader compilation failed." );
}
return result;
}
internal void
gl_render(Render_Target *t){
Font_Set *font_set = (Font_Set*)t->font_set;
local_persist b32 first_call = true;
if (first_call){
// NOTE(simon, 28/02/24): Most of the code here has been moved in win32_gl_create_window
// because if that code fails we should exit the application directly.
first_call = false;
u32 stride = sizeof( Render_Vertex );
u32 offset = 0;
g_dx11.context->IASetVertexBuffers( 0, 1, &g_dx11.vertex_buffer, &stride, &offset );
g_dx11.context->IASetInputLayout( g_dx11.gpu_program.layout );
g_dx11.context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
g_dx11.context->VSSetShader( g_dx11.gpu_program.vertex, 0, 0 );
g_dx11.context->VSSetConstantBuffers( 0, 1, &g_dx11.constants_buffer );
g_dx11.context->PSSetShader( g_dx11.gpu_program.pixel, 0, 0 );
g_dx11.context->PSSetSamplers( 0, 1, &g_dx11.sampler );
{
t->fallback_texture_id = gl__get_texture(V3i32(2, 2, 1), TextureKind_Mono);
u8 white_block[] = { 0xFF, 0xFF, 0xFF, 0xFF, };
// NOTE(simon, 28/02/24): Passing the fallback texture, because we can't rely on the
// fact that gl__get_texture has bound the fallback texture.
gl__fill_texture(TextureKind_Mono, t->fallback_texture_id, V3i32(0, 0, 0), V3i32(2, 2, 1), white_block);
}
}
// NOTE(simon, 28/02/24): OMSetRenderTargets needs to be set each frame when using a FLIP swap
// chain.
g_dx11.context->OMSetRenderTargets( 1, &g_dx11.render_target_view, 0 );
i32 width = t->width;
i32 height = t->height;
// NOTE(simon, 28/02/24): Viewport (0, 0) is top left in directx. Important for viewport and
// scissor calls.
D3D11_VIEWPORT viewport = {
0, // TopLeftX
0, // TopLeftY
( float ) width, // Width
( float ) height, // Height
0, // MinDepth
1// MaxDepth
};
g_dx11.context->RSSetViewports( 1, &viewport );
D3D11_RECT scissor = {
0, // left
0, // top
width, // right
height // bottom
};
g_dx11.context->RSSetScissorRects( 1, &scissor );
float magenta[ 4 ] = { 1.0f, 0.0f, 1.0f, 1.0f };
g_dx11.context->ClearRenderTargetView( g_dx11.render_target_view, magenta );
// NOTE(simon, 28/02/24): The constants (uniforms) were set in the render loop in the OpenGL
// version. But since they don't vary between draw calls I moved the code before the render
// loop.
D3D11_MAPPED_SUBRESOURCE constants_map = { };
HRESULT hr = g_dx11.context->Map( ( ID3D11Resource* ) g_dx11.constants_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &constants_map );
// NOTE(simon, 28/02/24): The layout of the constants buffer was a bit confusing. This link
// explains a little about how data is laid out:
// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
// The article doesn't explain anything about matrices. What I found out while making this work
// is that each row or column (depending on if we use column or row major matrices) of a matrix
// needs to start on a new 16 bytes vector. For a 2 by 2 matrix, this means that there are two
// register elements at the end of the first vector that aren't used.
// Another thing is that the second vector only needs the first two elements for the matrix,
// so the two elements we want to put next can be in the same vector.
// NOTE(simon, 28/02/24): The code here could be shorter, but I prefer to make it clear what's
// happening.
f32 view_m[ 4 ] = {
2.0f / width, 0,
0, -2.0f / height
};
f32 view_t[ 2 ] = { width / 2.0f, height / 2.0f };
f32* vector_1 = ( f32* ) constants_map.pData;
f32* vector_2 = vector_1 + 4;
vector_1[ 0 ] = view_m[ 0 ];
vector_1[ 1 ] = view_m[ 1 ];
vector_1[ 2 ] = 0; // Padding
vector_1[ 3 ] = 0; // Padding
vector_2[ 0 ] = view_m[ 2 ];
vector_2[ 1 ] = view_m[ 3 ];
vector_2[ 2 ] = view_t[ 0 ];
vector_2[ 3 ] = view_t[ 1 ];
g_dx11.context->Unmap( ( ID3D11Resource* ) g_dx11.constants_buffer, 0 );
gl__bind_texture( t, 0 );
for (Render_Free_Texture *free_texture = t->free_texture_first;
free_texture != 0;
free_texture = free_texture->next){
gl__free_texture( free_texture->tex_id );
}
t->free_texture_first = 0;
t->free_texture_last = 0;
D3D11_BUFFER_DESC vertex_buffer_desc = { };
g_dx11.vertex_buffer->GetDesc( &vertex_buffer_desc );
for (Render_Group *group = t->group_first;
group != 0;
group = group->next){
Rect_i32 box = Ri32(group->clip_box);
// NOTE(FS): Ignore this group if we our scissor rectangle is not well defined
if ((rect_width(box) <= 0) || (rect_height(box) <= 0)) {
continue;
}
D3D11_RECT group_scissor = { };
group_scissor.left = box.x0;
group_scissor.right = box.x1;
group_scissor.top = box.y0;
group_scissor.bottom = box.y1;
g_dx11.context->RSSetScissorRects( 1, &group_scissor );
i32 vertex_count = group->vertex_list.vertex_count;
if (vertex_count > 0){
Face *face = font_set_face_from_id(font_set, group->face_id);
if (face != 0){
gl__bind_texture(t, face->texture);
}
else{
gl__bind_any_texture(t);
}
// NOTE(simon, 29/03/24): 4coder doesn't appear to clip character outside the screen
// horizontally. Even with line wrapping enabled, you can have cases where the line
// won't wrap, for example "{0,0,0,0,...}" with a lot of zero and no space will not
// wrap. The consequence of that is that we might send a lot of vertex data that's
// offscreen and the assumption about the vertex buffer size I made, can be wrong.
// So in this loop we release the previous vertex and create a new one when necessary.
u32 size_required = vertex_count * sizeof( Render_Vertex );
if ( size_required > vertex_buffer_desc.ByteWidth ) {
u32 new_size = vertex_buffer_desc.ByteWidth * 2;
while ( new_size < size_required ) {
new_size *= 2;
}
// NOTE(simon, 29/03/24): Create a new buffer and only release the previous one if
// the creation succeeded. If the creation fails, we skip this vertex group, which
// means the user will see an empty panel, but at least we won't stop rendering.
D3D11_BUFFER_DESC new_vertex_buffer_desc = vertex_buffer_desc;
new_vertex_buffer_desc.ByteWidth = new_size;
ID3D11Buffer* new_vertex_buffer = 0;
hr = g_dx11.device->CreateBuffer( &new_vertex_buffer_desc, 0, &new_vertex_buffer );
if ( FAILED( hr ) ) {
continue;
}
g_dx11.vertex_buffer->Release( );
g_dx11.vertex_buffer = new_vertex_buffer;
vertex_buffer_desc.ByteWidth = new_size;
u32 stride = sizeof( Render_Vertex );
u32 offset = 0;
g_dx11.context->IASetVertexBuffers( 0, 1, &g_dx11.vertex_buffer, &stride, &offset );
}
// NOTE(simon, 28/02/24): We fill the buffer, draw what we filled and then do the next
// group, which allows to always start drawing from vertex 0. Alternatively we could
// do a pass to fill the vertex buffer completly so we only map the vertex buffer once,
// and then a second pass that just execute the draw calls. It doesn't seems necessary
// since we have less than 10 draw call.
D3D11_MAPPED_SUBRESOURCE vertex_map = { };
hr = g_dx11.context->Map( ( ID3D11Resource* ) g_dx11.vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &vertex_map );
if ( FAILED( hr ) ) {
// NOTE(simon, 28/02/24): It's improbable that Map will fail, but if it does we
// just stop rendering, and we'll try on the next frame. We could just skip the
// group and try with the next (using 'continue' instead of 'break'), but Map would
// probably fail again. Waiting for the next frame "might" work. I don't really
// know. We could also just exit the application assuming we won't be able to
// render anything.
break;
}
u8* bytes = ( u8* ) vertex_map.pData;
for (Render_Vertex_Array_Node *node = group->vertex_list.first;
node != 0;
node = node->next){
i32 size = node->vertex_count*sizeof(*node->vertices);
memcpy( bytes, node->vertices, size );
bytes += size;
}
g_dx11.context->Unmap( ( ID3D11Resource* ) g_dx11.vertex_buffer, 0 );
g_dx11.context->Draw( vertex_count, 0 );
}
}
}

View File

@ -12,8 +12,6 @@
// #define FPS 144
// #define frame_useconds (1000000 / FPS)
// #define WIN32_DX11
#include <stdio.h>
#include "4coder_base_types.h"
@ -58,6 +56,7 @@
#define function static
#include "win32_utf8.h"
#include "win32_gl.h"
////////////////////////////////
@ -448,7 +447,6 @@ win32_post_clipboard(Arena *scratch, char *text, i32 len){
SetClipboardData(CF_TEXT, memory_handle);
}
CloseClipboard();
win32vars.clipboard_sequence = GetClipboardSequenceNumber();
}
}
@ -457,10 +455,14 @@ system_get_clipboard_sig(){
String_Const_u8 result = {};
DWORD new_number = GetClipboardSequenceNumber();
if (new_number != win32vars.clipboard_sequence){
result = win32_read_clipboard_contents(win32vars.tctx, arena);
if (result.str != 0){
win32vars.clipboard_sequence = new_number;
}
win32vars.clipboard_sequence = new_number;
for (i32 R = 0; R < 8; ++R){
result = win32_read_clipboard_contents(win32vars.tctx, arena);
if (result.str == 0){
break;
}
}
}
return(result);
}
@ -647,18 +649,18 @@ system_cli_end_update_sig(){
function void
os_popup_error(char *title, char *message){
MessageBoxA(0, message, title, MB_OK);
MessageBoxA(0, title, message, MB_OK);
ExitProcess(1);
}
#include "4ed_font_provider_freetype.h"
#include "4ed_font_provider_freetype.cpp"
#if defined( WIN32_DX11 )
#include "win32_dx11.cpp"
#else
#include "win32_opengl.cpp"
#endif
#include <GL/gl.h>
#include "opengl/4ed_opengl_defines.h"
#define GL_FUNC(N,R,P) typedef R (CALL_CONVENTION N##_Function)P; N##_Function *N = 0;
#include "opengl/4ed_opengl_funcs.h"
#include "opengl/4ed_opengl_render.cpp"
internal
graphics_get_texture_sig(){
@ -670,11 +672,6 @@ graphics_fill_texture_sig(){
return(gl__fill_texture(texture_kind, texture, p, dim, data));
}
internal
graphics_free_texture_sig(){
gl__free_texture(texid);
}
internal
font_make_face_sig(){
return(ft__font_make_face(arena, description, scale_factor));
@ -782,13 +779,13 @@ win32_keycode_init(void){
keycode_lookup_table[VK_NUMPAD8] = KeyCode_NumPad8;
keycode_lookup_table[VK_NUMPAD9] = KeyCode_NumPad9;
for (i32 i = 0; i < 30; i += 1){
keycode_lookup_table[0xDF + i] = KeyCode_Ex0 + i;
for (i32 i = 0xDF; i < 0xFF; i += 1){
keycode_lookup_table[i] = KeyCode_Ex0 + 1;
}
}
internal b32
keycode_physical_translation_is_wrong(u64 vk){
keycode_physical_translaion_is_wrong(u64 vk){
b32 result = false;
switch (vk){
case VK_UP: case VK_DOWN: case VK_LEFT: case VK_RIGHT:
@ -826,73 +823,6 @@ win32_resize(i32 width, i32 height){
if (width > 0 && height > 0){
target.width = width;
target.height = height;
#if defined( WIN32_DX11 )
HRESULT hr = S_OK;
ID3D11Texture2D* frame_buffer = 0;
do {
if ( g_dx11.initialized ) {
if ( g_dx11.render_target_view ) {
g_dx11.render_target_view->Release( );
g_dx11.render_target_view = 0;
}
hr = g_dx11.swap_chain->ResizeBuffers( 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0 );
if ( FAILED( hr ) ) {
log_os( "Failed to resize the swap chain buffers.\n" );
break;
}
hr = g_dx11.swap_chain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( void** ) &frame_buffer );
if ( FAILED( hr ) ) {
log_os( "Failled to get the swap chain back buffer.\n" );
break;
}
D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc = { 0 };
// NOTE(simon, 28/02/24): 4coder checks for sRGB support but never actually enables
// it in the OpenGL version (never calls glEnable( GL_FRAMEBUFFER_SRGB ) ).
// Note that enabling it would require to convert collors
// passed to the shader to linear (when using sRBG back buffer, the shader values
// must be linear values). This would be more problematic than just passing linear
// values as the blending wouldn't produce the same result as with sRGB off.
// render_target_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
render_target_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
hr = g_dx11.device->CreateRenderTargetView( ( ID3D11Resource* ) frame_buffer, &render_target_view_desc, &g_dx11.render_target_view );
if ( FAILED( hr ) ) {
log_os( "Failed to create a render target view.\n" );
break;
}
}
} while ( 0 );
if ( frame_buffer ) {
frame_buffer->Release( );
frame_buffer = 0;
}
if ( FAILED( hr ) ) {
if ( g_dx11.render_target_view ) {
g_dx11.render_target_view->Release( );
g_dx11.render_target_view = 0;
}
// NOTE(simon, 28/02/24): Failing here means no rendering possible, so we exit.
exit( 1 );
}
#endif
}
}
@ -971,10 +901,10 @@ internal void
date_time_from_win32_system_time(Date_Time *out, SYSTEMTIME *in){
out->year = in->wYear;
out->mon = (u8)(in->wMonth - 1);
out->day = (u8)(in->wDay - 1);
out->hour = (u8)(in->wHour);
out->min = (u8)(in->wMinute);
out->sec = (u8)(in->wSecond);
out->day = (u8)(in->wDay - 1);
out->hour = (u8)(in->wHour);
out->min = (u8)(in->wMinute);
out->sec = (u8)(in->wSecond);
out->msec = in->wMilliseconds;
}
@ -1227,7 +1157,7 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
u64 vk = wParam;
if (win32vars.key_mode == KeyMode_Physical &&
!keycode_physical_translation_is_wrong(vk)){
!keycode_physical_translaion_is_wrong(vk)){
UINT scan_code = ((lParam >> 16) & bitmask_8);
vk = MapVirtualKeyEx(scan_code, MAPVK_VSC_TO_VK_EX, win32vars.kl_universal);
}
@ -1261,7 +1191,7 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
}
}break;
}
b8 ctrl = (controls->r_ctrl || (controls->l_ctrl && !controls->r_alt));
b8 alt = (controls->l_alt || (controls->r_alt && !controls->l_ctrl));
if (win32vars.lctrl_lalt_is_altgr && controls->l_alt && controls->l_ctrl){
@ -1502,7 +1432,249 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
//-
internal b32
win32_wgl_good(Void_Func *f){
return(f != 0 &&
f != (Void_Func*)1 &&
f != (Void_Func*)2 &&
f != (Void_Func*)3 &&
f != (Void_Func*)-1);
}
typedef HGLRC (CALL_CONVENTION wglCreateContextAttribsARB_Function)(HDC,HGLRC,i32*);
typedef BOOL (CALL_CONVENTION wglChoosePixelFormatARB_Function)(HDC,i32*,f32*,u32,i32*,u32*);
typedef char* (CALL_CONVENTION wglGetExtensionsStringEXT_Function)();
typedef VOID (CALL_CONVENTION wglSwapIntervalEXT_Function)(i32);
global wglCreateContextAttribsARB_Function *wglCreateContextAttribsARB = 0;
global wglChoosePixelFormatARB_Function *wglChoosePixelFormatARB = 0;
global wglGetExtensionsStringEXT_Function *wglGetExtensionsStringEXT = 0;
global wglSwapIntervalEXT_Function *wglSwapIntervalEXT = 0;
internal b32
win32_gl_create_window(HWND *wnd_out, HGLRC *context_out, DWORD style, RECT rect){
HINSTANCE this_instance = GetModuleHandle(0);
local_persist b32 srgb_support = false;
local_persist b32 register_success = true;
local_persist b32 first_call = true;
if (first_call){
log_os(" GL bootstrapping...\n");
first_call = false;
// NOTE(allen): Create the GL bootstrap window
log_os(" registering bootstrap class...\n");
WNDCLASSW wglclass = {};
wglclass.lpfnWndProc = DefWindowProcW;
wglclass.hInstance = this_instance;
wglclass.lpszClassName = L"wgl-loader";
if (RegisterClassW(&wglclass) == 0){
register_success = false;
goto fail_register;
}
log_os(" creating bootstrap window...\n");
HWND wglwindow = CreateWindowW(wglclass.lpszClassName, L"", 0, 0, 0, 0, 0,
0, 0, this_instance, 0);
if (wglwindow == 0){
register_success = false;
goto fail_register;
}
// NOTE(allen): Create the GL bootstrap context
log_os(" setting bootstrap pixel format...\n");
HDC wgldc = GetDC(wglwindow);
PIXELFORMATDESCRIPTOR format = {};
format.nSize = sizeof(format);
format.nVersion = 1;
format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
format.iPixelType = PFD_TYPE_RGBA;
format.cColorBits = 32;
format.cAlphaBits = 8;
format.cDepthBits = 24;
format.iLayerType = PFD_MAIN_PLANE;
i32 suggested_format_index = ChoosePixelFormat(wgldc, &format);
if (!SetPixelFormat(wgldc, suggested_format_index, &format)){
register_success = false;
goto fail_register;
}
log_os(" creating bootstrap GL context...\n");
HGLRC wglcontext = wglCreateContext(wgldc);
if (wglcontext == 0){
register_success = false;
goto fail_register;
}
log_os(" making bootstrap GL context current...\n");
if (!wglMakeCurrent(wgldc, wglcontext)){
register_success = false;
goto fail_register;
}
// NOTE(allen): Load wgl extensions
log_os(" loading wgl extensions...\n");
#define LoadWGL(f,l) Stmnt((f) = (f##_Function*)wglGetProcAddress(#f); \
(l) = (l) && win32_wgl_good((Void_Func*)(f));)
b32 load_success = true;
LoadWGL(wglCreateContextAttribsARB, load_success);
LoadWGL(wglChoosePixelFormatARB, load_success);
LoadWGL(wglGetExtensionsStringEXT, load_success);
if (!load_success){
register_success = false;
goto fail_register;
}
log_os(" checking wgl extensions...\n");
char *extensions_c = wglGetExtensionsStringEXT();
String_Const_u8 extensions = SCu8((u8*)extensions_c);
{
String_Const_u8 s = string_skip_whitespace(extensions);
for (;s.size > 0;){
u64 end = string_find_first_whitespace(s);
String_Const_u8 m = string_prefix(s, end);
if (string_match(m, string_u8_litexpr("WGL_EXT_framebuffer_sRGB")) ||
string_match(m, string_u8_litexpr("WGL_ARB_framebuffer_sRGB"))){
srgb_support = true;
}
else if (string_match(m, string_u8_litexpr("WGL_EXT_swap_interval"))){
b32 wgl_swap_interval_ext = true;
LoadWGL(wglSwapIntervalEXT, wgl_swap_interval_ext);
if (!wgl_swap_interval_ext){
wglSwapIntervalEXT = 0;
}
}
s = string_skip_whitespace(string_skip(s, end));
}
}
// NOTE(allen): Load gl functions
log_os(" loading core GL functions...\n");
#define GL_FUNC(f,R,P) LoadWGL(f,load_success);
#include "opengl/4ed_opengl_funcs.h"
if (!load_success){
register_success = false;
goto fail_register;
}
// NOTE(allen): Cleanup the GL bootstrap resources
log_os(" cleaning up boostrap resources...\n");
ReleaseDC(wglwindow, wgldc);
DestroyWindow(wglwindow);
wglDeleteContext(wglcontext);
// NOTE(allen): Register the graphics window class
log_os(" registering graphics class...\n");
WNDCLASSW wndclass = {};
wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wndclass.lpfnWndProc = win32_proc;
wndclass.hIcon = LoadIconW(GetModuleHandle(0), L"main");
wndclass.hInstance = this_instance;
wndclass.lpszClassName = L"GRAPHICS-WINDOW-NAME";
if (RegisterClassW(&wndclass) == 0){
register_success = false;
goto fail_register;
}
}
fail_register:;
b32 result = false;
if (register_success){
// NOTE(allen): Create the graphics window
log_os(" creating graphics window...\n");
HWND wnd = CreateWindowExW(0, L"GRAPHICS-WINDOW-NAME", L"GRAPHICS", style,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top,
0, 0, this_instance, 0);
*wnd_out = 0;
*context_out = 0;
if (wnd != 0){
log_os(" setting graphics pixel format...\n");
HDC dc = GetDC(wnd);
PIXELFORMATDESCRIPTOR format = {};
i32 pixel_attrib_list[] = {
/* 0*/WGL_DRAW_TO_WINDOW_ARB, TRUE,
/* 2*/WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
/* 4*/WGL_SUPPORT_OPENGL_ARB, TRUE,
/* 6*/WGL_DOUBLE_BUFFER_ARB, false,
/* 8*/WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
/*10*/WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE,
/*12*/0,
};
if (!srgb_support){
pixel_attrib_list[10] = 0;
}
i32 suggested_format_index = 0;
u32 ignore = 0;
if (!wglChoosePixelFormatARB(dc, pixel_attrib_list, 0, 1, &suggested_format_index, &ignore)){
goto fail_window_init;
}
DescribePixelFormat(dc, suggested_format_index, sizeof(format), &format);
if (!SetPixelFormat(dc, suggested_format_index, &format)){
goto fail_window_init;
}
log_os(" setting graphics attributes...\n");
i32 context_attrib_list[] = {
/*0*/WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
/*2*/WGL_CONTEXT_MINOR_VERSION_ARB, 2,
/*4*/WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
#if GL_DEBUG_MODE
|WGL_CONTEXT_DEBUG_BIT_ARB
#endif
,
/*6*/WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
/*8*/0
};
log_os(" creating graphics GL context...\n");
HGLRC context = wglCreateContextAttribsARB(dc, 0, context_attrib_list);
if (context == 0){
goto fail_window_init;
}
log_os(" making graphics GL context current...\n");
wglMakeCurrent(dc, context);
if (wglSwapIntervalEXT != 0){
log_os(" setting swap interval...\n");
wglSwapIntervalEXT(1);
}
*wnd_out = wnd;
*context_out = context;
result = true;
if (false){
fail_window_init:;
DWORD error = GetLastError();
ReleaseDC(wnd, dc);
DestroyWindow(wnd);
SetLastError(error);
}
}
}
return(result);
}
//-
@ -1746,21 +1918,15 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
window_style |= WS_MAXIMIZE;
}
log_os(" windowed dimensions: %d, %d\n"
" initially maximized: %d\n",
" initially maximized: %d",
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
((window_style & WS_MAXIMIZE) != 0));
#if defined( WIN32_DX11 )
if( !win32_gl_create_window( &win32vars.window_handle, window_style, window_rect ) ) {
exit(1);
}
#else
HGLRC window_opengl_context = 0;
if (!win32_gl_create_window(&win32vars.window_handle, &window_opengl_context, window_style, window_rect)){
exit(1);
}
#endif
log_os(" window created successfully\n");
@ -1861,7 +2027,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
// NOTE(allen): while we're doing this (and possibly sleeping)
// we can let async processes get there time in.
system_release_global_frame_mutex(win32vars.tctx);
system_release_global_frame_mutex(win32vars.tctx);
b32 get_more_messages = true;
do{
@ -1939,7 +2105,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
}
}while (get_more_messages);
system_acquire_global_frame_mutex(win32vars.tctx);
system_acquire_global_frame_mutex(win32vars.tctx);
}
// NOTE(allen): Mouse Out of Window Detection
@ -2044,15 +2210,10 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
win32vars.lctrl_lalt_is_altgr = (b8)result.lctrl_lalt_is_altgr;
// NOTE(allen): render
#if defined( WIN32_DX11 )
gl_render(&target);
g_dx11.swap_chain->Present( 1, 0 );
#else
HDC hdc = GetDC(win32vars.window_handle);
gl_render(&target);
SwapBuffers(hdc);
ReleaseDC(win32vars.window_handle, hdc);
#endif
// NOTE(allen): toggle full screen
if (win32vars.do_toggle){
@ -2069,7 +2230,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
}
// NOTE(allen): sleep a bit to cool off :)
system_release_global_frame_mutex(win32vars.tctx);
system_release_global_frame_mutex(win32vars.tctx);
u64 timer_end = system_now_time();
u64 end_target = timer_start + frame_useconds;
@ -2088,10 +2249,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
win32vars.first = false;
}
#if defined( WIN32_DX11 ) && !SHIP_MODE
win32_gl_cleanup( );
#endif
return(0);
}

View File

@ -1,544 +0,0 @@
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
#include <initguid.h>
#include <d3d11_1.h>
#include <dxgi1_3.h>
#include <d3dcompiler.h>
#if !SHIP_MODE
#include <dxgidebug.h>
IDXGIDebug1* dxgi_debug;
#endif
#include "4ed_dx11_render.cpp"
internal LRESULT CALL_CONVENTION
win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
internal b32
win32_gl_create_window(HWND *wnd_out, DWORD style, RECT rect){
local_persist b32 srgb_support = false;
local_persist b32 first_call = true;
b32 result = false;
*wnd_out = 0;
Assert( g_dx11.initialized == 0 );
Assert( g_dx11.device == 0 );
Assert( g_dx11.context == 0 );
Assert( g_dx11.swap_chain == 0 );
Assert( g_dx11.sampler == 0 );
Assert( g_dx11.render_target_view == 0 );
Assert( g_dx11.gpu_program.vertex == 0 );
Assert( g_dx11.gpu_program.layout == 0 );
Assert( g_dx11.gpu_program.pixel == 0 );
Assert( g_dx11.gpu_program.valid == 0 );
Assert( g_dx11.vertex_buffer == 0 );
Assert( g_dx11.constants_buffer == 0 );
Assert( g_dx11.texture_count == 0 );
g_dx11 = { };
HINSTANCE this_instance = GetModuleHandle(0);
HWND wnd = 0;
ID3D11Device* base_device = 0;
ID3D11DeviceContext* base_device_context = 0;
IDXGIDevice1* dxgi_device = 0;
IDXGIAdapter* dxgi_adapter = 0;
IDXGIFactory2* dxgi_factory = 0;
ID3D11BlendState* blend_state = 0;
ID3D11RasterizerState1* rasterizer_state = 0;
do {
// NOTE(simon, 28/02/24): There is nothing in the code suggesting that this function could
// be called several time. If it is called several time, we would need to make sure that
// we cleaned up previous dx11 resources. The reason this function could be called twice
// would be if it failed previously, and in that case we clean up everything before
// exiting the function so we should be good. Still we assume it's only ever call once.
Assert( first_call );
if (first_call){
first_call = false;
log_os( " Registering graphics class...\n" );
WNDCLASSW wndclass = {};
wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wndclass.lpfnWndProc = win32_proc;
wndclass.hIcon = LoadIconW(GetModuleHandle(0), L"main");
wndclass.hInstance = this_instance;
wndclass.lpszClassName = L"GRAPHICS-WINDOW-NAME";
if (RegisterClassW(&wndclass) == 0){
log_os(" Failed.\n");
break;
}
}
log_os( " Creating graphics window...\n" );
wnd = CreateWindowExW(0, L"GRAPHICS-WINDOW-NAME", L"GRAPHICS", style,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top,
0, 0, this_instance, 0);
if (wnd == 0) {
log_os( " Failed.\n" );
break;
}
log_os( " Creating a d3d11 hardware device and context...\n" );
// NOTE(simon, 28/02/24): We are creating a directx 11.1 device and context (supported
// since windows 8).
D3D_FEATURE_LEVEL feature_levels[ ] = { D3D_FEATURE_LEVEL_11_1 };
u32 device_flags = 0;
// device_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if !SHIP_MODE
device_flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
HRESULT hr = D3D11CreateDevice( 0, D3D_DRIVER_TYPE_HARDWARE, 0, device_flags, feature_levels, ArrayCount( feature_levels ), D3D11_SDK_VERSION, &base_device, 0, &base_device_context );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
log_os( " Creating a d3d11 software (WARP) device and context...\n" );
// NOTE(simon, 28/02/24): Try creating a high performance software device as a fallback.
hr = D3D11CreateDevice( 0, D3D_DRIVER_TYPE_WARP, 0, device_flags, feature_levels, ArrayCount( feature_levels ), D3D11_SDK_VERSION, &base_device, 0, &base_device_context );
}
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
log_os( " Creating a ID3D11Device1...\n" );
hr = base_device->QueryInterface( __uuidof( ID3D11Device1 ), ( void** ) &g_dx11.device );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
log_os( " Creating a ID3D11DeviceContext1...\n" );
hr = base_device_context->QueryInterface( __uuidof( ID3D11DeviceContext1 ), ( void** ) &g_dx11.context );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
ID3D11Device1* device = g_dx11.device;
ID3D11DeviceContext1* context = g_dx11.context;
#if !SHIP_MODE
log_os( " Getting ID3D11InfoQueue. This is not important if you're not debugging graphics...\n" );
ID3D11InfoQueue* info;
hr = device->QueryInterface( __uuidof( ID3D11InfoQueue ), ( void** ) &info );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
} else {
info->SetBreakOnSeverity( D3D11_MESSAGE_SEVERITY_CORRUPTION, TRUE );
info->SetBreakOnSeverity( D3D11_MESSAGE_SEVERITY_ERROR, TRUE );
info->Release( );
}
log_os( " Getting IDXGIDebug1. This is not important if you're not debugging graphics...\n" );
hr = DXGIGetDebugInterface1( 0, __uuidof( IDXGIDebug1 ), ( void** ) &dxgi_debug );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
}
#endif
// NOTE(simon, 28/02/24): sRGB should be supported by any hardware now, but there was a
// check so I added one. The OpenGL version never enables sRGB.
DXGI_FORMAT back_buffer_format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
UINT format_support = 0;
if ( SUCCEEDED( device->CheckFormatSupport( back_buffer_format, &format_support ) ) ) {
u32 required = D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_DISPLAY;
srgb_support = ( ( format_support & required ) == required );
}
if ( !srgb_support ) {
log_os( " sRBG back buffer not supported.\n" );
back_buffer_format = DXGI_FORMAT_R8G8B8A8_UNORM;
} else {
log_os( " sRBG back buffer supported.\n" );
}
log_os( " Getting a IDXGIFactory2...\n" );
log_os( " Qurey for the IDXGIDevice1...\n" );
hr = device->QueryInterface( __uuidof( IDXGIDevice1 ), ( void** ) &dxgi_device );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
log_os( " Getting the IDXGIAdapter...\n" );
dxgi_device->GetAdapter( &dxgi_adapter );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
log_os( " Getting the IDXGIFactor2...\n" );
dxgi_adapter->GetParent( __uuidof( IDXGIFactory2 ), ( void** ) &dxgi_factory );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = { };
// NOTE(simon, 28/02/24): Can't request sRGB format here when using FLIP_* swap chain. It's
// requested when creating the render target view.
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.BufferCount = 2;
swap_chain_desc.Scaling = DXGI_SCALING_NONE;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
log_os( " Creating a IDXGISwapChain1...\n" );
hr = dxgi_factory->CreateSwapChainForHwnd( device, wnd, &swap_chain_desc, 0, 0, &g_dx11.swap_chain );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
log_os( " Prevent DXGI handling ALT + ENTER...\n" );
hr = dxgi_factory->MakeWindowAssociation( wnd, DXGI_MWA_NO_ALT_ENTER );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
}
// NOTE(simon, 28/02/24): We setup alpha blending here as it's always on in 4coder.
D3D11_BLEND_DESC blend_state_desc = { };
blend_state_desc.RenderTarget[ 0 ].BlendEnable = TRUE;
blend_state_desc.RenderTarget[ 0 ].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blend_state_desc.RenderTarget[ 0 ].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blend_state_desc.RenderTarget[ 0 ].BlendOp = D3D11_BLEND_OP_ADD;
blend_state_desc.RenderTarget[ 0 ].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blend_state_desc.RenderTarget[ 0 ].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blend_state_desc.RenderTarget[ 0 ].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blend_state_desc.RenderTarget[ 0 ].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
log_os( " Creating a blend state...\n" );
hr = device->CreateBlendState( &blend_state_desc, &blend_state );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
context->OMSetBlendState( blend_state, 0, 0xffffffff );
// NOTE(simon, 28/02/24): Enable scissor and disable backface culling.
D3D11_RASTERIZER_DESC1 rasterizer_desc = { };
rasterizer_desc.FillMode = D3D11_FILL_SOLID;
rasterizer_desc.CullMode = D3D11_CULL_NONE;
rasterizer_desc.DepthClipEnable = TRUE;
rasterizer_desc.ScissorEnable = TRUE;
log_os( " Creating a rasterizer state...\n" );
hr = device->CreateRasterizerState1( &rasterizer_desc, &rasterizer_state );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
context->RSSetState( rasterizer_state );
// NOTE(simon, 28/02/24): Not setting depth stencil as 4coder doesn't use it.
// NOTE(simon, 28/02/24): Swap interval is a parameter of swap_chain->present.
D3D11_SAMPLER_DESC linear_desc = { };
linear_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
linear_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
linear_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
linear_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
linear_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
linear_desc.MinLOD = 0;
linear_desc.MaxLOD = D3D11_FLOAT32_MAX;
log_os( " Creating a sampler state...\n" );
hr = device->CreateSamplerState( &linear_desc, &g_dx11.sampler );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
// NOTE(simon, 28/02/24): We create the vertex buffer, constants buffers and shader here
// because if we can't create them we won't be able to render anything and so we should
// just exit the program.
D3D11_BUFFER_DESC vertex_buffer_desc = { };
// NOTE(simon, 28/02/24): Reserving 400K vertices which is about 11 megabytes and would
// allow 100K characters. On a 1080p monitor, with 4 by 10 pixels characters we would need
// (1920/4)*(1080/10) = 51840 characters to fill the screen.
vertex_buffer_desc.ByteWidth = 400000 * sizeof( Render_Vertex );
vertex_buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
vertex_buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertex_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
log_os( " Creating a vertex buffer...\n" );
hr = device->CreateBuffer( &vertex_buffer_desc, 0, &g_dx11.vertex_buffer );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
D3D11_BUFFER_DESC constants_buffer_desc = { };
// NOTE(simon, 28/02/24): constants buffer size needs to be a multiple of 16.
// NOTE(simon, 28/02/24): The layout is explained where we set the values in the buffer in
// gl_render.
constants_buffer_desc.ByteWidth = 32;
constants_buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
constants_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constants_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
log_os( " Creating a constants buffer...\n" );
hr = device->CreateBuffer( &constants_buffer_desc, 0, &g_dx11.constants_buffer );
if ( FAILED( hr ) ) {
log_os( " Failed.\n" );
break;
}
g_dx11.gpu_program = gl__make_program( gl__vertex, gl__fragment );
if ( !g_dx11.gpu_program.valid ) {
break;
}
*wnd_out = wnd;
// NOTE(simon, 28/02/24): Reserve the first texture slot as a invalid/unbind texture.
g_dx11.texture_count = 1;
g_dx11.initialized = true;
result = true;
} while ( 0 );
if ( !result ) {
if ( wnd ) {
DestroyWindow( wnd );
( *wnd_out ) = 0;
}
if ( g_dx11.context ) {
g_dx11.context->OMSetBlendState( 0, 0, 0xffffffff );
g_dx11.context->RSSetState( 0 );
}
if ( g_dx11.constants_buffer ) {
g_dx11.constants_buffer->Release( );
g_dx11.constants_buffer = 0;
}
if ( g_dx11.vertex_buffer ) {
g_dx11.vertex_buffer->Release( );
g_dx11.vertex_buffer = 0;
}
if ( g_dx11.gpu_program.valid ) {
if ( g_dx11.gpu_program.vertex ) {
g_dx11.gpu_program.vertex->Release( );
g_dx11.gpu_program.vertex = 0;
}
if ( g_dx11.gpu_program.layout ) {
g_dx11.gpu_program.layout->Release( );
g_dx11.gpu_program.layout = 0;
}
if ( g_dx11.gpu_program.pixel ) {
g_dx11.gpu_program.pixel->Release( );
g_dx11.gpu_program.pixel = 0;
}
}
// NOTE(simon, 28/02/24): No render target view at this point as it's created in the
// WM_SIZE message.
if ( g_dx11.sampler ) {
g_dx11.sampler->Release( );
g_dx11.sampler = 0;
}
if ( g_dx11.swap_chain ) {
g_dx11.swap_chain->Release( );
g_dx11.swap_chain = 0;
}
if ( g_dx11.context ) {
g_dx11.context->Release( );
g_dx11.context = 0;
}
if ( g_dx11.device ) {
g_dx11.device->Release( );
g_dx11.device = 0;
}
g_dx11.initialized = false;
#if SHIP_MODE
os_popup_error( "Error", "Window creation failed.");
#endif
}
if( base_device ) {
base_device->Release( );
base_device = 0;
}
if ( base_device_context ) {
base_device_context->Release( );
base_device_context = 0;
}
if ( dxgi_device ) {
dxgi_device->Release( );
dxgi_device = 0;
}
if ( dxgi_adapter ) {
dxgi_adapter->Release( );
dxgi_adapter = 0;
}
if ( dxgi_factory ) {
dxgi_factory->Release( );
dxgi_factory = 0;
}
if ( blend_state ) {
blend_state->Release( );
blend_state = 0;
}
if ( rasterizer_state ) {
rasterizer_state->Release( );
rasterizer_state = 0;
}
return(result);
}
#if !SHIP_MODE
// NOTE(simon, 28/02/24): Only call this when working on 4coder, to make sure we don't do something
// stupid. In SHIP_MODE we let the os clean up resources.
internal void
win32_gl_cleanup( void ) {
if ( dxgi_debug && g_dx11.initialized ) {
OutputDebugString( L"win32_gl_cleanup start report...\n" );
dxgi_debug->ReportLiveObjects( DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL );
g_dx11.initialized = false;
if ( g_dx11.context ) {
g_dx11.context->OMSetBlendState( 0, 0, 0xffffffff );
g_dx11.context->RSSetState( 0 );
}
for ( u32 i = 1; i < g_dx11.texture_count; i++ ) {
DX11Texture* texture = g_dx11.textures + i;
if ( texture->view ) {
texture->view->Release( );
texture->view = 0;
}
if ( texture->pointer ) {
texture->pointer->Release( );
texture->pointer = 0;
}
}
g_dx11.texture_count = 0;
if ( g_dx11.constants_buffer ) {
g_dx11.constants_buffer->Release( );
g_dx11.constants_buffer = 0;
}
if ( g_dx11.vertex_buffer ) {
g_dx11.vertex_buffer->Release( );
g_dx11.vertex_buffer = 0;
}
if ( g_dx11.gpu_program.valid ) {
if ( g_dx11.gpu_program.vertex ) {
g_dx11.gpu_program.vertex->Release( );
g_dx11.gpu_program.vertex = 0;
}
if ( g_dx11.gpu_program.layout ) {
g_dx11.gpu_program.layout->Release( );
g_dx11.gpu_program.layout = 0;
}
if ( g_dx11.gpu_program.pixel ) {
g_dx11.gpu_program.pixel->Release( );
g_dx11.gpu_program.pixel = 0;
}
}
if ( g_dx11.render_target_view ) {
g_dx11.render_target_view->Release( );
g_dx11.render_target_view = 0;
}
if ( g_dx11.sampler ) {
g_dx11.sampler->Release( );
g_dx11.sampler = 0;
}
if ( g_dx11.swap_chain ) {
g_dx11.swap_chain->Release( );
g_dx11.swap_chain = 0;
}
if ( g_dx11.context ) {
g_dx11.context->Release( );
g_dx11.context = 0;
}
if ( g_dx11.device ) {
g_dx11.device->Release( );
g_dx11.device = 0;
}
OutputDebugString( L"win32_gl_cleanup end report (nothing printed after this line means everything is OK)...\n" );
dxgi_debug->ReportLiveObjects( DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL );
}
}
#endif

View File

@ -1,257 +0,0 @@
#pragma comment(lib, "OpenGL32.lib")
#include "win32_gl.h"
#include <GL/gl.h>
#include "opengl/4ed_opengl_defines.h"
#define GL_FUNC(N,R,P) typedef R (CALL_CONVENTION N##_Function)P; N##_Function *N = 0;
#include "opengl/4ed_opengl_funcs.h"
#include "opengl/4ed_opengl_render.cpp"
internal b32
win32_wgl_good(Void_Func *f){
return(f != 0 &&
f != (Void_Func*)1 &&
f != (Void_Func*)2 &&
f != (Void_Func*)3 &&
f != (Void_Func*)-1);
}
typedef HGLRC (CALL_CONVENTION wglCreateContextAttribsARB_Function)(HDC,HGLRC,i32*);
typedef BOOL (CALL_CONVENTION wglChoosePixelFormatARB_Function)(HDC,i32*,f32*,u32,i32*,u32*);
typedef char* (CALL_CONVENTION wglGetExtensionsStringEXT_Function)();
typedef VOID (CALL_CONVENTION wglSwapIntervalEXT_Function)(i32);
global wglCreateContextAttribsARB_Function *wglCreateContextAttribsARB = 0;
global wglChoosePixelFormatARB_Function *wglChoosePixelFormatARB = 0;
global wglGetExtensionsStringEXT_Function *wglGetExtensionsStringEXT = 0;
global wglSwapIntervalEXT_Function *wglSwapIntervalEXT = 0;
internal LRESULT CALL_CONVENTION
win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
internal b32
win32_gl_create_window(HWND *wnd_out, HGLRC *context_out, DWORD style, RECT rect){
HINSTANCE this_instance = GetModuleHandle(0);
local_persist b32 srgb_support = false;
local_persist b32 register_success = true;
local_persist b32 first_call = true;
if (first_call){
log_os(" GL bootstrapping...\n");
first_call = false;
// NOTE(allen): Create the GL bootstrap window
log_os(" registering bootstrap class...\n");
WNDCLASSW wglclass = {};
wglclass.lpfnWndProc = DefWindowProcW;
wglclass.hInstance = this_instance;
wglclass.lpszClassName = L"wgl-loader";
if (RegisterClassW(&wglclass) == 0){
register_success = false;
goto fail_register;
}
log_os(" creating bootstrap window...\n");
HWND wglwindow = CreateWindowW(wglclass.lpszClassName, L"", 0, 0, 0, 0, 0,
0, 0, this_instance, 0);
if (wglwindow == 0){
register_success = false;
goto fail_register;
}
// NOTE(allen): Create the GL bootstrap context
log_os(" setting bootstrap pixel format...\n");
HDC wgldc = GetDC(wglwindow);
PIXELFORMATDESCRIPTOR format = {};
format.nSize = sizeof(format);
format.nVersion = 1;
format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
format.iPixelType = PFD_TYPE_RGBA;
format.cColorBits = 32;
format.cAlphaBits = 8;
format.cDepthBits = 24;
format.iLayerType = PFD_MAIN_PLANE;
i32 suggested_format_index = ChoosePixelFormat(wgldc, &format);
if (!SetPixelFormat(wgldc, suggested_format_index, &format)){
register_success = false;
goto fail_register;
}
log_os(" creating bootstrap GL context...\n");
HGLRC wglcontext = wglCreateContext(wgldc);
if (wglcontext == 0){
register_success = false;
goto fail_register;
}
log_os(" making bootstrap GL context current...\n");
if (!wglMakeCurrent(wgldc, wglcontext)){
register_success = false;
goto fail_register;
}
// NOTE(allen): Load wgl extensions
log_os(" loading wgl extensions...\n");
#define LoadWGL(f,l) Stmnt((f) = (f##_Function*)wglGetProcAddress(#f); \
(l) = (l) && win32_wgl_good((Void_Func*)(f));)
b32 load_success = true;
LoadWGL(wglCreateContextAttribsARB, load_success);
LoadWGL(wglChoosePixelFormatARB, load_success);
LoadWGL(wglGetExtensionsStringEXT, load_success);
if (!load_success){
register_success = false;
goto fail_register;
}
log_os(" checking wgl extensions...\n");
char *extensions_c = wglGetExtensionsStringEXT();
String_Const_u8 extensions = SCu8((u8*)extensions_c);
{
String_Const_u8 s = string_skip_whitespace(extensions);
for (;s.size > 0;){
u64 end = string_find_first_whitespace(s);
String_Const_u8 m = string_prefix(s, end);
if (string_match(m, string_u8_litexpr("WGL_EXT_framebuffer_sRGB")) ||
string_match(m, string_u8_litexpr("WGL_ARB_framebuffer_sRGB"))){
srgb_support = true;
}
else if (string_match(m, string_u8_litexpr("WGL_EXT_swap_interval"))){
b32 wgl_swap_interval_ext = true;
LoadWGL(wglSwapIntervalEXT, wgl_swap_interval_ext);
if (!wgl_swap_interval_ext){
wglSwapIntervalEXT = 0;
}
}
s = string_skip_whitespace(string_skip(s, end));
}
}
// NOTE(allen): Load gl functions
log_os(" loading core GL functions...\n");
#define GL_FUNC(f,R,P) LoadWGL(f,load_success);
#include "opengl/4ed_opengl_funcs.h"
if (!load_success){
register_success = false;
goto fail_register;
}
// NOTE(allen): Cleanup the GL bootstrap resources
log_os(" cleaning up boostrap resources...\n");
ReleaseDC(wglwindow, wgldc);
DestroyWindow(wglwindow);
wglDeleteContext(wglcontext);
// NOTE(allen): Register the graphics window class
log_os(" registering graphics class...\n");
WNDCLASSW wndclass = {};
wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wndclass.lpfnWndProc = win32_proc;
wndclass.hIcon = LoadIconW(GetModuleHandle(0), L"main");
wndclass.hInstance = this_instance;
wndclass.lpszClassName = L"GRAPHICS-WINDOW-NAME";
if (RegisterClassW(&wndclass) == 0){
register_success = false;
goto fail_register;
}
}
fail_register:;
b32 result = false;
if (register_success){
// NOTE(allen): Create the graphics window
log_os(" creating graphics window...\n");
HWND wnd = CreateWindowExW(0, L"GRAPHICS-WINDOW-NAME", L"GRAPHICS", style,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top,
0, 0, this_instance, 0);
*wnd_out = 0;
*context_out = 0;
if (wnd != 0){
log_os(" setting graphics pixel format...\n");
HDC dc = GetDC(wnd);
PIXELFORMATDESCRIPTOR format = {};
i32 pixel_attrib_list[] = {
/* 0*/WGL_DRAW_TO_WINDOW_ARB, TRUE,
/* 2*/WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
/* 4*/WGL_SUPPORT_OPENGL_ARB, TRUE,
/* 6*/WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
/* 8*/WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
/*10*/WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE,
/*12*/0,
};
if (!srgb_support){
pixel_attrib_list[10] = 0;
}
i32 suggested_format_index = 0;
u32 ignore = 0;
if (!wglChoosePixelFormatARB(dc, pixel_attrib_list, 0, 1, &suggested_format_index, &ignore)){
goto fail_window_init;
}
DescribePixelFormat(dc, suggested_format_index, sizeof(format), &format);
if (!SetPixelFormat(dc, suggested_format_index, &format)){
goto fail_window_init;
}
log_os(" setting graphics attributes...\n");
i32 context_attrib_list[] = {
/*0*/WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
/*2*/WGL_CONTEXT_MINOR_VERSION_ARB, 2,
/*4*/WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
#if GL_DEBUG_MODE
|WGL_CONTEXT_DEBUG_BIT_ARB
#endif
,
/*6*/WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
/*8*/0
};
log_os(" creating graphics GL context...\n");
HGLRC context = wglCreateContextAttribsARB(dc, 0, context_attrib_list);
if (context == 0){
goto fail_window_init;
}
log_os(" making graphics GL context current...\n");
wglMakeCurrent(dc, context);
if (wglSwapIntervalEXT != 0){
log_os(" setting swap interval...\n");
wglSwapIntervalEXT(1);
}
*wnd_out = wnd;
*context_out = context;
result = true;
if (false){
fail_window_init:;
DWORD error = GetLastError();
ReleaseDC(wnd, dc);
DestroyWindow(wnd);
SetLastError(error);
}
}
}
return(result);
}