Compare commits
29 Commits
7359649465
...
0ee8e3904a
Author | SHA1 | Date |
---|---|---|
|
0ee8e3904a | |
|
27b4626907 | |
|
9e58435637 | |
|
6469fe5a0f | |
|
0f5d46f5a4 | |
|
87d0eb9cf3 | |
|
b834dbb451 | |
|
b2bdc515ec | |
|
9b927bd410 | |
|
bd7dac90ac | |
|
0e2b8d0df8 | |
|
e040b1a29b | |
|
c194053b83 | |
|
e4a4910e6b | |
|
33c3428796 | |
|
dfce9bf369 | |
|
f3dc516704 | |
|
d926166630 | |
|
52124edcd8 | |
|
dadb7dc49a | |
|
84da2da350 | |
|
cbbd83affc | |
|
c81d9b4e97 | |
|
d0a18fcdb7 | |
|
7ce0a7d698 | |
|
b651847ba3 | |
|
e4b4e5c943 | |
|
911df4ce05 | |
|
f2abe27704 |
54
README.md
54
README.md
|
@ -26,5 +26,55 @@ Welcome to the 4coder community repository.
|
||||||
1. `$ cd 4cc/code`
|
1. `$ cd 4cc/code`
|
||||||
2. `$ ./bin/build-linux.sh`
|
2. `$ ./bin/build-linux.sh`
|
||||||
|
|
||||||
## Mac (Untested)
|
## Mac
|
||||||
1. The steps should be the same as linux but replace the `*-linux.sh` with their `*-mac.sh` equivalents.
|
|
||||||
|
> 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.
|
||||||
|
|
|
@ -208,7 +208,10 @@ api_get_callable_name(Arena *arena, String_Const_u8 api_name, String_Const_u8 na
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
function void
|
function void
|
||||||
generate_api_master_list(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
|
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));
|
||||||
|
|
||||||
for (API_Call *call = api->first_call;
|
for (API_Call *call = api->first_call;
|
||||||
call != 0;
|
call != 0;
|
||||||
call = call->next){
|
call = call->next){
|
||||||
|
@ -236,7 +239,10 @@ generate_api_master_list(Arena *scratch, API_Definition *api, API_Generation_Fla
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
|
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));
|
||||||
|
|
||||||
for (API_Call *call = api->first_call;
|
for (API_Call *call = api->first_call;
|
||||||
call != 0;
|
call != 0;
|
||||||
call = call->next){
|
call = call->next){
|
||||||
|
@ -264,6 +270,8 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
|
||||||
fprintf(out, ")\n");
|
fprintf(out, ")\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(out, "\n");
|
||||||
|
|
||||||
for (API_Call *call = api->first_call;
|
for (API_Call *call = api->first_call;
|
||||||
call != 0;
|
call != 0;
|
||||||
call = call->next){
|
call = call->next){
|
||||||
|
@ -289,11 +297,13 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
|
||||||
fprintf(out, ");\n");
|
fprintf(out, ");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(out, "\n");
|
||||||
|
|
||||||
fprintf(out, "struct API_VTable_%.*s{\n", string_expand(api->name));
|
fprintf(out, "struct API_VTable_%.*s{\n", string_expand(api->name));
|
||||||
for (API_Call *call = api->first_call;
|
for (API_Call *call = api->first_call;
|
||||||
call != 0;
|
call != 0;
|
||||||
call = call->next){
|
call = call->next){
|
||||||
fprintf(out, "%.*s_%.*s_type *",
|
fprintf(out, " %.*s_%.*s_type *",
|
||||||
string_expand(api->name),
|
string_expand(api->name),
|
||||||
string_expand(call->name));
|
string_expand(call->name));
|
||||||
fprintf(out, "%.*s",
|
fprintf(out, "%.*s",
|
||||||
|
@ -302,6 +312,8 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
|
||||||
}
|
}
|
||||||
fprintf(out, "};\n");
|
fprintf(out, "};\n");
|
||||||
|
|
||||||
|
fprintf(out, "\n");
|
||||||
|
|
||||||
fprintf(out, "#if defined(STATIC_LINK_API)\n");
|
fprintf(out, "#if defined(STATIC_LINK_API)\n");
|
||||||
for (API_Call *call = api->first_call;
|
for (API_Call *call = api->first_call;
|
||||||
call != 0;
|
call != 0;
|
||||||
|
@ -328,6 +340,7 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
|
||||||
fprintf(out, ");\n");
|
fprintf(out, ");\n");
|
||||||
}
|
}
|
||||||
fprintf(out, "#undef STATIC_LINK_API\n");
|
fprintf(out, "#undef STATIC_LINK_API\n");
|
||||||
|
fprintf(out, "\n");
|
||||||
fprintf(out, "#elif defined(DYNAMIC_LINK_API)\n");
|
fprintf(out, "#elif defined(DYNAMIC_LINK_API)\n");
|
||||||
for (API_Call *call = api->first_call;
|
for (API_Call *call = api->first_call;
|
||||||
call != 0;
|
call != 0;
|
||||||
|
@ -343,7 +356,10 @@ generate_header(Arena *scratch, API_Definition *api, API_Generation_Flag flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
|
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));
|
||||||
|
|
||||||
fprintf(out, "function void\n");
|
fprintf(out, "function void\n");
|
||||||
fprintf(out, "%.*s_api_fill_vtable(API_VTable_%.*s *vtable){\n",
|
fprintf(out, "%.*s_api_fill_vtable(API_VTable_%.*s *vtable){\n",
|
||||||
string_expand(api->name),
|
string_expand(api->name),
|
||||||
|
@ -352,11 +368,12 @@ generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FIL
|
||||||
call != 0;
|
call != 0;
|
||||||
call = call->next){
|
call = call->next){
|
||||||
String_Const_u8 callable_name = api_get_callable_name(scratch, api->name, call->name, flags);
|
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(call->name),
|
||||||
string_expand(callable_name));
|
string_expand(callable_name));
|
||||||
}
|
}
|
||||||
fprintf(out, "}\n");
|
fprintf(out, "}\n");
|
||||||
|
fprintf(out, "\n");
|
||||||
|
|
||||||
fprintf(out, "#if defined(DYNAMIC_LINK_API)\n");
|
fprintf(out, "#if defined(DYNAMIC_LINK_API)\n");
|
||||||
fprintf(out, "function void\n");
|
fprintf(out, "function void\n");
|
||||||
|
@ -367,7 +384,7 @@ generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FIL
|
||||||
call != 0;
|
call != 0;
|
||||||
call = call->next){
|
call = call->next){
|
||||||
String_Const_u8 callable_name = api_get_callable_name(scratch, api->name, call->name, flags);
|
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(callable_name),
|
||||||
string_expand(call->name));
|
string_expand(call->name));
|
||||||
}
|
}
|
||||||
|
@ -377,18 +394,21 @@ generate_cpp(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FIL
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
generate_constructor(Arena *scratch, API_Definition *api, API_Generation_Flag flags, FILE *out){
|
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));
|
||||||
|
|
||||||
fprintf(out, "function API_Definition*\n");
|
fprintf(out, "function API_Definition*\n");
|
||||||
fprintf(out, "%.*s_api_construct(Arena *arena){\n",
|
fprintf(out, "%.*s_api_construct(Arena *arena){\n",
|
||||||
string_expand(api->name));
|
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));
|
string_expand(api->name));
|
||||||
|
|
||||||
for (API_Call *call = api->first_call;
|
for (API_Call *call = api->first_call;
|
||||||
call != 0;
|
call != 0;
|
||||||
call = call->next){
|
call = call->next){
|
||||||
fprintf(out, "{\n");
|
fprintf(out, " {\n");
|
||||||
fprintf(out, "API_Call *call = api_call_with_location(arena, result, "
|
fprintf(out, " API_Call *call = api_call_with_location(arena, result, "
|
||||||
"string_u8_litexpr(\"%.*s\"), "
|
"string_u8_litexpr(\"%.*s\"), "
|
||||||
"string_u8_litexpr(\"%.*s\"), "
|
"string_u8_litexpr(\"%.*s\"), "
|
||||||
"string_u8_litexpr(\"\"));\n",
|
"string_u8_litexpr(\"\"));\n",
|
||||||
|
@ -396,29 +416,29 @@ generate_constructor(Arena *scratch, API_Definition *api, API_Generation_Flag fl
|
||||||
string_expand(call->return_type));
|
string_expand(call->return_type));
|
||||||
|
|
||||||
if (call->params.count == 0){
|
if (call->params.count == 0){
|
||||||
fprintf(out, "(void)call;\n");
|
fprintf(out, " (void)call;\n");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for (API_Param *param = call->params.first;
|
for (API_Param *param = call->params.first;
|
||||||
param != 0;
|
param != 0;
|
||||||
param = param->next){
|
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->type_name),
|
||||||
string_expand(param->name));
|
string_expand(param->name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(out, "}\n");
|
fprintf(out, " }\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(out, "return(result);\n");
|
fprintf(out, " return(result);\n");
|
||||||
fprintf(out, "}\n");
|
fprintf(out, "}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
function b32
|
function b32
|
||||||
api_definition_generate_api_includes(Arena *arena, API_Definition *api, Generated_Group group, API_Generation_Flag flags){
|
api_definition_generate_api_includes(Arena *arena, API_Definition *api, Generated_Group group, API_Generation_Flag flags, String_Const_u8 generated_by){
|
||||||
// NOTE(allen): Arrange output files
|
// NOTE(allen): Arrange output files
|
||||||
|
|
||||||
String_Const_u8 path_to_self = string_u8_litexpr(__FILE__);
|
String_Const_u8 path_to_self = string_u8_litexpr(__FILE__);
|
||||||
|
@ -494,10 +514,10 @@ api_definition_generate_api_includes(Arena *arena, API_Definition *api, Generate
|
||||||
|
|
||||||
// NOTE(allen): Generate output
|
// NOTE(allen): Generate output
|
||||||
|
|
||||||
generate_api_master_list(arena, api, flags, out_file_ml);
|
generate_api_master_list(arena, api, flags, out_file_ml, generated_by);
|
||||||
generate_header(arena, api, flags, out_file_h);
|
generate_header(arena, api, flags, out_file_h, generated_by);
|
||||||
generate_cpp(arena, api, flags, out_file_cpp);
|
generate_cpp(arena, api, flags, out_file_cpp, generated_by);
|
||||||
generate_constructor(arena, api, flags, out_file_con);
|
generate_constructor(arena, api, flags, out_file_con, generated_by);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
@ -594,7 +614,7 @@ api_definition_check(Arena *arena, API_Definition *correct, API_Definition *remo
|
||||||
API_Call *correct_call = api_get_call(correct, call->name);
|
API_Call *correct_call = api_get_call(correct, call->name);
|
||||||
if (correct_call == 0 && report_extra){
|
if (correct_call == 0 && report_extra){
|
||||||
api_definition_error(arena, error_list,
|
api_definition_error(arena, error_list,
|
||||||
"remote call", call,
|
"remote call", call,
|
||||||
"does not exist in api master");
|
"does not exist in api master");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ int
|
||||||
main(void){
|
main(void){
|
||||||
Arena arena = make_arena_malloc();
|
Arena arena = make_arena_malloc();
|
||||||
API_Definition *api = define_api(&arena);
|
API_Definition *api = define_api(&arena);
|
||||||
if (!api_definition_generate_api_includes(&arena, api, get_api_group(), 0)){
|
if (!api_definition_generate_api_includes(&arena, api, get_api_group(), 0, SCu8(GENERATED_BY))){
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
|
|
@ -37,9 +37,21 @@ main(int argc, char **argv){
|
||||||
exit(1);
|
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 = {};
|
API_Definition_List list = {};
|
||||||
for (i32 i = 1; i < argc; i += 1){
|
for (i32 i = 1; i < argc; i += 1){
|
||||||
char *file_name = argv[i];
|
char *file_name = argv[i];
|
||||||
|
string_append_character(&command_line, ' ');
|
||||||
|
string_append(&command_line, SCu8(argv[i]));
|
||||||
FILE *file = fopen(file_name, "rb");
|
FILE *file = fopen(file_name, "rb");
|
||||||
if (file == 0){
|
if (file == 0){
|
||||||
printf("error: could not open input file: '%s'\n", argv[i]);
|
printf("error: could not open input file: '%s'\n", argv[i]);
|
||||||
|
@ -57,7 +69,7 @@ main(int argc, char **argv){
|
||||||
for (API_Definition *node = list.first;
|
for (API_Definition *node = list.first;
|
||||||
node != 0;
|
node != 0;
|
||||||
node = node->next){
|
node = node->next){
|
||||||
api_definition_generate_api_includes(&arena, node, GeneratedGroup_Custom, APIGeneration_NoAPINameOnCallables);
|
api_definition_generate_api_includes(&arena, node, GeneratedGroup_Custom, APIGeneration_NoAPINameOnCallables, SCu8(command_line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,9 @@ edit_change_current_history_state(Thread_Context *tctx, Models *models, Editing_
|
||||||
}
|
}
|
||||||
|
|
||||||
file->state.current_record_index = current;
|
file->state.current_record_index = current;
|
||||||
|
if (file->state.saved_record_index == current){
|
||||||
|
RemFlag(file->state.dirty, DirtyState_UnsavedChanges);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,7 @@ 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);
|
File_Attributes new_attributes = system_save_file(scratch, (char*)file_name, saveable_string);
|
||||||
if (new_attributes.last_write_time > 0 &&
|
if (new_attributes.last_write_time > 0 &&
|
||||||
using_actual_file_name){
|
using_actual_file_name){
|
||||||
|
file->state.saved_record_index = file->state.current_record_index;
|
||||||
file->state.save_state = FileSaveState_SavedWaitingForNotification;
|
file->state.save_state = FileSaveState_SavedWaitingForNotification;
|
||||||
file_clear_dirty_flags(file);
|
file_clear_dirty_flags(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ struct Editing_File_State{
|
||||||
History history;
|
History history;
|
||||||
i32 current_record_index;
|
i32 current_record_index;
|
||||||
|
|
||||||
|
i32 saved_record_index;
|
||||||
|
|
||||||
Dirty_State dirty;
|
Dirty_State dirty;
|
||||||
File_Save_State save_state;
|
File_Save_State save_state;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
|
#define GENERATED_BY "code/4ed_font_api.cpp"
|
||||||
|
|
||||||
#include "4ed_api_definition_main.cpp"
|
#include "4ed_api_definition_main.cpp"
|
||||||
|
|
||||||
function API_Definition*
|
function API_Definition*
|
||||||
|
|
|
@ -33,13 +33,13 @@ ft__load_flags(b32 use_hinting){
|
||||||
internal FT_Codepoint_Index_Pair_Array
|
internal FT_Codepoint_Index_Pair_Array
|
||||||
ft__get_codepoint_index_pairs(Arena *arena, FT_Face face, u16 *maximum_index_out){
|
ft__get_codepoint_index_pairs(Arena *arena, FT_Face face, u16 *maximum_index_out){
|
||||||
FT_Long glyph_count = face->num_glyphs;
|
FT_Long glyph_count = face->num_glyphs;
|
||||||
|
|
||||||
FT_Codepoint_Index_Pair_Array array = {};
|
FT_Codepoint_Index_Pair_Array array = {};
|
||||||
array.count = glyph_count;
|
array.count = glyph_count;
|
||||||
array.vals = push_array(arena, FT_Codepoint_Index_Pair, glyph_count);
|
array.vals = push_array(arena, FT_Codepoint_Index_Pair, glyph_count);
|
||||||
|
|
||||||
u16 maximum_index = 0;
|
u16 maximum_index = 0;
|
||||||
|
|
||||||
i32 counter = 0;
|
i32 counter = 0;
|
||||||
FT_UInt index = 0;
|
FT_UInt index = 0;
|
||||||
FT_ULong codepoint = FT_Get_First_Char(face, &index);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*maximum_index_out = maximum_index;
|
*maximum_index_out = maximum_index;
|
||||||
|
|
||||||
return(array);
|
return(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Codepoint_Index_Map
|
internal Codepoint_Index_Map
|
||||||
ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){
|
ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){
|
||||||
FT_Long glyph_count = face->num_glyphs;
|
FT_Long glyph_count = face->num_glyphs;
|
||||||
|
|
||||||
Codepoint_Index_Map map = {};
|
Codepoint_Index_Map map = {};
|
||||||
map.zero_index = max_u16;
|
map.zero_index = max_u16;
|
||||||
map.table = make_table_u32_u16(base_allocator, glyph_count*4);
|
map.table = make_table_u32_u16(base_allocator, glyph_count*4);
|
||||||
|
|
||||||
u16 maximum_index = 0;
|
u16 maximum_index = 0;
|
||||||
|
|
||||||
i32 counter = 0;
|
i32 counter = 0;
|
||||||
FT_UInt index = 0;
|
FT_UInt index = 0;
|
||||||
FT_ULong codepoint = FT_Get_First_Char(face, &index);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map.max_index = maximum_index;
|
map.max_index = maximum_index;
|
||||||
|
|
||||||
return(map);
|
return(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,27 +125,50 @@ ft__bad_rect_pack_end_line(Bad_Rect_Pack *pack){
|
||||||
|
|
||||||
internal Vec3_i32
|
internal Vec3_i32
|
||||||
ft__bad_rect_pack_next(Bad_Rect_Pack *pack, Vec2_i32 dim){
|
ft__bad_rect_pack_next(Bad_Rect_Pack *pack, Vec2_i32 dim){
|
||||||
Vec3_i32 result = {};
|
|
||||||
if (dim.x <= pack->max_dim.x && dim.y <= pack->max_dim.y){
|
Vec3_i32 result = { };
|
||||||
if (pack->current_line_h < dim.y){
|
|
||||||
pack->current_line_h = dim.y;
|
// 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;
|
||||||
}
|
}
|
||||||
if (pack->current_line_h > pack->max_dim.y){
|
|
||||||
ft__bad_rect_pack_end_line(pack);
|
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.
|
||||||
pack->p.y = 0;
|
pack->p.y = 0;
|
||||||
pack->dim.z += 1;
|
pack->dim.z += 1;
|
||||||
pack->p.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.
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
if (pack->p.x + dim.x > pack->max_dim.x){
|
// NOTE(simon, 28/02/24): We are now sure that the character will fit.
|
||||||
ft__bad_rect_pack_end_line(pack);
|
pack->current_line_h = Max(pack->current_line_h, dim.y);
|
||||||
}
|
|
||||||
result = pack->p;
|
result = pack->p;
|
||||||
pack->p.x += dim.x;
|
pack->p.x += dim.x;
|
||||||
pack->current_line_h = Max(pack->current_line_h, dim.y);
|
pack->dim.x = Max( pack->dim.x, pack->p.x );
|
||||||
pack->dim.x = clamp_bot(pack->dim.x, pack->p.x);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,31 +186,31 @@ ft__glyph_bounds_store_uv_raw(Vec3_i32 p, Vec2_i32 dim, Glyph_Bounds *bounds){
|
||||||
internal Face*
|
internal Face*
|
||||||
ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor){
|
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);
|
String_Const_u8 file_name = push_string_copy(arena, description->font.file_name);
|
||||||
|
|
||||||
FT_Library ft;
|
FT_Library ft;
|
||||||
FT_Init_FreeType(&ft);
|
FT_Init_FreeType(&ft);
|
||||||
|
|
||||||
FT_Face ft_face;
|
FT_Face ft_face;
|
||||||
FT_Error error = FT_New_Face(ft, (char*)file_name.str, 0, &ft_face);
|
FT_Error error = FT_New_Face(ft, (char*)file_name.str, 0, &ft_face);
|
||||||
|
|
||||||
Face *face = 0;
|
Face *face = 0;
|
||||||
if (error == 0){
|
if (error == 0){
|
||||||
face = push_array_zero(arena, Face, 1);
|
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);
|
u32 pt_size = (u32)(pt_size_unscaled*scale_factor);
|
||||||
b32 hinting = description->parameters.hinting;
|
b32 hinting = description->parameters.hinting;
|
||||||
|
|
||||||
FT_Size_RequestRec_ size = {};
|
FT_Size_RequestRec_ size = {};
|
||||||
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
|
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
|
||||||
size.height = (pt_size << 6);
|
size.height = (pt_size << 6);
|
||||||
FT_Request_Size(ft_face, &size);
|
FT_Request_Size(ft_face, &size);
|
||||||
|
|
||||||
face->description.font.file_name = file_name;
|
face->description.font.file_name = file_name;
|
||||||
face->description.parameters = description->parameters;
|
face->description.parameters = description->parameters;
|
||||||
|
|
||||||
Face_Metrics *met = &face->metrics;
|
Face_Metrics *met = &face->metrics;
|
||||||
|
|
||||||
met->max_advance = f32_ceil32(ft_face->size->metrics.max_advance/64.f);
|
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->ascent = f32_ceil32(ft_face->size->metrics.ascender/64.f);
|
||||||
met->descent = f32_floor32(ft_face->size->metrics.descender/64.f);
|
met->descent = f32_floor32(ft_face->size->metrics.descender/64.f);
|
||||||
|
@ -195,19 +218,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 = met->text_height - (met->ascent - met->descent);
|
||||||
met->line_skip = clamp_bot(1.f, met->line_skip);
|
met->line_skip = clamp_bot(1.f, met->line_skip);
|
||||||
met->line_height = met->text_height + met->line_skip;
|
met->line_height = met->text_height + met->line_skip;
|
||||||
|
|
||||||
{
|
{
|
||||||
f32 real_over_notional = met->line_height/(f32)ft_face->height;
|
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_center = -1.f*real_over_notional*ft_face->underline_position;
|
||||||
f32 relative_thickness = real_over_notional*ft_face->underline_thickness;
|
f32 relative_thickness = real_over_notional*ft_face->underline_thickness;
|
||||||
|
|
||||||
f32 center = f32_floor32(met->ascent + relative_center);
|
f32 center = f32_floor32(met->ascent + relative_center);
|
||||||
f32 thickness = clamp_bot(1.f, relative_thickness);
|
f32 thickness = clamp_bot(1.f, relative_thickness);
|
||||||
|
|
||||||
met->underline_yoff1 = center - thickness*0.5f;
|
met->underline_yoff1 = center - thickness*0.5f;
|
||||||
met->underline_yoff2 = center + thickness*0.5f;
|
met->underline_yoff2 = center + thickness*0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
face->advance_map.codepoint_to_index =
|
face->advance_map.codepoint_to_index =
|
||||||
ft__get_codepoint_index_map(arena->base_allocator, ft_face);
|
ft__get_codepoint_index_map(arena->base_allocator, ft_face);
|
||||||
u16 index_count =
|
u16 index_count =
|
||||||
|
@ -215,40 +238,40 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
|
||||||
face->advance_map.index_count = index_count;
|
face->advance_map.index_count = index_count;
|
||||||
face->advance_map.advance = push_array_zero(arena, f32, index_count);
|
face->advance_map.advance = push_array_zero(arena, f32, index_count);
|
||||||
face->bounds = push_array(arena, Glyph_Bounds, index_count);
|
face->bounds = push_array(arena, Glyph_Bounds, index_count);
|
||||||
|
|
||||||
Temp_Memory_Block temp_memory(arena);
|
Temp_Memory_Block temp_memory(arena);
|
||||||
struct Bitmap{
|
struct Bitmap{
|
||||||
Vec2_i32 dim;
|
Vec2_i32 dim;
|
||||||
u8 *data;
|
u8 *data;
|
||||||
};
|
};
|
||||||
Bitmap *glyph_bitmaps = push_array(arena, Bitmap, index_count);
|
Bitmap *glyph_bitmaps = push_array(arena, Bitmap, index_count);
|
||||||
|
|
||||||
u32 load_flags = ft__load_flags(hinting);
|
u32 load_flags = ft__load_flags(hinting);
|
||||||
for (u16 i = 0; i < index_count; i += 1){
|
for (u16 i = 0; i < index_count; i += 1){
|
||||||
Bitmap *bitmap = &glyph_bitmaps[i];
|
Bitmap *bitmap = &glyph_bitmaps[i];
|
||||||
|
|
||||||
error = FT_Load_Glyph(ft_face, i, load_flags);
|
error = FT_Load_Glyph(ft_face, i, load_flags);
|
||||||
if (error == 0){
|
if (error == 0){
|
||||||
FT_GlyphSlot ft_glyph = ft_face->glyph;
|
FT_GlyphSlot ft_glyph = ft_face->glyph;
|
||||||
Vec2_i32 dim = V2i32(ft_glyph->bitmap.width, ft_glyph->bitmap.rows);
|
Vec2_i32 dim = V2i32(ft_glyph->bitmap.width, ft_glyph->bitmap.rows);
|
||||||
bitmap->dim = dim;
|
bitmap->dim = dim;
|
||||||
bitmap->data = push_array(arena, u8, dim.x*dim.y);
|
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.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.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.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);
|
face->bounds[i].xy_off.y1 = (f32)(face->bounds[i].xy_off.y0 + dim.y);
|
||||||
|
|
||||||
switch (ft_glyph->bitmap.pixel_mode){
|
switch (ft_glyph->bitmap.pixel_mode){
|
||||||
case FT_PIXEL_MODE_MONO:
|
case FT_PIXEL_MODE_MONO:
|
||||||
{
|
{
|
||||||
NotImplemented;
|
NotImplemented;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case FT_PIXEL_MODE_GRAY:
|
case FT_PIXEL_MODE_GRAY:
|
||||||
{
|
{
|
||||||
b32 aa_1bit_mono = (description->parameters.aa_mode == FaceAntialiasingMode_1BitMono);
|
b32 aa_1bit_mono = (description->parameters.aa_mode == FaceAntialiasingMode_1BitMono);
|
||||||
|
|
||||||
u8 *src_line = ft_glyph->bitmap.buffer;
|
u8 *src_line = ft_glyph->bitmap.buffer;
|
||||||
if (ft_glyph->bitmap.pitch < 0){
|
if (ft_glyph->bitmap.pitch < 0){
|
||||||
src_line = ft_glyph->bitmap.buffer + (-ft_glyph->bitmap.pitch)*(dim.y - 1);
|
src_line = ft_glyph->bitmap.buffer + (-ft_glyph->bitmap.pitch)*(dim.y - 1);
|
||||||
|
@ -273,28 +296,28 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor
|
||||||
src_line += ft_glyph->bitmap.pitch;
|
src_line += ft_glyph->bitmap.pitch;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
NotImplemented;
|
NotImplemented;
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
face->advance_map.advance[i] = f32_ceil32(ft_glyph->advance.x/64.0f);
|
face->advance_map.advance[i] = f32_ceil32(ft_glyph->advance.x/64.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 white_data[16] = {
|
u8 white_data[16] = {
|
||||||
0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
Bitmap white = {};
|
Bitmap white = {};
|
||||||
white.dim = V2i32(4, 4);
|
white.dim = V2i32(4, 4);
|
||||||
white.data = white_data;
|
white.data = white_data;
|
||||||
|
|
||||||
Bad_Rect_Pack pack = {};
|
Bad_Rect_Pack pack = {};
|
||||||
ft__bad_rect_pack_init(&pack, V2i32(1024, 1024));
|
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);
|
ft__glyph_bounds_store_uv_raw(ft__bad_rect_pack_next(&pack, white.dim), white.dim, &face->white);
|
||||||
|
@ -303,69 +326,76 @@ 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__glyph_bounds_store_uv_raw(ft__bad_rect_pack_next(&pack, dim), dim, &face->bounds[i]);
|
||||||
}
|
}
|
||||||
ft__bad_rect_store_finish(&pack);
|
ft__bad_rect_store_finish(&pack);
|
||||||
|
|
||||||
Texture_Kind texture_kind = TextureKind_Mono;
|
Texture_Kind texture_kind = TextureKind_Mono;
|
||||||
u32 texture = graphics_get_texture(pack.dim, texture_kind);
|
u32 texture = graphics_get_texture(pack.dim, texture_kind);
|
||||||
face->texture_kind = texture_kind;
|
|
||||||
face->texture = texture;
|
/* 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. */
|
||||||
Vec3_f32 texture_dim = V3f32(pack.dim);
|
if (texture != 0 ){
|
||||||
face->texture_dim = texture_dim;
|
|
||||||
|
face->texture_kind = texture_kind;
|
||||||
{
|
face->texture = texture;
|
||||||
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);
|
Vec3_f32 texture_dim = V3f32(pack.dim);
|
||||||
graphics_fill_texture(texture_kind, texture, p, dim, white.data);
|
face->texture_dim = texture_dim;
|
||||||
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;
|
Vec3_i32 p = V3i32((i32)face->white.uv.x0, (i32)face->white.uv.y0, (i32)face->white.w);
|
||||||
face->white.uv.y0 = face->white.uv.y0/texture_dim.y;
|
Vec3_i32 dim = V3i32(white.dim.x, white.dim.y, 1);
|
||||||
face->white.w /= texture_dim.z;
|
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;
|
||||||
for (u16 i = 0; i < index_count; i += 1){
|
face->white.uv.x0 = face->white.uv.x0/texture_dim.x;
|
||||||
Vec3_i32 p = V3i32((i32)face->bounds[i].uv.x0, (i32)face->bounds[i].uv.y0, (i32)face->bounds[i].w);
|
face->white.uv.y0 = face->white.uv.y0/texture_dim.y;
|
||||||
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;
|
for (u16 i = 0; i < index_count; i += 1){
|
||||||
face->bounds[i].uv.y1 = (face->bounds[i].uv.y0 + face->bounds[i].uv.y1)/texture_dim.y;
|
Vec3_i32 p = V3i32((i32)face->bounds[i].uv.x0, (i32)face->bounds[i].uv.y0, (i32)face->bounds[i].w);
|
||||||
face->bounds[i].uv.x0 = face->bounds[i].uv.x0/texture_dim.x;
|
Vec3_i32 dim = V3i32(glyph_bitmaps[i].dim.x, glyph_bitmaps[i].dim.y, 1);
|
||||||
face->bounds[i].uv.y0 = face->bounds[i].uv.y0/texture_dim.y;
|
graphics_fill_texture(texture_kind, texture, p, dim, glyph_bitmaps[i].data);
|
||||||
face->bounds[i].w /= texture_dim.z;
|
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 =
|
Face_Advance_Map *advance_map = &face->advance_map;
|
||||||
font_get_max_glyph_advance_range(advance_map, met, '0', '9', 0);
|
|
||||||
met->hex_digit_advance =
|
met->space_advance = font_get_glyph_advance(advance_map, met, ' ', 0);
|
||||||
font_get_max_glyph_advance_range(advance_map, met, 'A', 'F', 0);
|
met->decimal_digit_advance =
|
||||||
met->hex_digit_advance =
|
font_get_max_glyph_advance_range(advance_map, met, '0', '9', 0);
|
||||||
Max(met->hex_digit_advance, met->decimal_digit_advance);
|
met->hex_digit_advance =
|
||||||
met->byte_sub_advances[0] =
|
font_get_max_glyph_advance_range(advance_map, met, 'A', 'F', 0);
|
||||||
font_get_glyph_advance(advance_map, met, '\\', 0);
|
met->hex_digit_advance =
|
||||||
met->byte_sub_advances[1] = met->hex_digit_advance;
|
Max(met->hex_digit_advance, met->decimal_digit_advance);
|
||||||
met->byte_sub_advances[2] = met->hex_digit_advance;
|
met->byte_sub_advances[0] =
|
||||||
met->byte_advance =
|
font_get_glyph_advance(advance_map, met, '\\', 0);
|
||||||
met->byte_sub_advances[0] +
|
met->byte_sub_advances[1] = met->hex_digit_advance;
|
||||||
met->byte_sub_advances[1] +
|
met->byte_sub_advances[2] = met->hex_digit_advance;
|
||||||
met->byte_sub_advances[2];
|
met->byte_advance =
|
||||||
met->normal_lowercase_advance =
|
met->byte_sub_advances[0] +
|
||||||
font_get_average_glyph_advance_range(advance_map, met, 'a', 'z', 0);
|
met->byte_sub_advances[1] +
|
||||||
met->normal_uppercase_advance =
|
met->byte_sub_advances[2];
|
||||||
font_get_average_glyph_advance_range(advance_map, met, 'A', 'Z', 0);
|
met->normal_lowercase_advance =
|
||||||
met->normal_advance = (26*met->normal_lowercase_advance +
|
font_get_average_glyph_advance_range(advance_map, met, 'a', 'z', 0);
|
||||||
26*met->normal_uppercase_advance +
|
met->normal_uppercase_advance =
|
||||||
10*met->decimal_digit_advance)/62.f;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Done_FreeType(ft);
|
FT_Done_FreeType(ft);
|
||||||
|
|
||||||
return(face);
|
return(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,9 @@ font_set_modify_face(Font_Set *set, Face_ID id, Face_Description *description){
|
||||||
Arena arena = make_arena_system();
|
Arena arena = make_arena_system();
|
||||||
Face *face = font_make_face(&arena, description, set->scale_factor);
|
Face *face = font_make_face(&arena, description, set->scale_factor);
|
||||||
if (face != 0){
|
if (face != 0){
|
||||||
|
if (slot->face->texture != 0){
|
||||||
|
graphics_free_texture(slot->face->texture);
|
||||||
|
}
|
||||||
linalloc_clear(&slot->arena);
|
linalloc_clear(&slot->arena);
|
||||||
slot->arena = arena;
|
slot->arena = arena;
|
||||||
slot->face = face;
|
slot->face = face;
|
||||||
|
|
|
@ -45,20 +45,20 @@ generate_codes(Arena *scratch, Event_Code_List *list, FILE *out){
|
||||||
for (Event_Code *code = list->first;
|
for (Event_Code *code = list->first;
|
||||||
code != 0;
|
code != 0;
|
||||||
code = code->next){
|
code = code->next){
|
||||||
fprintf(out, "%.*s_%.*s = %d,\n",
|
fprintf(out, " %.*s_%.*s = %d,\n",
|
||||||
string_expand(code_prefix), string_expand(code->name), counter);
|
string_expand(code_prefix), string_expand(code->name), counter);
|
||||||
counter += 1;
|
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, "};\n");
|
||||||
|
|
||||||
fprintf(out, "global char* %.*s[%.*s_COUNT] = {\n",
|
fprintf(out, "global char* %.*s[%.*s_COUNT] = {\n",
|
||||||
string_expand(name_table), string_expand(code_prefix));
|
string_expand(name_table), string_expand(code_prefix));
|
||||||
fprintf(out, "\"None\",\n");
|
fprintf(out, " \"None\",\n");
|
||||||
for (Event_Code *code = list->first;
|
for (Event_Code *code = list->first;
|
||||||
code != 0;
|
code != 0;
|
||||||
code = code->next){
|
code = code->next){
|
||||||
fprintf(out, "\"%.*s\",\n", string_expand(code->name));
|
fprintf(out, " \"%.*s\",\n", string_expand(code->name));
|
||||||
counter += 1;
|
counter += 1;
|
||||||
}
|
}
|
||||||
fprintf(out, "};\n");
|
fprintf(out, "};\n");
|
||||||
|
@ -188,6 +188,9 @@ main(void){
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(out, "/* Generated by: " __FILE__ );
|
||||||
|
fprintf(out, " */\n" );
|
||||||
|
|
||||||
generate_codes(&arena, &key_list, out);
|
generate_codes(&arena, &key_list, out);
|
||||||
generate_codes(&arena, &mouse_list, out);
|
generate_codes(&arena, &mouse_list, out);
|
||||||
generate_codes(&arena, &core_list, out);
|
generate_codes(&arena, &core_list, out);
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
|
#define GENERATED_BY "code/4ed_graphics_api.cpp"
|
||||||
|
|
||||||
#include "4ed_api_definition_main.cpp"
|
#include "4ed_api_definition_main.cpp"
|
||||||
|
|
||||||
function API_Definition*
|
function API_Definition*
|
||||||
|
@ -30,6 +32,11 @@ define_api(Arena *arena){
|
||||||
api_param(arena, call, "void*", "data");
|
api_param(arena, call, "void*", "data");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
API_Call *call = api_call(arena, api, "free_texture", "void");
|
||||||
|
api_param(arena, call, "u32", "texid");
|
||||||
|
}
|
||||||
|
|
||||||
return(api);
|
return(api);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,27 +132,32 @@ end_render_section(Render_Target *target){
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
draw_rectangle_outline(Render_Target *target, Rect_f32 rect, f32 roundness, f32 thickness, u32 color){
|
draw_rectangle_outline(Render_Target *target, Rect_f32 rect, f32 roundness, f32 thickness, u32 color){
|
||||||
if (roundness < epsilon_f32){
|
|
||||||
roundness = 0.f;
|
|
||||||
}
|
|
||||||
thickness = clamp_bot(1.f, thickness);
|
|
||||||
f32 half_thickness = thickness*0.5f;
|
|
||||||
|
|
||||||
Render_Vertex vertices[6] = {};
|
if ( rect_overlap(rect, target->current_clip_box) ) {
|
||||||
vertices[0].xy = V2f32(rect.x0, rect.y0);
|
|
||||||
vertices[1].xy = V2f32(rect.x1, rect.y0);
|
if (roundness < epsilon_f32){
|
||||||
vertices[2].xy = V2f32(rect.x0, rect.y1);
|
roundness = 0.f;
|
||||||
vertices[3].xy = V2f32(rect.x1, rect.y0);
|
}
|
||||||
vertices[4].xy = V2f32(rect.x0, rect.y1);
|
thickness = clamp_bot(1.f, thickness);
|
||||||
vertices[5].xy = V2f32(rect.x1, rect.y1);
|
f32 half_thickness = thickness*0.5f;
|
||||||
|
|
||||||
Vec2_f32 center = rect_center(rect);
|
Render_Vertex vertices[6] = {};
|
||||||
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
|
vertices[0].xy = V2f32(rect.x0, rect.y0);
|
||||||
vertices[i].uvw = V3f32(center.x, center.y, roundness);
|
vertices[1].xy = V2f32(rect.x1, rect.y0);
|
||||||
vertices[i].color = color;
|
vertices[2].xy = V2f32(rect.x0, rect.y1);
|
||||||
vertices[i].half_thickness = half_thickness;
|
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));
|
||||||
}
|
}
|
||||||
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
@ -194,53 +199,62 @@ draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p,
|
||||||
vertices[2].xy = p_x_min + y_max;
|
vertices[2].xy = p_x_min + y_max;
|
||||||
vertices[5].xy = p_x_max + y_max;
|
vertices[5].xy = p_x_max + y_max;
|
||||||
|
|
||||||
#if 0
|
/* NOTE simon (26/09/24): We don't use rect_overlap here because the text rect is not guaranteed to be axis aligned. */
|
||||||
Vec2_f32 xy_min = p + bounds.xy_off.x0*x_axis + bounds.xy_off.y0*y_axis;
|
b32 draw = rect_contains_point( target->current_clip_box, vertices[ 0 ].xy );
|
||||||
Vec2_f32 xy_max = p + bounds.xy_off.x1*x_axis + bounds.xy_off.y1*y_axis;
|
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 );
|
||||||
|
|
||||||
vertices[0].xy = V2f32(xy_min.x, xy_min.y);
|
if ( draw ) {
|
||||||
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 0
|
||||||
if (!HasFlag(flags, GlyphFlag_Rotate90)){
|
Vec2_f32 xy_min = p + bounds.xy_off.x0*x_axis + bounds.xy_off.y0*y_axis;
|
||||||
Rect_f32 xy = Rf32(p + bounds.xy_off.p0, p + bounds.xy_off.p1);
|
Vec2_f32 xy_max = p + bounds.xy_off.x1*x_axis + bounds.xy_off.y1*y_axis;
|
||||||
|
|
||||||
vertices[0].xy = V2f32(xy.x0, xy.y1);
|
vertices[0].xy = V2f32(xy_min.x, xy_min.y);
|
||||||
vertices[0].uvw = V3f32(uv.x0, uv.y1, bounds.w);
|
vertices[1].xy = V2f32(xy_max.x, xy_min.y);
|
||||||
vertices[1].xy = V2f32(xy.x1, xy.y1);
|
vertices[2].xy = V2f32(xy_min.x, xy_max.y);
|
||||||
vertices[1].uvw = V3f32(uv.x1, uv.y1, bounds.w);
|
vertices[5].xy = V2f32(xy_max.x, xy_max.y);
|
||||||
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
|
#endif
|
||||||
|
|
||||||
vertices[3] = vertices[1];
|
#if 0
|
||||||
vertices[4] = vertices[2];
|
if (!HasFlag(flags, GlyphFlag_Rotate90)){
|
||||||
|
Rect_f32 xy = Rf32(p + bounds.xy_off.p0, p + bounds.xy_off.p1);
|
||||||
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
|
|
||||||
vertices[i].color = color;
|
vertices[0].xy = V2f32(xy.x0, xy.y1);
|
||||||
vertices[i].half_thickness = 0.f;
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
|
#define GENERATED_BY "code/4ed_system_api.cpp"
|
||||||
|
|
||||||
#include "4ed_api_definition_main.cpp"
|
#include "4ed_api_definition_main.cpp"
|
||||||
|
|
||||||
function API_Definition*
|
function API_Definition*
|
||||||
|
|
|
@ -185,7 +185,7 @@ get_defines_from_flags(Arena *arena, u32 flags){
|
||||||
"-wd4611 -wd4189 -WX -GR- -EHa- -nologo -FC"
|
"-wd4611 -wd4189 -WX -GR- -EHa- -nologo -FC"
|
||||||
|
|
||||||
#define CL_LIBS_COMMON \
|
#define CL_LIBS_COMMON \
|
||||||
"user32.lib winmm.lib gdi32.lib opengl32.lib comdlg32.lib userenv.lib "
|
"user32.lib winmm.lib gdi32.lib comdlg32.lib userenv.lib "
|
||||||
#define CL_LIBS_X64 CL_LIBS_COMMON FOREIGN_WIN "\\x64\\freetype.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"
|
#define CL_LIBS_X86 CL_LIBS_COMMON FOREIGN_WIN "\\x86\\freetype.lib"
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* Generated by: 4ed_generate_keycodes.cpp */
|
||||||
enum{
|
enum{
|
||||||
KeyCode_A = 1,
|
KeyCode_A = 1,
|
||||||
KeyCode_B = 2,
|
KeyCode_B = 2,
|
||||||
|
|
|
@ -1,367 +1,370 @@
|
||||||
|
/* Generated by "code/4ed_api_parser_main.exe 4ed_api_implementation.cpp" */
|
||||||
|
|
||||||
function void
|
function void
|
||||||
custom_api_fill_vtable(API_VTable_custom *vtable){
|
custom_api_fill_vtable(API_VTable_custom *vtable){
|
||||||
vtable->global_set_setting = global_set_setting;
|
vtable->global_set_setting = global_set_setting;
|
||||||
vtable->global_get_screen_rectangle = global_get_screen_rectangle;
|
vtable->global_get_screen_rectangle = global_get_screen_rectangle;
|
||||||
vtable->get_thread_context = get_thread_context;
|
vtable->get_thread_context = get_thread_context;
|
||||||
vtable->create_child_process = create_child_process;
|
vtable->create_child_process = create_child_process;
|
||||||
vtable->child_process_set_target_buffer = child_process_set_target_buffer;
|
vtable->child_process_set_target_buffer = child_process_set_target_buffer;
|
||||||
vtable->buffer_get_attached_child_process = buffer_get_attached_child_process;
|
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_attached_buffer = child_process_get_attached_buffer;
|
||||||
vtable->child_process_get_state = child_process_get_state;
|
vtable->child_process_get_state = child_process_get_state;
|
||||||
vtable->enqueue_virtual_event = enqueue_virtual_event;
|
vtable->enqueue_virtual_event = enqueue_virtual_event;
|
||||||
vtable->get_buffer_count = get_buffer_count;
|
vtable->get_buffer_count = get_buffer_count;
|
||||||
vtable->get_buffer_next = get_buffer_next;
|
vtable->get_buffer_next = get_buffer_next;
|
||||||
vtable->get_buffer_by_name = get_buffer_by_name;
|
vtable->get_buffer_by_name = get_buffer_by_name;
|
||||||
vtable->get_buffer_by_file_name = get_buffer_by_file_name;
|
vtable->get_buffer_by_file_name = get_buffer_by_file_name;
|
||||||
vtable->buffer_read_range = buffer_read_range;
|
vtable->buffer_read_range = buffer_read_range;
|
||||||
vtable->buffer_replace_range = buffer_replace_range;
|
vtable->buffer_replace_range = buffer_replace_range;
|
||||||
vtable->buffer_batch_edit = buffer_batch_edit;
|
vtable->buffer_batch_edit = buffer_batch_edit;
|
||||||
vtable->buffer_seek_string = buffer_seek_string;
|
vtable->buffer_seek_string = buffer_seek_string;
|
||||||
vtable->buffer_seek_character_class = buffer_seek_character_class;
|
vtable->buffer_seek_character_class = buffer_seek_character_class;
|
||||||
vtable->buffer_line_y_difference = buffer_line_y_difference;
|
vtable->buffer_line_y_difference = buffer_line_y_difference;
|
||||||
vtable->buffer_line_shift_y = buffer_line_shift_y;
|
vtable->buffer_line_shift_y = buffer_line_shift_y;
|
||||||
vtable->buffer_pos_at_relative_xy = buffer_pos_at_relative_xy;
|
vtable->buffer_pos_at_relative_xy = buffer_pos_at_relative_xy;
|
||||||
vtable->buffer_relative_box_of_pos = buffer_relative_box_of_pos;
|
vtable->buffer_relative_box_of_pos = buffer_relative_box_of_pos;
|
||||||
vtable->buffer_padded_box_of_pos = buffer_padded_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_relative_character_from_pos = buffer_relative_character_from_pos;
|
||||||
vtable->buffer_pos_from_relative_character = buffer_pos_from_relative_character;
|
vtable->buffer_pos_from_relative_character = buffer_pos_from_relative_character;
|
||||||
vtable->view_line_y_difference = view_line_y_difference;
|
vtable->view_line_y_difference = view_line_y_difference;
|
||||||
vtable->view_line_shift_y = view_line_shift_y;
|
vtable->view_line_shift_y = view_line_shift_y;
|
||||||
vtable->view_pos_at_relative_xy = view_pos_at_relative_xy;
|
vtable->view_pos_at_relative_xy = view_pos_at_relative_xy;
|
||||||
vtable->view_relative_box_of_pos = view_relative_box_of_pos;
|
vtable->view_relative_box_of_pos = view_relative_box_of_pos;
|
||||||
vtable->view_padded_box_of_pos = view_padded_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_relative_character_from_pos = view_relative_character_from_pos;
|
||||||
vtable->view_pos_from_relative_character = view_pos_from_relative_character;
|
vtable->view_pos_from_relative_character = view_pos_from_relative_character;
|
||||||
vtable->buffer_exists = buffer_exists;
|
vtable->buffer_exists = buffer_exists;
|
||||||
vtable->buffer_get_access_flags = buffer_get_access_flags;
|
vtable->buffer_get_access_flags = buffer_get_access_flags;
|
||||||
vtable->buffer_get_size = buffer_get_size;
|
vtable->buffer_get_size = buffer_get_size;
|
||||||
vtable->buffer_get_line_count = buffer_get_line_count;
|
vtable->buffer_get_line_count = buffer_get_line_count;
|
||||||
vtable->push_buffer_base_name = push_buffer_base_name;
|
vtable->push_buffer_base_name = push_buffer_base_name;
|
||||||
vtable->push_buffer_unique_name = push_buffer_unique_name;
|
vtable->push_buffer_unique_name = push_buffer_unique_name;
|
||||||
vtable->push_buffer_file_name = push_buffer_file_name;
|
vtable->push_buffer_file_name = push_buffer_file_name;
|
||||||
vtable->buffer_get_dirty_state = buffer_get_dirty_state;
|
vtable->buffer_get_dirty_state = buffer_get_dirty_state;
|
||||||
vtable->buffer_set_dirty_state = buffer_set_dirty_state;
|
vtable->buffer_set_dirty_state = buffer_set_dirty_state;
|
||||||
vtable->buffer_set_layout = buffer_set_layout;
|
vtable->buffer_set_layout = buffer_set_layout;
|
||||||
vtable->buffer_clear_layout_cache = buffer_clear_layout_cache;
|
vtable->buffer_clear_layout_cache = buffer_clear_layout_cache;
|
||||||
vtable->buffer_get_layout = buffer_get_layout;
|
vtable->buffer_get_layout = buffer_get_layout;
|
||||||
vtable->buffer_get_setting = buffer_get_setting;
|
vtable->buffer_get_setting = buffer_get_setting;
|
||||||
vtable->buffer_set_setting = buffer_set_setting;
|
vtable->buffer_set_setting = buffer_set_setting;
|
||||||
vtable->buffer_get_managed_scope = buffer_get_managed_scope;
|
vtable->buffer_get_managed_scope = buffer_get_managed_scope;
|
||||||
vtable->buffer_send_end_signal = buffer_send_end_signal;
|
vtable->buffer_send_end_signal = buffer_send_end_signal;
|
||||||
vtable->create_buffer = create_buffer;
|
vtable->create_buffer = create_buffer;
|
||||||
vtable->buffer_save = buffer_save;
|
vtable->buffer_save = buffer_save;
|
||||||
vtable->buffer_kill = buffer_kill;
|
vtable->buffer_kill = buffer_kill;
|
||||||
vtable->buffer_reopen = buffer_reopen;
|
vtable->buffer_reopen = buffer_reopen;
|
||||||
vtable->buffer_get_file_attributes = buffer_get_file_attributes;
|
vtable->buffer_get_file_attributes = buffer_get_file_attributes;
|
||||||
vtable->get_view_next = get_view_next;
|
vtable->get_view_next = get_view_next;
|
||||||
vtable->get_view_prev = get_view_prev;
|
vtable->get_view_prev = get_view_prev;
|
||||||
vtable->get_this_ctx_view = get_this_ctx_view;
|
vtable->get_this_ctx_view = get_this_ctx_view;
|
||||||
vtable->get_active_view = get_active_view;
|
vtable->get_active_view = get_active_view;
|
||||||
vtable->view_exists = view_exists;
|
vtable->view_exists = view_exists;
|
||||||
vtable->view_get_buffer = view_get_buffer;
|
vtable->view_get_buffer = view_get_buffer;
|
||||||
vtable->view_get_cursor_pos = view_get_cursor_pos;
|
vtable->view_get_cursor_pos = view_get_cursor_pos;
|
||||||
vtable->view_get_mark_pos = view_get_mark_pos;
|
vtable->view_get_mark_pos = view_get_mark_pos;
|
||||||
vtable->view_get_preferred_x = view_get_preferred_x;
|
vtable->view_get_preferred_x = view_get_preferred_x;
|
||||||
vtable->view_set_preferred_x = view_set_preferred_x;
|
vtable->view_set_preferred_x = view_set_preferred_x;
|
||||||
vtable->view_get_screen_rect = view_get_screen_rect;
|
vtable->view_get_screen_rect = view_get_screen_rect;
|
||||||
vtable->view_get_panel = view_get_panel;
|
vtable->view_get_panel = view_get_panel;
|
||||||
vtable->panel_get_view = panel_get_view;
|
vtable->panel_get_view = panel_get_view;
|
||||||
vtable->panel_is_split = panel_is_split;
|
vtable->panel_is_split = panel_is_split;
|
||||||
vtable->panel_is_leaf = panel_is_leaf;
|
vtable->panel_is_leaf = panel_is_leaf;
|
||||||
vtable->panel_split = panel_split;
|
vtable->panel_split = panel_split;
|
||||||
vtable->panel_set_split = panel_set_split;
|
vtable->panel_set_split = panel_set_split;
|
||||||
vtable->panel_swap_children = panel_swap_children;
|
vtable->panel_swap_children = panel_swap_children;
|
||||||
vtable->panel_get_root = panel_get_root;
|
vtable->panel_get_root = panel_get_root;
|
||||||
vtable->panel_get_parent = panel_get_parent;
|
vtable->panel_get_parent = panel_get_parent;
|
||||||
vtable->panel_get_child = panel_get_child;
|
vtable->panel_get_child = panel_get_child;
|
||||||
vtable->view_close = view_close;
|
vtable->view_close = view_close;
|
||||||
vtable->view_get_buffer_region = view_get_buffer_region;
|
vtable->view_get_buffer_region = view_get_buffer_region;
|
||||||
vtable->view_get_buffer_scroll = view_get_buffer_scroll;
|
vtable->view_get_buffer_scroll = view_get_buffer_scroll;
|
||||||
vtable->view_set_active = view_set_active;
|
vtable->view_set_active = view_set_active;
|
||||||
vtable->view_enqueue_command_function = view_enqueue_command_function;
|
vtable->view_enqueue_command_function = view_enqueue_command_function;
|
||||||
vtable->view_get_setting = view_get_setting;
|
vtable->view_get_setting = view_get_setting;
|
||||||
vtable->view_set_setting = view_set_setting;
|
vtable->view_set_setting = view_set_setting;
|
||||||
vtable->view_get_managed_scope = view_get_managed_scope;
|
vtable->view_get_managed_scope = view_get_managed_scope;
|
||||||
vtable->buffer_compute_cursor = buffer_compute_cursor;
|
vtable->buffer_compute_cursor = buffer_compute_cursor;
|
||||||
vtable->view_compute_cursor = view_compute_cursor;
|
vtable->view_compute_cursor = view_compute_cursor;
|
||||||
vtable->view_set_camera_bounds = view_set_camera_bounds;
|
vtable->view_set_camera_bounds = view_set_camera_bounds;
|
||||||
vtable->view_get_camera_bounds = view_get_camera_bounds;
|
vtable->view_get_camera_bounds = view_get_camera_bounds;
|
||||||
vtable->view_set_cursor = view_set_cursor;
|
vtable->view_set_cursor = view_set_cursor;
|
||||||
vtable->view_set_buffer_scroll = view_set_buffer_scroll;
|
vtable->view_set_buffer_scroll = view_set_buffer_scroll;
|
||||||
vtable->view_set_mark = view_set_mark;
|
vtable->view_set_mark = view_set_mark;
|
||||||
vtable->view_quit_ui = view_quit_ui;
|
vtable->view_quit_ui = view_quit_ui;
|
||||||
vtable->view_set_buffer = view_set_buffer;
|
vtable->view_set_buffer = view_set_buffer;
|
||||||
vtable->view_push_context = view_push_context;
|
vtable->view_push_context = view_push_context;
|
||||||
vtable->view_pop_context = view_pop_context;
|
vtable->view_pop_context = view_pop_context;
|
||||||
vtable->view_alter_context = view_alter_context;
|
vtable->view_alter_context = view_alter_context;
|
||||||
vtable->view_current_context = view_current_context;
|
vtable->view_current_context = view_current_context;
|
||||||
vtable->view_current_context_hook_memory = view_current_context_hook_memory;
|
vtable->view_current_context_hook_memory = view_current_context_hook_memory;
|
||||||
vtable->create_user_managed_scope = create_user_managed_scope;
|
vtable->create_user_managed_scope = create_user_managed_scope;
|
||||||
vtable->destroy_user_managed_scope = destroy_user_managed_scope;
|
vtable->destroy_user_managed_scope = destroy_user_managed_scope;
|
||||||
vtable->get_global_managed_scope = get_global_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->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_contents = managed_scope_clear_contents;
|
||||||
vtable->managed_scope_clear_self_all_dependent_scopes = managed_scope_clear_self_all_dependent_scopes;
|
vtable->managed_scope_clear_self_all_dependent_scopes = managed_scope_clear_self_all_dependent_scopes;
|
||||||
vtable->managed_scope_allocator = managed_scope_allocator;
|
vtable->managed_scope_allocator = managed_scope_allocator;
|
||||||
vtable->managed_id_group_highest_id = managed_id_group_highest_id;
|
vtable->managed_id_group_highest_id = managed_id_group_highest_id;
|
||||||
vtable->managed_id_declare = managed_id_declare;
|
vtable->managed_id_declare = managed_id_declare;
|
||||||
vtable->managed_id_get = managed_id_get;
|
vtable->managed_id_get = managed_id_get;
|
||||||
vtable->managed_scope_get_attachment = managed_scope_get_attachment;
|
vtable->managed_scope_get_attachment = managed_scope_get_attachment;
|
||||||
vtable->managed_scope_attachment_erase = managed_scope_attachment_erase;
|
vtable->managed_scope_attachment_erase = managed_scope_attachment_erase;
|
||||||
vtable->alloc_managed_memory_in_scope = alloc_managed_memory_in_scope;
|
vtable->alloc_managed_memory_in_scope = alloc_managed_memory_in_scope;
|
||||||
vtable->alloc_buffer_markers_on_buffer = alloc_buffer_markers_on_buffer;
|
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_size = managed_object_get_item_size;
|
||||||
vtable->managed_object_get_item_count = managed_object_get_item_count;
|
vtable->managed_object_get_item_count = managed_object_get_item_count;
|
||||||
vtable->managed_object_get_pointer = managed_object_get_pointer;
|
vtable->managed_object_get_pointer = managed_object_get_pointer;
|
||||||
vtable->managed_object_get_type = managed_object_get_type;
|
vtable->managed_object_get_type = managed_object_get_type;
|
||||||
vtable->managed_object_get_containing_scope = managed_object_get_containing_scope;
|
vtable->managed_object_get_containing_scope = managed_object_get_containing_scope;
|
||||||
vtable->managed_object_free = managed_object_free;
|
vtable->managed_object_free = managed_object_free;
|
||||||
vtable->managed_object_store_data = managed_object_store_data;
|
vtable->managed_object_store_data = managed_object_store_data;
|
||||||
vtable->managed_object_load_data = managed_object_load_data;
|
vtable->managed_object_load_data = managed_object_load_data;
|
||||||
vtable->get_next_input_raw = get_next_input_raw;
|
vtable->get_next_input_raw = get_next_input_raw;
|
||||||
vtable->get_current_input_sequence_number = get_current_input_sequence_number;
|
vtable->get_current_input_sequence_number = get_current_input_sequence_number;
|
||||||
vtable->get_current_input = get_current_input;
|
vtable->get_current_input = get_current_input;
|
||||||
vtable->set_current_input = set_current_input;
|
vtable->set_current_input = set_current_input;
|
||||||
vtable->leave_current_input_unhandled = leave_current_input_unhandled;
|
vtable->leave_current_input_unhandled = leave_current_input_unhandled;
|
||||||
vtable->set_custom_hook = set_custom_hook;
|
vtable->set_custom_hook = set_custom_hook;
|
||||||
vtable->get_custom_hook = get_custom_hook;
|
vtable->get_custom_hook = get_custom_hook;
|
||||||
vtable->set_custom_hook_memory_size = set_custom_hook_memory_size;
|
vtable->set_custom_hook_memory_size = set_custom_hook_memory_size;
|
||||||
vtable->get_mouse_state = get_mouse_state;
|
vtable->get_mouse_state = get_mouse_state;
|
||||||
vtable->get_active_query_bars = get_active_query_bars;
|
vtable->get_active_query_bars = get_active_query_bars;
|
||||||
vtable->start_query_bar = start_query_bar;
|
vtable->start_query_bar = start_query_bar;
|
||||||
vtable->end_query_bar = end_query_bar;
|
vtable->end_query_bar = end_query_bar;
|
||||||
vtable->clear_all_query_bars = clear_all_query_bars;
|
vtable->clear_all_query_bars = clear_all_query_bars;
|
||||||
vtable->print_message = print_message;
|
vtable->print_message = print_message;
|
||||||
vtable->log_string = log_string;
|
vtable->log_string = log_string;
|
||||||
vtable->get_largest_face_id = get_largest_face_id;
|
vtable->get_largest_face_id = get_largest_face_id;
|
||||||
vtable->set_global_face = set_global_face;
|
vtable->set_global_face = set_global_face;
|
||||||
vtable->buffer_history_get_max_record_index = buffer_history_get_max_record_index;
|
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_record_info = buffer_history_get_record_info;
|
||||||
vtable->buffer_history_get_group_sub_record = buffer_history_get_group_sub_record;
|
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_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_set_current_state_index = buffer_history_set_current_state_index;
|
||||||
vtable->buffer_history_merge_record_range = buffer_history_merge_record_range;
|
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->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_begin = global_history_edit_group_begin;
|
||||||
vtable->global_history_edit_group_end = global_history_edit_group_end;
|
vtable->global_history_edit_group_end = global_history_edit_group_end;
|
||||||
vtable->buffer_set_face = buffer_set_face;
|
vtable->buffer_set_face = buffer_set_face;
|
||||||
vtable->get_face_description = get_face_description;
|
vtable->get_face_description = get_face_description;
|
||||||
vtable->get_face_metrics = get_face_metrics;
|
vtable->get_face_metrics = get_face_metrics;
|
||||||
vtable->get_face_advance_map = get_face_advance_map;
|
vtable->get_face_advance_map = get_face_advance_map;
|
||||||
vtable->get_face_id = get_face_id;
|
vtable->get_face_id = get_face_id;
|
||||||
vtable->try_create_new_face = try_create_new_face;
|
vtable->try_create_new_face = try_create_new_face;
|
||||||
vtable->try_modify_face = try_modify_face;
|
vtable->try_modify_face = try_modify_face;
|
||||||
vtable->try_release_face = try_release_face;
|
vtable->try_release_face = try_release_face;
|
||||||
vtable->push_hot_directory = push_hot_directory;
|
vtable->push_hot_directory = push_hot_directory;
|
||||||
vtable->set_hot_directory = set_hot_directory;
|
vtable->set_hot_directory = set_hot_directory;
|
||||||
vtable->send_exit_signal = send_exit_signal;
|
vtable->send_exit_signal = send_exit_signal;
|
||||||
vtable->hard_exit = hard_exit;
|
vtable->hard_exit = hard_exit;
|
||||||
vtable->set_window_title = set_window_title;
|
vtable->set_window_title = set_window_title;
|
||||||
vtable->acquire_global_frame_mutex = acquire_global_frame_mutex;
|
vtable->acquire_global_frame_mutex = acquire_global_frame_mutex;
|
||||||
vtable->release_global_frame_mutex = release_global_frame_mutex;
|
vtable->release_global_frame_mutex = release_global_frame_mutex;
|
||||||
vtable->draw_string_oriented = draw_string_oriented;
|
vtable->draw_string_oriented = draw_string_oriented;
|
||||||
vtable->get_string_advance = get_string_advance;
|
vtable->get_string_advance = get_string_advance;
|
||||||
vtable->draw_rectangle = draw_rectangle;
|
vtable->draw_rectangle = draw_rectangle;
|
||||||
vtable->draw_rectangle_outline = draw_rectangle_outline;
|
vtable->draw_rectangle_outline = draw_rectangle_outline;
|
||||||
vtable->draw_set_clip = draw_set_clip;
|
vtable->draw_set_clip = draw_set_clip;
|
||||||
vtable->text_layout_create = text_layout_create;
|
vtable->text_layout_create = text_layout_create;
|
||||||
vtable->text_layout_region = text_layout_region;
|
vtable->text_layout_region = text_layout_region;
|
||||||
vtable->text_layout_get_buffer = text_layout_get_buffer;
|
vtable->text_layout_get_buffer = text_layout_get_buffer;
|
||||||
vtable->text_layout_get_visible_range = text_layout_get_visible_range;
|
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_line_on_screen = text_layout_line_on_screen;
|
||||||
vtable->text_layout_character_on_screen = text_layout_character_on_screen;
|
vtable->text_layout_character_on_screen = text_layout_character_on_screen;
|
||||||
vtable->paint_text_color = paint_text_color;
|
vtable->paint_text_color = paint_text_color;
|
||||||
vtable->paint_text_color_blend = paint_text_color_blend;
|
vtable->paint_text_color_blend = paint_text_color_blend;
|
||||||
vtable->text_layout_free = text_layout_free;
|
vtable->text_layout_free = text_layout_free;
|
||||||
vtable->draw_text_layout = draw_text_layout;
|
vtable->draw_text_layout = draw_text_layout;
|
||||||
vtable->open_color_picker = open_color_picker;
|
vtable->open_color_picker = open_color_picker;
|
||||||
vtable->animate_in_n_milliseconds = animate_in_n_milliseconds;
|
vtable->animate_in_n_milliseconds = animate_in_n_milliseconds;
|
||||||
vtable->buffer_find_all_matches = buffer_find_all_matches;
|
vtable->buffer_find_all_matches = buffer_find_all_matches;
|
||||||
vtable->get_core_profile_list = get_core_profile_list;
|
vtable->get_core_profile_list = get_core_profile_list;
|
||||||
vtable->get_custom_layer_boundary_docs = get_custom_layer_boundary_docs;
|
vtable->get_custom_layer_boundary_docs = get_custom_layer_boundary_docs;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DYNAMIC_LINK_API)
|
#if defined(DYNAMIC_LINK_API)
|
||||||
function void
|
function void
|
||||||
custom_api_read_vtable(API_VTable_custom *vtable){
|
custom_api_read_vtable(API_VTable_custom *vtable){
|
||||||
global_set_setting = vtable->global_set_setting;
|
global_set_setting = vtable->global_set_setting;
|
||||||
global_get_screen_rectangle = vtable->global_get_screen_rectangle;
|
global_get_screen_rectangle = vtable->global_get_screen_rectangle;
|
||||||
get_thread_context = vtable->get_thread_context;
|
get_thread_context = vtable->get_thread_context;
|
||||||
create_child_process = vtable->create_child_process;
|
create_child_process = vtable->create_child_process;
|
||||||
child_process_set_target_buffer = vtable->child_process_set_target_buffer;
|
child_process_set_target_buffer = vtable->child_process_set_target_buffer;
|
||||||
buffer_get_attached_child_process = vtable->buffer_get_attached_child_process;
|
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_attached_buffer = vtable->child_process_get_attached_buffer;
|
||||||
child_process_get_state = vtable->child_process_get_state;
|
child_process_get_state = vtable->child_process_get_state;
|
||||||
enqueue_virtual_event = vtable->enqueue_virtual_event;
|
enqueue_virtual_event = vtable->enqueue_virtual_event;
|
||||||
get_buffer_count = vtable->get_buffer_count;
|
get_buffer_count = vtable->get_buffer_count;
|
||||||
get_buffer_next = vtable->get_buffer_next;
|
get_buffer_next = vtable->get_buffer_next;
|
||||||
get_buffer_by_name = vtable->get_buffer_by_name;
|
get_buffer_by_name = vtable->get_buffer_by_name;
|
||||||
get_buffer_by_file_name = vtable->get_buffer_by_file_name;
|
get_buffer_by_file_name = vtable->get_buffer_by_file_name;
|
||||||
buffer_read_range = vtable->buffer_read_range;
|
buffer_read_range = vtable->buffer_read_range;
|
||||||
buffer_replace_range = vtable->buffer_replace_range;
|
buffer_replace_range = vtable->buffer_replace_range;
|
||||||
buffer_batch_edit = vtable->buffer_batch_edit;
|
buffer_batch_edit = vtable->buffer_batch_edit;
|
||||||
buffer_seek_string = vtable->buffer_seek_string;
|
buffer_seek_string = vtable->buffer_seek_string;
|
||||||
buffer_seek_character_class = vtable->buffer_seek_character_class;
|
buffer_seek_character_class = vtable->buffer_seek_character_class;
|
||||||
buffer_line_y_difference = vtable->buffer_line_y_difference;
|
buffer_line_y_difference = vtable->buffer_line_y_difference;
|
||||||
buffer_line_shift_y = vtable->buffer_line_shift_y;
|
buffer_line_shift_y = vtable->buffer_line_shift_y;
|
||||||
buffer_pos_at_relative_xy = vtable->buffer_pos_at_relative_xy;
|
buffer_pos_at_relative_xy = vtable->buffer_pos_at_relative_xy;
|
||||||
buffer_relative_box_of_pos = vtable->buffer_relative_box_of_pos;
|
buffer_relative_box_of_pos = vtable->buffer_relative_box_of_pos;
|
||||||
buffer_padded_box_of_pos = vtable->buffer_padded_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_relative_character_from_pos = vtable->buffer_relative_character_from_pos;
|
||||||
buffer_pos_from_relative_character = vtable->buffer_pos_from_relative_character;
|
buffer_pos_from_relative_character = vtable->buffer_pos_from_relative_character;
|
||||||
view_line_y_difference = vtable->view_line_y_difference;
|
view_line_y_difference = vtable->view_line_y_difference;
|
||||||
view_line_shift_y = vtable->view_line_shift_y;
|
view_line_shift_y = vtable->view_line_shift_y;
|
||||||
view_pos_at_relative_xy = vtable->view_pos_at_relative_xy;
|
view_pos_at_relative_xy = vtable->view_pos_at_relative_xy;
|
||||||
view_relative_box_of_pos = vtable->view_relative_box_of_pos;
|
view_relative_box_of_pos = vtable->view_relative_box_of_pos;
|
||||||
view_padded_box_of_pos = vtable->view_padded_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_relative_character_from_pos = vtable->view_relative_character_from_pos;
|
||||||
view_pos_from_relative_character = vtable->view_pos_from_relative_character;
|
view_pos_from_relative_character = vtable->view_pos_from_relative_character;
|
||||||
buffer_exists = vtable->buffer_exists;
|
buffer_exists = vtable->buffer_exists;
|
||||||
buffer_get_access_flags = vtable->buffer_get_access_flags;
|
buffer_get_access_flags = vtable->buffer_get_access_flags;
|
||||||
buffer_get_size = vtable->buffer_get_size;
|
buffer_get_size = vtable->buffer_get_size;
|
||||||
buffer_get_line_count = vtable->buffer_get_line_count;
|
buffer_get_line_count = vtable->buffer_get_line_count;
|
||||||
push_buffer_base_name = vtable->push_buffer_base_name;
|
push_buffer_base_name = vtable->push_buffer_base_name;
|
||||||
push_buffer_unique_name = vtable->push_buffer_unique_name;
|
push_buffer_unique_name = vtable->push_buffer_unique_name;
|
||||||
push_buffer_file_name = vtable->push_buffer_file_name;
|
push_buffer_file_name = vtable->push_buffer_file_name;
|
||||||
buffer_get_dirty_state = vtable->buffer_get_dirty_state;
|
buffer_get_dirty_state = vtable->buffer_get_dirty_state;
|
||||||
buffer_set_dirty_state = vtable->buffer_set_dirty_state;
|
buffer_set_dirty_state = vtable->buffer_set_dirty_state;
|
||||||
buffer_set_layout = vtable->buffer_set_layout;
|
buffer_set_layout = vtable->buffer_set_layout;
|
||||||
buffer_clear_layout_cache = vtable->buffer_clear_layout_cache;
|
buffer_clear_layout_cache = vtable->buffer_clear_layout_cache;
|
||||||
buffer_get_layout = vtable->buffer_get_layout;
|
buffer_get_layout = vtable->buffer_get_layout;
|
||||||
buffer_get_setting = vtable->buffer_get_setting;
|
buffer_get_setting = vtable->buffer_get_setting;
|
||||||
buffer_set_setting = vtable->buffer_set_setting;
|
buffer_set_setting = vtable->buffer_set_setting;
|
||||||
buffer_get_managed_scope = vtable->buffer_get_managed_scope;
|
buffer_get_managed_scope = vtable->buffer_get_managed_scope;
|
||||||
buffer_send_end_signal = vtable->buffer_send_end_signal;
|
buffer_send_end_signal = vtable->buffer_send_end_signal;
|
||||||
create_buffer = vtable->create_buffer;
|
create_buffer = vtable->create_buffer;
|
||||||
buffer_save = vtable->buffer_save;
|
buffer_save = vtable->buffer_save;
|
||||||
buffer_kill = vtable->buffer_kill;
|
buffer_kill = vtable->buffer_kill;
|
||||||
buffer_reopen = vtable->buffer_reopen;
|
buffer_reopen = vtable->buffer_reopen;
|
||||||
buffer_get_file_attributes = vtable->buffer_get_file_attributes;
|
buffer_get_file_attributes = vtable->buffer_get_file_attributes;
|
||||||
get_view_next = vtable->get_view_next;
|
get_view_next = vtable->get_view_next;
|
||||||
get_view_prev = vtable->get_view_prev;
|
get_view_prev = vtable->get_view_prev;
|
||||||
get_this_ctx_view = vtable->get_this_ctx_view;
|
get_this_ctx_view = vtable->get_this_ctx_view;
|
||||||
get_active_view = vtable->get_active_view;
|
get_active_view = vtable->get_active_view;
|
||||||
view_exists = vtable->view_exists;
|
view_exists = vtable->view_exists;
|
||||||
view_get_buffer = vtable->view_get_buffer;
|
view_get_buffer = vtable->view_get_buffer;
|
||||||
view_get_cursor_pos = vtable->view_get_cursor_pos;
|
view_get_cursor_pos = vtable->view_get_cursor_pos;
|
||||||
view_get_mark_pos = vtable->view_get_mark_pos;
|
view_get_mark_pos = vtable->view_get_mark_pos;
|
||||||
view_get_preferred_x = vtable->view_get_preferred_x;
|
view_get_preferred_x = vtable->view_get_preferred_x;
|
||||||
view_set_preferred_x = vtable->view_set_preferred_x;
|
view_set_preferred_x = vtable->view_set_preferred_x;
|
||||||
view_get_screen_rect = vtable->view_get_screen_rect;
|
view_get_screen_rect = vtable->view_get_screen_rect;
|
||||||
view_get_panel = vtable->view_get_panel;
|
view_get_panel = vtable->view_get_panel;
|
||||||
panel_get_view = vtable->panel_get_view;
|
panel_get_view = vtable->panel_get_view;
|
||||||
panel_is_split = vtable->panel_is_split;
|
panel_is_split = vtable->panel_is_split;
|
||||||
panel_is_leaf = vtable->panel_is_leaf;
|
panel_is_leaf = vtable->panel_is_leaf;
|
||||||
panel_split = vtable->panel_split;
|
panel_split = vtable->panel_split;
|
||||||
panel_set_split = vtable->panel_set_split;
|
panel_set_split = vtable->panel_set_split;
|
||||||
panel_swap_children = vtable->panel_swap_children;
|
panel_swap_children = vtable->panel_swap_children;
|
||||||
panel_get_root = vtable->panel_get_root;
|
panel_get_root = vtable->panel_get_root;
|
||||||
panel_get_parent = vtable->panel_get_parent;
|
panel_get_parent = vtable->panel_get_parent;
|
||||||
panel_get_child = vtable->panel_get_child;
|
panel_get_child = vtable->panel_get_child;
|
||||||
view_close = vtable->view_close;
|
view_close = vtable->view_close;
|
||||||
view_get_buffer_region = vtable->view_get_buffer_region;
|
view_get_buffer_region = vtable->view_get_buffer_region;
|
||||||
view_get_buffer_scroll = vtable->view_get_buffer_scroll;
|
view_get_buffer_scroll = vtable->view_get_buffer_scroll;
|
||||||
view_set_active = vtable->view_set_active;
|
view_set_active = vtable->view_set_active;
|
||||||
view_enqueue_command_function = vtable->view_enqueue_command_function;
|
view_enqueue_command_function = vtable->view_enqueue_command_function;
|
||||||
view_get_setting = vtable->view_get_setting;
|
view_get_setting = vtable->view_get_setting;
|
||||||
view_set_setting = vtable->view_set_setting;
|
view_set_setting = vtable->view_set_setting;
|
||||||
view_get_managed_scope = vtable->view_get_managed_scope;
|
view_get_managed_scope = vtable->view_get_managed_scope;
|
||||||
buffer_compute_cursor = vtable->buffer_compute_cursor;
|
buffer_compute_cursor = vtable->buffer_compute_cursor;
|
||||||
view_compute_cursor = vtable->view_compute_cursor;
|
view_compute_cursor = vtable->view_compute_cursor;
|
||||||
view_set_camera_bounds = vtable->view_set_camera_bounds;
|
view_set_camera_bounds = vtable->view_set_camera_bounds;
|
||||||
view_get_camera_bounds = vtable->view_get_camera_bounds;
|
view_get_camera_bounds = vtable->view_get_camera_bounds;
|
||||||
view_set_cursor = vtable->view_set_cursor;
|
view_set_cursor = vtable->view_set_cursor;
|
||||||
view_set_buffer_scroll = vtable->view_set_buffer_scroll;
|
view_set_buffer_scroll = vtable->view_set_buffer_scroll;
|
||||||
view_set_mark = vtable->view_set_mark;
|
view_set_mark = vtable->view_set_mark;
|
||||||
view_quit_ui = vtable->view_quit_ui;
|
view_quit_ui = vtable->view_quit_ui;
|
||||||
view_set_buffer = vtable->view_set_buffer;
|
view_set_buffer = vtable->view_set_buffer;
|
||||||
view_push_context = vtable->view_push_context;
|
view_push_context = vtable->view_push_context;
|
||||||
view_pop_context = vtable->view_pop_context;
|
view_pop_context = vtable->view_pop_context;
|
||||||
view_alter_context = vtable->view_alter_context;
|
view_alter_context = vtable->view_alter_context;
|
||||||
view_current_context = vtable->view_current_context;
|
view_current_context = vtable->view_current_context;
|
||||||
view_current_context_hook_memory = vtable->view_current_context_hook_memory;
|
view_current_context_hook_memory = vtable->view_current_context_hook_memory;
|
||||||
create_user_managed_scope = vtable->create_user_managed_scope;
|
create_user_managed_scope = vtable->create_user_managed_scope;
|
||||||
destroy_user_managed_scope = vtable->destroy_user_managed_scope;
|
destroy_user_managed_scope = vtable->destroy_user_managed_scope;
|
||||||
get_global_managed_scope = vtable->get_global_managed_scope;
|
get_global_managed_scope = vtable->get_global_managed_scope;
|
||||||
get_managed_scope_with_multiple_dependencies = vtable->get_managed_scope_with_multiple_dependencies;
|
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_contents = vtable->managed_scope_clear_contents;
|
||||||
managed_scope_clear_self_all_dependent_scopes = vtable->managed_scope_clear_self_all_dependent_scopes;
|
managed_scope_clear_self_all_dependent_scopes = vtable->managed_scope_clear_self_all_dependent_scopes;
|
||||||
managed_scope_allocator = vtable->managed_scope_allocator;
|
managed_scope_allocator = vtable->managed_scope_allocator;
|
||||||
managed_id_group_highest_id = vtable->managed_id_group_highest_id;
|
managed_id_group_highest_id = vtable->managed_id_group_highest_id;
|
||||||
managed_id_declare = vtable->managed_id_declare;
|
managed_id_declare = vtable->managed_id_declare;
|
||||||
managed_id_get = vtable->managed_id_get;
|
managed_id_get = vtable->managed_id_get;
|
||||||
managed_scope_get_attachment = vtable->managed_scope_get_attachment;
|
managed_scope_get_attachment = vtable->managed_scope_get_attachment;
|
||||||
managed_scope_attachment_erase = vtable->managed_scope_attachment_erase;
|
managed_scope_attachment_erase = vtable->managed_scope_attachment_erase;
|
||||||
alloc_managed_memory_in_scope = vtable->alloc_managed_memory_in_scope;
|
alloc_managed_memory_in_scope = vtable->alloc_managed_memory_in_scope;
|
||||||
alloc_buffer_markers_on_buffer = vtable->alloc_buffer_markers_on_buffer;
|
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_size = vtable->managed_object_get_item_size;
|
||||||
managed_object_get_item_count = vtable->managed_object_get_item_count;
|
managed_object_get_item_count = vtable->managed_object_get_item_count;
|
||||||
managed_object_get_pointer = vtable->managed_object_get_pointer;
|
managed_object_get_pointer = vtable->managed_object_get_pointer;
|
||||||
managed_object_get_type = vtable->managed_object_get_type;
|
managed_object_get_type = vtable->managed_object_get_type;
|
||||||
managed_object_get_containing_scope = vtable->managed_object_get_containing_scope;
|
managed_object_get_containing_scope = vtable->managed_object_get_containing_scope;
|
||||||
managed_object_free = vtable->managed_object_free;
|
managed_object_free = vtable->managed_object_free;
|
||||||
managed_object_store_data = vtable->managed_object_store_data;
|
managed_object_store_data = vtable->managed_object_store_data;
|
||||||
managed_object_load_data = vtable->managed_object_load_data;
|
managed_object_load_data = vtable->managed_object_load_data;
|
||||||
get_next_input_raw = vtable->get_next_input_raw;
|
get_next_input_raw = vtable->get_next_input_raw;
|
||||||
get_current_input_sequence_number = vtable->get_current_input_sequence_number;
|
get_current_input_sequence_number = vtable->get_current_input_sequence_number;
|
||||||
get_current_input = vtable->get_current_input;
|
get_current_input = vtable->get_current_input;
|
||||||
set_current_input = vtable->set_current_input;
|
set_current_input = vtable->set_current_input;
|
||||||
leave_current_input_unhandled = vtable->leave_current_input_unhandled;
|
leave_current_input_unhandled = vtable->leave_current_input_unhandled;
|
||||||
set_custom_hook = vtable->set_custom_hook;
|
set_custom_hook = vtable->set_custom_hook;
|
||||||
get_custom_hook = vtable->get_custom_hook;
|
get_custom_hook = vtable->get_custom_hook;
|
||||||
set_custom_hook_memory_size = vtable->set_custom_hook_memory_size;
|
set_custom_hook_memory_size = vtable->set_custom_hook_memory_size;
|
||||||
get_mouse_state = vtable->get_mouse_state;
|
get_mouse_state = vtable->get_mouse_state;
|
||||||
get_active_query_bars = vtable->get_active_query_bars;
|
get_active_query_bars = vtable->get_active_query_bars;
|
||||||
start_query_bar = vtable->start_query_bar;
|
start_query_bar = vtable->start_query_bar;
|
||||||
end_query_bar = vtable->end_query_bar;
|
end_query_bar = vtable->end_query_bar;
|
||||||
clear_all_query_bars = vtable->clear_all_query_bars;
|
clear_all_query_bars = vtable->clear_all_query_bars;
|
||||||
print_message = vtable->print_message;
|
print_message = vtable->print_message;
|
||||||
log_string = vtable->log_string;
|
log_string = vtable->log_string;
|
||||||
get_largest_face_id = vtable->get_largest_face_id;
|
get_largest_face_id = vtable->get_largest_face_id;
|
||||||
set_global_face = vtable->set_global_face;
|
set_global_face = vtable->set_global_face;
|
||||||
buffer_history_get_max_record_index = vtable->buffer_history_get_max_record_index;
|
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_record_info = vtable->buffer_history_get_record_info;
|
||||||
buffer_history_get_group_sub_record = vtable->buffer_history_get_group_sub_record;
|
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_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_set_current_state_index = vtable->buffer_history_set_current_state_index;
|
||||||
buffer_history_merge_record_range = vtable->buffer_history_merge_record_range;
|
buffer_history_merge_record_range = vtable->buffer_history_merge_record_range;
|
||||||
buffer_history_clear_after_current_state = vtable->buffer_history_clear_after_current_state;
|
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_begin = vtable->global_history_edit_group_begin;
|
||||||
global_history_edit_group_end = vtable->global_history_edit_group_end;
|
global_history_edit_group_end = vtable->global_history_edit_group_end;
|
||||||
buffer_set_face = vtable->buffer_set_face;
|
buffer_set_face = vtable->buffer_set_face;
|
||||||
get_face_description = vtable->get_face_description;
|
get_face_description = vtable->get_face_description;
|
||||||
get_face_metrics = vtable->get_face_metrics;
|
get_face_metrics = vtable->get_face_metrics;
|
||||||
get_face_advance_map = vtable->get_face_advance_map;
|
get_face_advance_map = vtable->get_face_advance_map;
|
||||||
get_face_id = vtable->get_face_id;
|
get_face_id = vtable->get_face_id;
|
||||||
try_create_new_face = vtable->try_create_new_face;
|
try_create_new_face = vtable->try_create_new_face;
|
||||||
try_modify_face = vtable->try_modify_face;
|
try_modify_face = vtable->try_modify_face;
|
||||||
try_release_face = vtable->try_release_face;
|
try_release_face = vtable->try_release_face;
|
||||||
push_hot_directory = vtable->push_hot_directory;
|
push_hot_directory = vtable->push_hot_directory;
|
||||||
set_hot_directory = vtable->set_hot_directory;
|
set_hot_directory = vtable->set_hot_directory;
|
||||||
send_exit_signal = vtable->send_exit_signal;
|
send_exit_signal = vtable->send_exit_signal;
|
||||||
hard_exit = vtable->hard_exit;
|
hard_exit = vtable->hard_exit;
|
||||||
set_window_title = vtable->set_window_title;
|
set_window_title = vtable->set_window_title;
|
||||||
acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
|
acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
|
||||||
release_global_frame_mutex = vtable->release_global_frame_mutex;
|
release_global_frame_mutex = vtable->release_global_frame_mutex;
|
||||||
draw_string_oriented = vtable->draw_string_oriented;
|
draw_string_oriented = vtable->draw_string_oriented;
|
||||||
get_string_advance = vtable->get_string_advance;
|
get_string_advance = vtable->get_string_advance;
|
||||||
draw_rectangle = vtable->draw_rectangle;
|
draw_rectangle = vtable->draw_rectangle;
|
||||||
draw_rectangle_outline = vtable->draw_rectangle_outline;
|
draw_rectangle_outline = vtable->draw_rectangle_outline;
|
||||||
draw_set_clip = vtable->draw_set_clip;
|
draw_set_clip = vtable->draw_set_clip;
|
||||||
text_layout_create = vtable->text_layout_create;
|
text_layout_create = vtable->text_layout_create;
|
||||||
text_layout_region = vtable->text_layout_region;
|
text_layout_region = vtable->text_layout_region;
|
||||||
text_layout_get_buffer = vtable->text_layout_get_buffer;
|
text_layout_get_buffer = vtable->text_layout_get_buffer;
|
||||||
text_layout_get_visible_range = vtable->text_layout_get_visible_range;
|
text_layout_get_visible_range = vtable->text_layout_get_visible_range;
|
||||||
text_layout_line_on_screen = vtable->text_layout_line_on_screen;
|
text_layout_line_on_screen = vtable->text_layout_line_on_screen;
|
||||||
text_layout_character_on_screen = vtable->text_layout_character_on_screen;
|
text_layout_character_on_screen = vtable->text_layout_character_on_screen;
|
||||||
paint_text_color = vtable->paint_text_color;
|
paint_text_color = vtable->paint_text_color;
|
||||||
paint_text_color_blend = vtable->paint_text_color_blend;
|
paint_text_color_blend = vtable->paint_text_color_blend;
|
||||||
text_layout_free = vtable->text_layout_free;
|
text_layout_free = vtable->text_layout_free;
|
||||||
draw_text_layout = vtable->draw_text_layout;
|
draw_text_layout = vtable->draw_text_layout;
|
||||||
open_color_picker = vtable->open_color_picker;
|
open_color_picker = vtable->open_color_picker;
|
||||||
animate_in_n_milliseconds = vtable->animate_in_n_milliseconds;
|
animate_in_n_milliseconds = vtable->animate_in_n_milliseconds;
|
||||||
buffer_find_all_matches = vtable->buffer_find_all_matches;
|
buffer_find_all_matches = vtable->buffer_find_all_matches;
|
||||||
get_core_profile_list = vtable->get_core_profile_list;
|
get_core_profile_list = vtable->get_core_profile_list;
|
||||||
get_custom_layer_boundary_docs = vtable->get_custom_layer_boundary_docs;
|
get_custom_layer_boundary_docs = vtable->get_custom_layer_boundary_docs;
|
||||||
}
|
}
|
||||||
#undef DYNAMIC_LINK_API
|
#undef DYNAMIC_LINK_API
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* 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_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_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)
|
#define custom_get_thread_context_sig() Thread_Context* custom_get_thread_context(Application_Links* app)
|
||||||
|
@ -177,6 +179,7 @@
|
||||||
#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_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_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)
|
#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 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 Rect_f32 custom_global_get_screen_rectangle_type(Application_Links* app);
|
||||||
typedef Thread_Context* custom_get_thread_context_type(Application_Links* app);
|
typedef Thread_Context* custom_get_thread_context_type(Application_Links* app);
|
||||||
|
@ -356,187 +359,189 @@ 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 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 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);
|
typedef Doc_Cluster* custom_get_custom_layer_boundary_docs_type(Application_Links* app, Arena* arena);
|
||||||
|
|
||||||
struct API_VTable_custom{
|
struct API_VTable_custom{
|
||||||
custom_global_set_setting_type *global_set_setting;
|
custom_global_set_setting_type *global_set_setting;
|
||||||
custom_global_get_screen_rectangle_type *global_get_screen_rectangle;
|
custom_global_get_screen_rectangle_type *global_get_screen_rectangle;
|
||||||
custom_get_thread_context_type *get_thread_context;
|
custom_get_thread_context_type *get_thread_context;
|
||||||
custom_create_child_process_type *create_child_process;
|
custom_create_child_process_type *create_child_process;
|
||||||
custom_child_process_set_target_buffer_type *child_process_set_target_buffer;
|
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_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_attached_buffer_type *child_process_get_attached_buffer;
|
||||||
custom_child_process_get_state_type *child_process_get_state;
|
custom_child_process_get_state_type *child_process_get_state;
|
||||||
custom_enqueue_virtual_event_type *enqueue_virtual_event;
|
custom_enqueue_virtual_event_type *enqueue_virtual_event;
|
||||||
custom_get_buffer_count_type *get_buffer_count;
|
custom_get_buffer_count_type *get_buffer_count;
|
||||||
custom_get_buffer_next_type *get_buffer_next;
|
custom_get_buffer_next_type *get_buffer_next;
|
||||||
custom_get_buffer_by_name_type *get_buffer_by_name;
|
custom_get_buffer_by_name_type *get_buffer_by_name;
|
||||||
custom_get_buffer_by_file_name_type *get_buffer_by_file_name;
|
custom_get_buffer_by_file_name_type *get_buffer_by_file_name;
|
||||||
custom_buffer_read_range_type *buffer_read_range;
|
custom_buffer_read_range_type *buffer_read_range;
|
||||||
custom_buffer_replace_range_type *buffer_replace_range;
|
custom_buffer_replace_range_type *buffer_replace_range;
|
||||||
custom_buffer_batch_edit_type *buffer_batch_edit;
|
custom_buffer_batch_edit_type *buffer_batch_edit;
|
||||||
custom_buffer_seek_string_type *buffer_seek_string;
|
custom_buffer_seek_string_type *buffer_seek_string;
|
||||||
custom_buffer_seek_character_class_type *buffer_seek_character_class;
|
custom_buffer_seek_character_class_type *buffer_seek_character_class;
|
||||||
custom_buffer_line_y_difference_type *buffer_line_y_difference;
|
custom_buffer_line_y_difference_type *buffer_line_y_difference;
|
||||||
custom_buffer_line_shift_y_type *buffer_line_shift_y;
|
custom_buffer_line_shift_y_type *buffer_line_shift_y;
|
||||||
custom_buffer_pos_at_relative_xy_type *buffer_pos_at_relative_xy;
|
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_relative_box_of_pos_type *buffer_relative_box_of_pos;
|
||||||
custom_buffer_padded_box_of_pos_type *buffer_padded_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_relative_character_from_pos_type *buffer_relative_character_from_pos;
|
||||||
custom_buffer_pos_from_relative_character_type *buffer_pos_from_relative_character;
|
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_y_difference_type *view_line_y_difference;
|
||||||
custom_view_line_shift_y_type *view_line_shift_y;
|
custom_view_line_shift_y_type *view_line_shift_y;
|
||||||
custom_view_pos_at_relative_xy_type *view_pos_at_relative_xy;
|
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_relative_box_of_pos_type *view_relative_box_of_pos;
|
||||||
custom_view_padded_box_of_pos_type *view_padded_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_relative_character_from_pos_type *view_relative_character_from_pos;
|
||||||
custom_view_pos_from_relative_character_type *view_pos_from_relative_character;
|
custom_view_pos_from_relative_character_type *view_pos_from_relative_character;
|
||||||
custom_buffer_exists_type *buffer_exists;
|
custom_buffer_exists_type *buffer_exists;
|
||||||
custom_buffer_get_access_flags_type *buffer_get_access_flags;
|
custom_buffer_get_access_flags_type *buffer_get_access_flags;
|
||||||
custom_buffer_get_size_type *buffer_get_size;
|
custom_buffer_get_size_type *buffer_get_size;
|
||||||
custom_buffer_get_line_count_type *buffer_get_line_count;
|
custom_buffer_get_line_count_type *buffer_get_line_count;
|
||||||
custom_push_buffer_base_name_type *push_buffer_base_name;
|
custom_push_buffer_base_name_type *push_buffer_base_name;
|
||||||
custom_push_buffer_unique_name_type *push_buffer_unique_name;
|
custom_push_buffer_unique_name_type *push_buffer_unique_name;
|
||||||
custom_push_buffer_file_name_type *push_buffer_file_name;
|
custom_push_buffer_file_name_type *push_buffer_file_name;
|
||||||
custom_buffer_get_dirty_state_type *buffer_get_dirty_state;
|
custom_buffer_get_dirty_state_type *buffer_get_dirty_state;
|
||||||
custom_buffer_set_dirty_state_type *buffer_set_dirty_state;
|
custom_buffer_set_dirty_state_type *buffer_set_dirty_state;
|
||||||
custom_buffer_set_layout_type *buffer_set_layout;
|
custom_buffer_set_layout_type *buffer_set_layout;
|
||||||
custom_buffer_clear_layout_cache_type *buffer_clear_layout_cache;
|
custom_buffer_clear_layout_cache_type *buffer_clear_layout_cache;
|
||||||
custom_buffer_get_layout_type *buffer_get_layout;
|
custom_buffer_get_layout_type *buffer_get_layout;
|
||||||
custom_buffer_get_setting_type *buffer_get_setting;
|
custom_buffer_get_setting_type *buffer_get_setting;
|
||||||
custom_buffer_set_setting_type *buffer_set_setting;
|
custom_buffer_set_setting_type *buffer_set_setting;
|
||||||
custom_buffer_get_managed_scope_type *buffer_get_managed_scope;
|
custom_buffer_get_managed_scope_type *buffer_get_managed_scope;
|
||||||
custom_buffer_send_end_signal_type *buffer_send_end_signal;
|
custom_buffer_send_end_signal_type *buffer_send_end_signal;
|
||||||
custom_create_buffer_type *create_buffer;
|
custom_create_buffer_type *create_buffer;
|
||||||
custom_buffer_save_type *buffer_save;
|
custom_buffer_save_type *buffer_save;
|
||||||
custom_buffer_kill_type *buffer_kill;
|
custom_buffer_kill_type *buffer_kill;
|
||||||
custom_buffer_reopen_type *buffer_reopen;
|
custom_buffer_reopen_type *buffer_reopen;
|
||||||
custom_buffer_get_file_attributes_type *buffer_get_file_attributes;
|
custom_buffer_get_file_attributes_type *buffer_get_file_attributes;
|
||||||
custom_get_view_next_type *get_view_next;
|
custom_get_view_next_type *get_view_next;
|
||||||
custom_get_view_prev_type *get_view_prev;
|
custom_get_view_prev_type *get_view_prev;
|
||||||
custom_get_this_ctx_view_type *get_this_ctx_view;
|
custom_get_this_ctx_view_type *get_this_ctx_view;
|
||||||
custom_get_active_view_type *get_active_view;
|
custom_get_active_view_type *get_active_view;
|
||||||
custom_view_exists_type *view_exists;
|
custom_view_exists_type *view_exists;
|
||||||
custom_view_get_buffer_type *view_get_buffer;
|
custom_view_get_buffer_type *view_get_buffer;
|
||||||
custom_view_get_cursor_pos_type *view_get_cursor_pos;
|
custom_view_get_cursor_pos_type *view_get_cursor_pos;
|
||||||
custom_view_get_mark_pos_type *view_get_mark_pos;
|
custom_view_get_mark_pos_type *view_get_mark_pos;
|
||||||
custom_view_get_preferred_x_type *view_get_preferred_x;
|
custom_view_get_preferred_x_type *view_get_preferred_x;
|
||||||
custom_view_set_preferred_x_type *view_set_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_screen_rect_type *view_get_screen_rect;
|
||||||
custom_view_get_panel_type *view_get_panel;
|
custom_view_get_panel_type *view_get_panel;
|
||||||
custom_panel_get_view_type *panel_get_view;
|
custom_panel_get_view_type *panel_get_view;
|
||||||
custom_panel_is_split_type *panel_is_split;
|
custom_panel_is_split_type *panel_is_split;
|
||||||
custom_panel_is_leaf_type *panel_is_leaf;
|
custom_panel_is_leaf_type *panel_is_leaf;
|
||||||
custom_panel_split_type *panel_split;
|
custom_panel_split_type *panel_split;
|
||||||
custom_panel_set_split_type *panel_set_split;
|
custom_panel_set_split_type *panel_set_split;
|
||||||
custom_panel_swap_children_type *panel_swap_children;
|
custom_panel_swap_children_type *panel_swap_children;
|
||||||
custom_panel_get_root_type *panel_get_root;
|
custom_panel_get_root_type *panel_get_root;
|
||||||
custom_panel_get_parent_type *panel_get_parent;
|
custom_panel_get_parent_type *panel_get_parent;
|
||||||
custom_panel_get_child_type *panel_get_child;
|
custom_panel_get_child_type *panel_get_child;
|
||||||
custom_view_close_type *view_close;
|
custom_view_close_type *view_close;
|
||||||
custom_view_get_buffer_region_type *view_get_buffer_region;
|
custom_view_get_buffer_region_type *view_get_buffer_region;
|
||||||
custom_view_get_buffer_scroll_type *view_get_buffer_scroll;
|
custom_view_get_buffer_scroll_type *view_get_buffer_scroll;
|
||||||
custom_view_set_active_type *view_set_active;
|
custom_view_set_active_type *view_set_active;
|
||||||
custom_view_enqueue_command_function_type *view_enqueue_command_function;
|
custom_view_enqueue_command_function_type *view_enqueue_command_function;
|
||||||
custom_view_get_setting_type *view_get_setting;
|
custom_view_get_setting_type *view_get_setting;
|
||||||
custom_view_set_setting_type *view_set_setting;
|
custom_view_set_setting_type *view_set_setting;
|
||||||
custom_view_get_managed_scope_type *view_get_managed_scope;
|
custom_view_get_managed_scope_type *view_get_managed_scope;
|
||||||
custom_buffer_compute_cursor_type *buffer_compute_cursor;
|
custom_buffer_compute_cursor_type *buffer_compute_cursor;
|
||||||
custom_view_compute_cursor_type *view_compute_cursor;
|
custom_view_compute_cursor_type *view_compute_cursor;
|
||||||
custom_view_set_camera_bounds_type *view_set_camera_bounds;
|
custom_view_set_camera_bounds_type *view_set_camera_bounds;
|
||||||
custom_view_get_camera_bounds_type *view_get_camera_bounds;
|
custom_view_get_camera_bounds_type *view_get_camera_bounds;
|
||||||
custom_view_set_cursor_type *view_set_cursor;
|
custom_view_set_cursor_type *view_set_cursor;
|
||||||
custom_view_set_buffer_scroll_type *view_set_buffer_scroll;
|
custom_view_set_buffer_scroll_type *view_set_buffer_scroll;
|
||||||
custom_view_set_mark_type *view_set_mark;
|
custom_view_set_mark_type *view_set_mark;
|
||||||
custom_view_quit_ui_type *view_quit_ui;
|
custom_view_quit_ui_type *view_quit_ui;
|
||||||
custom_view_set_buffer_type *view_set_buffer;
|
custom_view_set_buffer_type *view_set_buffer;
|
||||||
custom_view_push_context_type *view_push_context;
|
custom_view_push_context_type *view_push_context;
|
||||||
custom_view_pop_context_type *view_pop_context;
|
custom_view_pop_context_type *view_pop_context;
|
||||||
custom_view_alter_context_type *view_alter_context;
|
custom_view_alter_context_type *view_alter_context;
|
||||||
custom_view_current_context_type *view_current_context;
|
custom_view_current_context_type *view_current_context;
|
||||||
custom_view_current_context_hook_memory_type *view_current_context_hook_memory;
|
custom_view_current_context_hook_memory_type *view_current_context_hook_memory;
|
||||||
custom_create_user_managed_scope_type *create_user_managed_scope;
|
custom_create_user_managed_scope_type *create_user_managed_scope;
|
||||||
custom_destroy_user_managed_scope_type *destroy_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_global_managed_scope_type *get_global_managed_scope;
|
||||||
custom_get_managed_scope_with_multiple_dependencies_type *get_managed_scope_with_multiple_dependencies;
|
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_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_clear_self_all_dependent_scopes_type *managed_scope_clear_self_all_dependent_scopes;
|
||||||
custom_managed_scope_allocator_type *managed_scope_allocator;
|
custom_managed_scope_allocator_type *managed_scope_allocator;
|
||||||
custom_managed_id_group_highest_id_type *managed_id_group_highest_id;
|
custom_managed_id_group_highest_id_type *managed_id_group_highest_id;
|
||||||
custom_managed_id_declare_type *managed_id_declare;
|
custom_managed_id_declare_type *managed_id_declare;
|
||||||
custom_managed_id_get_type *managed_id_get;
|
custom_managed_id_get_type *managed_id_get;
|
||||||
custom_managed_scope_get_attachment_type *managed_scope_get_attachment;
|
custom_managed_scope_get_attachment_type *managed_scope_get_attachment;
|
||||||
custom_managed_scope_attachment_erase_type *managed_scope_attachment_erase;
|
custom_managed_scope_attachment_erase_type *managed_scope_attachment_erase;
|
||||||
custom_alloc_managed_memory_in_scope_type *alloc_managed_memory_in_scope;
|
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_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_size_type *managed_object_get_item_size;
|
||||||
custom_managed_object_get_item_count_type *managed_object_get_item_count;
|
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_pointer_type *managed_object_get_pointer;
|
||||||
custom_managed_object_get_type_type *managed_object_get_type;
|
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_get_containing_scope_type *managed_object_get_containing_scope;
|
||||||
custom_managed_object_free_type *managed_object_free;
|
custom_managed_object_free_type *managed_object_free;
|
||||||
custom_managed_object_store_data_type *managed_object_store_data;
|
custom_managed_object_store_data_type *managed_object_store_data;
|
||||||
custom_managed_object_load_data_type *managed_object_load_data;
|
custom_managed_object_load_data_type *managed_object_load_data;
|
||||||
custom_get_next_input_raw_type *get_next_input_raw;
|
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_sequence_number_type *get_current_input_sequence_number;
|
||||||
custom_get_current_input_type *get_current_input;
|
custom_get_current_input_type *get_current_input;
|
||||||
custom_set_current_input_type *set_current_input;
|
custom_set_current_input_type *set_current_input;
|
||||||
custom_leave_current_input_unhandled_type *leave_current_input_unhandled;
|
custom_leave_current_input_unhandled_type *leave_current_input_unhandled;
|
||||||
custom_set_custom_hook_type *set_custom_hook;
|
custom_set_custom_hook_type *set_custom_hook;
|
||||||
custom_get_custom_hook_type *get_custom_hook;
|
custom_get_custom_hook_type *get_custom_hook;
|
||||||
custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size;
|
custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size;
|
||||||
custom_get_mouse_state_type *get_mouse_state;
|
custom_get_mouse_state_type *get_mouse_state;
|
||||||
custom_get_active_query_bars_type *get_active_query_bars;
|
custom_get_active_query_bars_type *get_active_query_bars;
|
||||||
custom_start_query_bar_type *start_query_bar;
|
custom_start_query_bar_type *start_query_bar;
|
||||||
custom_end_query_bar_type *end_query_bar;
|
custom_end_query_bar_type *end_query_bar;
|
||||||
custom_clear_all_query_bars_type *clear_all_query_bars;
|
custom_clear_all_query_bars_type *clear_all_query_bars;
|
||||||
custom_print_message_type *print_message;
|
custom_print_message_type *print_message;
|
||||||
custom_log_string_type *log_string;
|
custom_log_string_type *log_string;
|
||||||
custom_get_largest_face_id_type *get_largest_face_id;
|
custom_get_largest_face_id_type *get_largest_face_id;
|
||||||
custom_set_global_face_type *set_global_face;
|
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_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_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_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_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_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_merge_record_range_type *buffer_history_merge_record_range;
|
||||||
custom_buffer_history_clear_after_current_state_type *buffer_history_clear_after_current_state;
|
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_begin_type *global_history_edit_group_begin;
|
||||||
custom_global_history_edit_group_end_type *global_history_edit_group_end;
|
custom_global_history_edit_group_end_type *global_history_edit_group_end;
|
||||||
custom_buffer_set_face_type *buffer_set_face;
|
custom_buffer_set_face_type *buffer_set_face;
|
||||||
custom_get_face_description_type *get_face_description;
|
custom_get_face_description_type *get_face_description;
|
||||||
custom_get_face_metrics_type *get_face_metrics;
|
custom_get_face_metrics_type *get_face_metrics;
|
||||||
custom_get_face_advance_map_type *get_face_advance_map;
|
custom_get_face_advance_map_type *get_face_advance_map;
|
||||||
custom_get_face_id_type *get_face_id;
|
custom_get_face_id_type *get_face_id;
|
||||||
custom_try_create_new_face_type *try_create_new_face;
|
custom_try_create_new_face_type *try_create_new_face;
|
||||||
custom_try_modify_face_type *try_modify_face;
|
custom_try_modify_face_type *try_modify_face;
|
||||||
custom_try_release_face_type *try_release_face;
|
custom_try_release_face_type *try_release_face;
|
||||||
custom_push_hot_directory_type *push_hot_directory;
|
custom_push_hot_directory_type *push_hot_directory;
|
||||||
custom_set_hot_directory_type *set_hot_directory;
|
custom_set_hot_directory_type *set_hot_directory;
|
||||||
custom_send_exit_signal_type *send_exit_signal;
|
custom_send_exit_signal_type *send_exit_signal;
|
||||||
custom_hard_exit_type *hard_exit;
|
custom_hard_exit_type *hard_exit;
|
||||||
custom_set_window_title_type *set_window_title;
|
custom_set_window_title_type *set_window_title;
|
||||||
custom_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
|
custom_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
|
||||||
custom_release_global_frame_mutex_type *release_global_frame_mutex;
|
custom_release_global_frame_mutex_type *release_global_frame_mutex;
|
||||||
custom_draw_string_oriented_type *draw_string_oriented;
|
custom_draw_string_oriented_type *draw_string_oriented;
|
||||||
custom_get_string_advance_type *get_string_advance;
|
custom_get_string_advance_type *get_string_advance;
|
||||||
custom_draw_rectangle_type *draw_rectangle;
|
custom_draw_rectangle_type *draw_rectangle;
|
||||||
custom_draw_rectangle_outline_type *draw_rectangle_outline;
|
custom_draw_rectangle_outline_type *draw_rectangle_outline;
|
||||||
custom_draw_set_clip_type *draw_set_clip;
|
custom_draw_set_clip_type *draw_set_clip;
|
||||||
custom_text_layout_create_type *text_layout_create;
|
custom_text_layout_create_type *text_layout_create;
|
||||||
custom_text_layout_region_type *text_layout_region;
|
custom_text_layout_region_type *text_layout_region;
|
||||||
custom_text_layout_get_buffer_type *text_layout_get_buffer;
|
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_get_visible_range_type *text_layout_get_visible_range;
|
||||||
custom_text_layout_line_on_screen_type *text_layout_line_on_screen;
|
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_text_layout_character_on_screen_type *text_layout_character_on_screen;
|
||||||
custom_paint_text_color_type *paint_text_color;
|
custom_paint_text_color_type *paint_text_color;
|
||||||
custom_paint_text_color_blend_type *paint_text_color_blend;
|
custom_paint_text_color_blend_type *paint_text_color_blend;
|
||||||
custom_text_layout_free_type *text_layout_free;
|
custom_text_layout_free_type *text_layout_free;
|
||||||
custom_draw_text_layout_type *draw_text_layout;
|
custom_draw_text_layout_type *draw_text_layout;
|
||||||
custom_open_color_picker_type *open_color_picker;
|
custom_open_color_picker_type *open_color_picker;
|
||||||
custom_animate_in_n_milliseconds_type *animate_in_n_milliseconds;
|
custom_animate_in_n_milliseconds_type *animate_in_n_milliseconds;
|
||||||
custom_buffer_find_all_matches_type *buffer_find_all_matches;
|
custom_buffer_find_all_matches_type *buffer_find_all_matches;
|
||||||
custom_get_core_profile_list_type *get_core_profile_list;
|
custom_get_core_profile_list_type *get_core_profile_list;
|
||||||
custom_get_custom_layer_boundary_docs_type *get_custom_layer_boundary_docs;
|
custom_get_custom_layer_boundary_docs_type *get_custom_layer_boundary_docs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(STATIC_LINK_API)
|
#if defined(STATIC_LINK_API)
|
||||||
internal b32 global_set_setting(Application_Links* app, Global_Setting_ID setting, i64 value);
|
internal b32 global_set_setting(Application_Links* app, Global_Setting_ID setting, i64 value);
|
||||||
internal Rect_f32 global_get_screen_rectangle(Application_Links* app);
|
internal Rect_f32 global_get_screen_rectangle(Application_Links* app);
|
||||||
|
@ -718,6 +723,7 @@ internal String_Match_List buffer_find_all_matches(Application_Links* app, Arena
|
||||||
internal Profile_Global_List* get_core_profile_list(Application_Links* app);
|
internal Profile_Global_List* get_core_profile_list(Application_Links* app);
|
||||||
internal Doc_Cluster* get_custom_layer_boundary_docs(Application_Links* app, Arena* arena);
|
internal Doc_Cluster* get_custom_layer_boundary_docs(Application_Links* app, Arena* arena);
|
||||||
#undef STATIC_LINK_API
|
#undef STATIC_LINK_API
|
||||||
|
|
||||||
#elif defined(DYNAMIC_LINK_API)
|
#elif defined(DYNAMIC_LINK_API)
|
||||||
global custom_global_set_setting_type *global_set_setting = 0;
|
global custom_global_set_setting_type *global_set_setting = 0;
|
||||||
global custom_global_get_screen_rectangle_type *global_get_screen_rectangle = 0;
|
global custom_global_get_screen_rectangle_type *global_get_screen_rectangle = 0;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,5 @@
|
||||||
|
/* 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 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 Rect_f32 global_get_screen_rectangle(Application_Links* app);
|
||||||
api(custom) function Thread_Context* get_thread_context(Application_Links* app);
|
api(custom) function Thread_Context* get_thread_context(Application_Links* app);
|
||||||
|
|
|
@ -1,123 +1,126 @@
|
||||||
|
/* Generated by "code/4ed_system_api.cpp" */
|
||||||
|
|
||||||
function void
|
function void
|
||||||
system_api_fill_vtable(API_VTable_system *vtable){
|
system_api_fill_vtable(API_VTable_system *vtable){
|
||||||
vtable->error_box = system_error_box;
|
vtable->error_box = system_error_box;
|
||||||
vtable->get_path = system_get_path;
|
vtable->get_path = system_get_path;
|
||||||
vtable->get_canonical = system_get_canonical;
|
vtable->get_canonical = system_get_canonical;
|
||||||
vtable->get_file_list = system_get_file_list;
|
vtable->get_file_list = system_get_file_list;
|
||||||
vtable->quick_file_attributes = system_quick_file_attributes;
|
vtable->quick_file_attributes = system_quick_file_attributes;
|
||||||
vtable->load_handle = system_load_handle;
|
vtable->load_handle = system_load_handle;
|
||||||
vtable->load_attributes = system_load_attributes;
|
vtable->load_attributes = system_load_attributes;
|
||||||
vtable->load_file = system_load_file;
|
vtable->load_file = system_load_file;
|
||||||
vtable->load_close = system_load_close;
|
vtable->load_close = system_load_close;
|
||||||
vtable->save_file = system_save_file;
|
vtable->save_file = system_save_file;
|
||||||
vtable->load_library = system_load_library;
|
vtable->load_library = system_load_library;
|
||||||
vtable->release_library = system_release_library;
|
vtable->release_library = system_release_library;
|
||||||
vtable->get_proc = system_get_proc;
|
vtable->get_proc = system_get_proc;
|
||||||
vtable->now_time = system_now_time;
|
vtable->now_time = system_now_time;
|
||||||
vtable->now_date_time_universal = system_now_date_time_universal;
|
vtable->now_date_time_universal = system_now_date_time_universal;
|
||||||
vtable->local_date_time_from_universal = system_local_date_time_from_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->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_create = system_wake_up_timer_create;
|
||||||
vtable->wake_up_timer_release = system_wake_up_timer_release;
|
vtable->wake_up_timer_release = system_wake_up_timer_release;
|
||||||
vtable->wake_up_timer_set = system_wake_up_timer_set;
|
vtable->wake_up_timer_set = system_wake_up_timer_set;
|
||||||
vtable->signal_step = system_signal_step;
|
vtable->signal_step = system_signal_step;
|
||||||
vtable->sleep = system_sleep;
|
vtable->sleep = system_sleep;
|
||||||
vtable->get_clipboard = system_get_clipboard;
|
vtable->get_clipboard = system_get_clipboard;
|
||||||
vtable->post_clipboard = system_post_clipboard;
|
vtable->post_clipboard = system_post_clipboard;
|
||||||
vtable->set_clipboard_catch_all = system_set_clipboard_catch_all;
|
vtable->set_clipboard_catch_all = system_set_clipboard_catch_all;
|
||||||
vtable->get_clipboard_catch_all = system_get_clipboard_catch_all;
|
vtable->get_clipboard_catch_all = system_get_clipboard_catch_all;
|
||||||
vtable->cli_call = system_cli_call;
|
vtable->cli_call = system_cli_call;
|
||||||
vtable->cli_begin_update = system_cli_begin_update;
|
vtable->cli_begin_update = system_cli_begin_update;
|
||||||
vtable->cli_update_step = system_cli_update_step;
|
vtable->cli_update_step = system_cli_update_step;
|
||||||
vtable->cli_end_update = system_cli_end_update;
|
vtable->cli_end_update = system_cli_end_update;
|
||||||
vtable->open_color_picker = system_open_color_picker;
|
vtable->open_color_picker = system_open_color_picker;
|
||||||
vtable->get_screen_scale_factor = system_get_screen_scale_factor;
|
vtable->get_screen_scale_factor = system_get_screen_scale_factor;
|
||||||
vtable->thread_launch = system_thread_launch;
|
vtable->thread_launch = system_thread_launch;
|
||||||
vtable->thread_join = system_thread_join;
|
vtable->thread_join = system_thread_join;
|
||||||
vtable->thread_free = system_thread_free;
|
vtable->thread_free = system_thread_free;
|
||||||
vtable->thread_get_id = system_thread_get_id;
|
vtable->thread_get_id = system_thread_get_id;
|
||||||
vtable->acquire_global_frame_mutex = system_acquire_global_frame_mutex;
|
vtable->acquire_global_frame_mutex = system_acquire_global_frame_mutex;
|
||||||
vtable->release_global_frame_mutex = system_release_global_frame_mutex;
|
vtable->release_global_frame_mutex = system_release_global_frame_mutex;
|
||||||
vtable->mutex_make = system_mutex_make;
|
vtable->mutex_make = system_mutex_make;
|
||||||
vtable->mutex_acquire = system_mutex_acquire;
|
vtable->mutex_acquire = system_mutex_acquire;
|
||||||
vtable->mutex_release = system_mutex_release;
|
vtable->mutex_release = system_mutex_release;
|
||||||
vtable->mutex_free = system_mutex_free;
|
vtable->mutex_free = system_mutex_free;
|
||||||
vtable->condition_variable_make = system_condition_variable_make;
|
vtable->condition_variable_make = system_condition_variable_make;
|
||||||
vtable->condition_variable_wait = system_condition_variable_wait;
|
vtable->condition_variable_wait = system_condition_variable_wait;
|
||||||
vtable->condition_variable_signal = system_condition_variable_signal;
|
vtable->condition_variable_signal = system_condition_variable_signal;
|
||||||
vtable->condition_variable_free = system_condition_variable_free;
|
vtable->condition_variable_free = system_condition_variable_free;
|
||||||
vtable->memory_allocate = system_memory_allocate;
|
vtable->memory_allocate = system_memory_allocate;
|
||||||
vtable->memory_set_protection = system_memory_set_protection;
|
vtable->memory_set_protection = system_memory_set_protection;
|
||||||
vtable->memory_free = system_memory_free;
|
vtable->memory_free = system_memory_free;
|
||||||
vtable->memory_annotation = system_memory_annotation;
|
vtable->memory_annotation = system_memory_annotation;
|
||||||
vtable->show_mouse_cursor = system_show_mouse_cursor;
|
vtable->show_mouse_cursor = system_show_mouse_cursor;
|
||||||
vtable->set_fullscreen = system_set_fullscreen;
|
vtable->set_fullscreen = system_set_fullscreen;
|
||||||
vtable->is_fullscreen = system_is_fullscreen;
|
vtable->is_fullscreen = system_is_fullscreen;
|
||||||
vtable->get_keyboard_modifiers = system_get_keyboard_modifiers;
|
vtable->get_keyboard_modifiers = system_get_keyboard_modifiers;
|
||||||
vtable->set_key_mode = system_set_key_mode;
|
vtable->set_key_mode = system_set_key_mode;
|
||||||
vtable->set_source_mixer = system_set_source_mixer;
|
vtable->set_source_mixer = system_set_source_mixer;
|
||||||
vtable->set_destination_mixer = system_set_destination_mixer;
|
vtable->set_destination_mixer = system_set_destination_mixer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DYNAMIC_LINK_API)
|
#if defined(DYNAMIC_LINK_API)
|
||||||
function void
|
function void
|
||||||
system_api_read_vtable(API_VTable_system *vtable){
|
system_api_read_vtable(API_VTable_system *vtable){
|
||||||
system_error_box = vtable->error_box;
|
system_error_box = vtable->error_box;
|
||||||
system_get_path = vtable->get_path;
|
system_get_path = vtable->get_path;
|
||||||
system_get_canonical = vtable->get_canonical;
|
system_get_canonical = vtable->get_canonical;
|
||||||
system_get_file_list = vtable->get_file_list;
|
system_get_file_list = vtable->get_file_list;
|
||||||
system_quick_file_attributes = vtable->quick_file_attributes;
|
system_quick_file_attributes = vtable->quick_file_attributes;
|
||||||
system_load_handle = vtable->load_handle;
|
system_load_handle = vtable->load_handle;
|
||||||
system_load_attributes = vtable->load_attributes;
|
system_load_attributes = vtable->load_attributes;
|
||||||
system_load_file = vtable->load_file;
|
system_load_file = vtable->load_file;
|
||||||
system_load_close = vtable->load_close;
|
system_load_close = vtable->load_close;
|
||||||
system_save_file = vtable->save_file;
|
system_save_file = vtable->save_file;
|
||||||
system_load_library = vtable->load_library;
|
system_load_library = vtable->load_library;
|
||||||
system_release_library = vtable->release_library;
|
system_release_library = vtable->release_library;
|
||||||
system_get_proc = vtable->get_proc;
|
system_get_proc = vtable->get_proc;
|
||||||
system_now_time = vtable->now_time;
|
system_now_time = vtable->now_time;
|
||||||
system_now_date_time_universal = vtable->now_date_time_universal;
|
system_now_date_time_universal = vtable->now_date_time_universal;
|
||||||
system_local_date_time_from_universal = vtable->local_date_time_from_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_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_create = vtable->wake_up_timer_create;
|
||||||
system_wake_up_timer_release = vtable->wake_up_timer_release;
|
system_wake_up_timer_release = vtable->wake_up_timer_release;
|
||||||
system_wake_up_timer_set = vtable->wake_up_timer_set;
|
system_wake_up_timer_set = vtable->wake_up_timer_set;
|
||||||
system_signal_step = vtable->signal_step;
|
system_signal_step = vtable->signal_step;
|
||||||
system_sleep = vtable->sleep;
|
system_sleep = vtable->sleep;
|
||||||
system_get_clipboard = vtable->get_clipboard;
|
system_get_clipboard = vtable->get_clipboard;
|
||||||
system_post_clipboard = vtable->post_clipboard;
|
system_post_clipboard = vtable->post_clipboard;
|
||||||
system_set_clipboard_catch_all = vtable->set_clipboard_catch_all;
|
system_set_clipboard_catch_all = vtable->set_clipboard_catch_all;
|
||||||
system_get_clipboard_catch_all = vtable->get_clipboard_catch_all;
|
system_get_clipboard_catch_all = vtable->get_clipboard_catch_all;
|
||||||
system_cli_call = vtable->cli_call;
|
system_cli_call = vtable->cli_call;
|
||||||
system_cli_begin_update = vtable->cli_begin_update;
|
system_cli_begin_update = vtable->cli_begin_update;
|
||||||
system_cli_update_step = vtable->cli_update_step;
|
system_cli_update_step = vtable->cli_update_step;
|
||||||
system_cli_end_update = vtable->cli_end_update;
|
system_cli_end_update = vtable->cli_end_update;
|
||||||
system_open_color_picker = vtable->open_color_picker;
|
system_open_color_picker = vtable->open_color_picker;
|
||||||
system_get_screen_scale_factor = vtable->get_screen_scale_factor;
|
system_get_screen_scale_factor = vtable->get_screen_scale_factor;
|
||||||
system_thread_launch = vtable->thread_launch;
|
system_thread_launch = vtable->thread_launch;
|
||||||
system_thread_join = vtable->thread_join;
|
system_thread_join = vtable->thread_join;
|
||||||
system_thread_free = vtable->thread_free;
|
system_thread_free = vtable->thread_free;
|
||||||
system_thread_get_id = vtable->thread_get_id;
|
system_thread_get_id = vtable->thread_get_id;
|
||||||
system_acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
|
system_acquire_global_frame_mutex = vtable->acquire_global_frame_mutex;
|
||||||
system_release_global_frame_mutex = vtable->release_global_frame_mutex;
|
system_release_global_frame_mutex = vtable->release_global_frame_mutex;
|
||||||
system_mutex_make = vtable->mutex_make;
|
system_mutex_make = vtable->mutex_make;
|
||||||
system_mutex_acquire = vtable->mutex_acquire;
|
system_mutex_acquire = vtable->mutex_acquire;
|
||||||
system_mutex_release = vtable->mutex_release;
|
system_mutex_release = vtable->mutex_release;
|
||||||
system_mutex_free = vtable->mutex_free;
|
system_mutex_free = vtable->mutex_free;
|
||||||
system_condition_variable_make = vtable->condition_variable_make;
|
system_condition_variable_make = vtable->condition_variable_make;
|
||||||
system_condition_variable_wait = vtable->condition_variable_wait;
|
system_condition_variable_wait = vtable->condition_variable_wait;
|
||||||
system_condition_variable_signal = vtable->condition_variable_signal;
|
system_condition_variable_signal = vtable->condition_variable_signal;
|
||||||
system_condition_variable_free = vtable->condition_variable_free;
|
system_condition_variable_free = vtable->condition_variable_free;
|
||||||
system_memory_allocate = vtable->memory_allocate;
|
system_memory_allocate = vtable->memory_allocate;
|
||||||
system_memory_set_protection = vtable->memory_set_protection;
|
system_memory_set_protection = vtable->memory_set_protection;
|
||||||
system_memory_free = vtable->memory_free;
|
system_memory_free = vtable->memory_free;
|
||||||
system_memory_annotation = vtable->memory_annotation;
|
system_memory_annotation = vtable->memory_annotation;
|
||||||
system_show_mouse_cursor = vtable->show_mouse_cursor;
|
system_show_mouse_cursor = vtable->show_mouse_cursor;
|
||||||
system_set_fullscreen = vtable->set_fullscreen;
|
system_set_fullscreen = vtable->set_fullscreen;
|
||||||
system_is_fullscreen = vtable->is_fullscreen;
|
system_is_fullscreen = vtable->is_fullscreen;
|
||||||
system_get_keyboard_modifiers = vtable->get_keyboard_modifiers;
|
system_get_keyboard_modifiers = vtable->get_keyboard_modifiers;
|
||||||
system_set_key_mode = vtable->set_key_mode;
|
system_set_key_mode = vtable->set_key_mode;
|
||||||
system_set_source_mixer = vtable->set_source_mixer;
|
system_set_source_mixer = vtable->set_source_mixer;
|
||||||
system_set_destination_mixer = vtable->set_destination_mixer;
|
system_set_destination_mixer = vtable->set_destination_mixer;
|
||||||
}
|
}
|
||||||
#undef DYNAMIC_LINK_API
|
#undef DYNAMIC_LINK_API
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* Generated by "code/4ed_system_api.cpp" */
|
||||||
|
|
||||||
#define system_error_box_sig() void system_error_box(char* msg)
|
#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_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)
|
#define system_get_canonical_sig() String_Const_u8 system_get_canonical(Arena* arena, String_Const_u8 name)
|
||||||
|
@ -55,6 +57,7 @@
|
||||||
#define system_set_key_mode_sig() void system_set_key_mode(Key_Mode mode)
|
#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_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)
|
#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 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_path_type(Arena* arena, System_Path_Code path_code);
|
||||||
typedef String_Const_u8 system_get_canonical_type(Arena* arena, String_Const_u8 name);
|
typedef String_Const_u8 system_get_canonical_type(Arena* arena, String_Const_u8 name);
|
||||||
|
@ -112,65 +115,67 @@ 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_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_source_mixer_type(void* ctx, Audio_Mix_Sources_Function* mix_func);
|
||||||
typedef void system_set_destination_mixer_type(Audio_Mix_Destination_Function* mix_func);
|
typedef void system_set_destination_mixer_type(Audio_Mix_Destination_Function* mix_func);
|
||||||
|
|
||||||
struct API_VTable_system{
|
struct API_VTable_system{
|
||||||
system_error_box_type *error_box;
|
system_error_box_type *error_box;
|
||||||
system_get_path_type *get_path;
|
system_get_path_type *get_path;
|
||||||
system_get_canonical_type *get_canonical;
|
system_get_canonical_type *get_canonical;
|
||||||
system_get_file_list_type *get_file_list;
|
system_get_file_list_type *get_file_list;
|
||||||
system_quick_file_attributes_type *quick_file_attributes;
|
system_quick_file_attributes_type *quick_file_attributes;
|
||||||
system_load_handle_type *load_handle;
|
system_load_handle_type *load_handle;
|
||||||
system_load_attributes_type *load_attributes;
|
system_load_attributes_type *load_attributes;
|
||||||
system_load_file_type *load_file;
|
system_load_file_type *load_file;
|
||||||
system_load_close_type *load_close;
|
system_load_close_type *load_close;
|
||||||
system_save_file_type *save_file;
|
system_save_file_type *save_file;
|
||||||
system_load_library_type *load_library;
|
system_load_library_type *load_library;
|
||||||
system_release_library_type *release_library;
|
system_release_library_type *release_library;
|
||||||
system_get_proc_type *get_proc;
|
system_get_proc_type *get_proc;
|
||||||
system_now_time_type *now_time;
|
system_now_time_type *now_time;
|
||||||
system_now_date_time_universal_type *now_date_time_universal;
|
system_now_date_time_universal_type *now_date_time_universal;
|
||||||
system_local_date_time_from_universal_type *local_date_time_from_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_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_create_type *wake_up_timer_create;
|
||||||
system_wake_up_timer_release_type *wake_up_timer_release;
|
system_wake_up_timer_release_type *wake_up_timer_release;
|
||||||
system_wake_up_timer_set_type *wake_up_timer_set;
|
system_wake_up_timer_set_type *wake_up_timer_set;
|
||||||
system_signal_step_type *signal_step;
|
system_signal_step_type *signal_step;
|
||||||
system_sleep_type *sleep;
|
system_sleep_type *sleep;
|
||||||
system_get_clipboard_type *get_clipboard;
|
system_get_clipboard_type *get_clipboard;
|
||||||
system_post_clipboard_type *post_clipboard;
|
system_post_clipboard_type *post_clipboard;
|
||||||
system_set_clipboard_catch_all_type *set_clipboard_catch_all;
|
system_set_clipboard_catch_all_type *set_clipboard_catch_all;
|
||||||
system_get_clipboard_catch_all_type *get_clipboard_catch_all;
|
system_get_clipboard_catch_all_type *get_clipboard_catch_all;
|
||||||
system_cli_call_type *cli_call;
|
system_cli_call_type *cli_call;
|
||||||
system_cli_begin_update_type *cli_begin_update;
|
system_cli_begin_update_type *cli_begin_update;
|
||||||
system_cli_update_step_type *cli_update_step;
|
system_cli_update_step_type *cli_update_step;
|
||||||
system_cli_end_update_type *cli_end_update;
|
system_cli_end_update_type *cli_end_update;
|
||||||
system_open_color_picker_type *open_color_picker;
|
system_open_color_picker_type *open_color_picker;
|
||||||
system_get_screen_scale_factor_type *get_screen_scale_factor;
|
system_get_screen_scale_factor_type *get_screen_scale_factor;
|
||||||
system_thread_launch_type *thread_launch;
|
system_thread_launch_type *thread_launch;
|
||||||
system_thread_join_type *thread_join;
|
system_thread_join_type *thread_join;
|
||||||
system_thread_free_type *thread_free;
|
system_thread_free_type *thread_free;
|
||||||
system_thread_get_id_type *thread_get_id;
|
system_thread_get_id_type *thread_get_id;
|
||||||
system_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
|
system_acquire_global_frame_mutex_type *acquire_global_frame_mutex;
|
||||||
system_release_global_frame_mutex_type *release_global_frame_mutex;
|
system_release_global_frame_mutex_type *release_global_frame_mutex;
|
||||||
system_mutex_make_type *mutex_make;
|
system_mutex_make_type *mutex_make;
|
||||||
system_mutex_acquire_type *mutex_acquire;
|
system_mutex_acquire_type *mutex_acquire;
|
||||||
system_mutex_release_type *mutex_release;
|
system_mutex_release_type *mutex_release;
|
||||||
system_mutex_free_type *mutex_free;
|
system_mutex_free_type *mutex_free;
|
||||||
system_condition_variable_make_type *condition_variable_make;
|
system_condition_variable_make_type *condition_variable_make;
|
||||||
system_condition_variable_wait_type *condition_variable_wait;
|
system_condition_variable_wait_type *condition_variable_wait;
|
||||||
system_condition_variable_signal_type *condition_variable_signal;
|
system_condition_variable_signal_type *condition_variable_signal;
|
||||||
system_condition_variable_free_type *condition_variable_free;
|
system_condition_variable_free_type *condition_variable_free;
|
||||||
system_memory_allocate_type *memory_allocate;
|
system_memory_allocate_type *memory_allocate;
|
||||||
system_memory_set_protection_type *memory_set_protection;
|
system_memory_set_protection_type *memory_set_protection;
|
||||||
system_memory_free_type *memory_free;
|
system_memory_free_type *memory_free;
|
||||||
system_memory_annotation_type *memory_annotation;
|
system_memory_annotation_type *memory_annotation;
|
||||||
system_show_mouse_cursor_type *show_mouse_cursor;
|
system_show_mouse_cursor_type *show_mouse_cursor;
|
||||||
system_set_fullscreen_type *set_fullscreen;
|
system_set_fullscreen_type *set_fullscreen;
|
||||||
system_is_fullscreen_type *is_fullscreen;
|
system_is_fullscreen_type *is_fullscreen;
|
||||||
system_get_keyboard_modifiers_type *get_keyboard_modifiers;
|
system_get_keyboard_modifiers_type *get_keyboard_modifiers;
|
||||||
system_set_key_mode_type *set_key_mode;
|
system_set_key_mode_type *set_key_mode;
|
||||||
system_set_source_mixer_type *set_source_mixer;
|
system_set_source_mixer_type *set_source_mixer;
|
||||||
system_set_destination_mixer_type *set_destination_mixer;
|
system_set_destination_mixer_type *set_destination_mixer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(STATIC_LINK_API)
|
#if defined(STATIC_LINK_API)
|
||||||
internal void system_error_box(char* msg);
|
internal void system_error_box(char* msg);
|
||||||
internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code);
|
internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code);
|
||||||
|
@ -230,6 +235,7 @@ 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_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func);
|
||||||
internal void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func);
|
internal void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func);
|
||||||
#undef STATIC_LINK_API
|
#undef STATIC_LINK_API
|
||||||
|
|
||||||
#elif defined(DYNAMIC_LINK_API)
|
#elif defined(DYNAMIC_LINK_API)
|
||||||
global system_error_box_type *system_error_box = 0;
|
global system_error_box_type *system_error_box = 0;
|
||||||
global system_get_path_type *system_get_path = 0;
|
global system_get_path_type *system_get_path = 0;
|
||||||
|
|
|
@ -1,262 +1,264 @@
|
||||||
|
/* Generated by "code/4ed_system_api.cpp" */
|
||||||
|
|
||||||
function API_Definition*
|
function API_Definition*
|
||||||
system_api_construct(Arena *arena){
|
system_api_construct(Arena *arena){
|
||||||
API_Definition *result = begin_api(arena, "system");
|
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_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_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_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, "Arena*", "arena");
|
||||||
api_param(arena, call, "System_Path_Code", "path_code");
|
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_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, "Arena*", "arena");
|
||||||
api_param(arena, call, "String_Const_u8", "name");
|
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_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, "Arena*", "arena");
|
||||||
api_param(arena, call, "String_Const_u8", "directory");
|
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_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, "Arena*", "scratch");
|
||||||
api_param(arena, call, "String_Const_u8", "file_name");
|
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_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, "Arena*", "scratch");
|
||||||
api_param(arena, call, "char*", "file_name");
|
api_param(arena, call, "char*", "file_name");
|
||||||
api_param(arena, call, "Plat_Handle*", "out");
|
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_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_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_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, "Plat_Handle", "handle");
|
||||||
api_param(arena, call, "char*", "buffer");
|
api_param(arena, call, "char*", "buffer");
|
||||||
api_param(arena, call, "u32", "size");
|
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_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_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_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, "Arena*", "scratch");
|
||||||
api_param(arena, call, "char*", "file_name");
|
api_param(arena, call, "char*", "file_name");
|
||||||
api_param(arena, call, "String_Const_u8", "data");
|
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_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, "Arena*", "scratch");
|
||||||
api_param(arena, call, "String_Const_u8", "file_name");
|
api_param(arena, call, "String_Const_u8", "file_name");
|
||||||
api_param(arena, call, "System_Library*", "out");
|
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_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_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_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, "System_Library", "handle");
|
||||||
api_param(arena, call, "char*", "proc_name");
|
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(""));
|
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("now_time"), string_u8_litexpr("u64"), string_u8_litexpr(""));
|
||||||
(void)call;
|
(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(""));
|
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;
|
(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_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_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_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_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(""));
|
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;
|
(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_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_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_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, "Plat_Handle", "handle");
|
||||||
api_param(arena, call, "u32", "time_milliseconds");
|
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_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_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_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_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_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, "Arena*", "arena");
|
||||||
api_param(arena, call, "i32", "index");
|
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_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, "String_Const_u8", "str");
|
||||||
api_param(arena, call, "i32", "index");
|
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_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_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(""));
|
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;
|
(void)call;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("cli_call"), string_u8_litexpr("b32"), string_u8_litexpr(""));
|
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, "Arena*", "scratch");
|
||||||
api_param(arena, call, "char*", "path");
|
api_param(arena, call, "char*", "path");
|
||||||
api_param(arena, call, "char*", "script");
|
api_param(arena, call, "char*", "script");
|
||||||
api_param(arena, call, "CLI_Handles*", "cli_out");
|
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_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_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_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, "CLI_Handles*", "cli");
|
||||||
api_param(arena, call, "char*", "dest");
|
api_param(arena, call, "char*", "dest");
|
||||||
api_param(arena, call, "u32", "max");
|
api_param(arena, call, "u32", "max");
|
||||||
api_param(arena, call, "u32*", "amount");
|
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_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_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_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_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(""));
|
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;
|
(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_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, "Thread_Function*", "proc");
|
||||||
api_param(arena, call, "void*", "ptr");
|
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_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_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_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_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(""));
|
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("thread_get_id"), string_u8_litexpr("i32"), string_u8_litexpr(""));
|
||||||
(void)call;
|
(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_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_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_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_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(""));
|
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_make"), string_u8_litexpr("System_Mutex"), string_u8_litexpr(""));
|
||||||
(void)call;
|
(void)call;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("mutex_acquire"), string_u8_litexpr("void"), string_u8_litexpr(""));
|
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_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_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_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_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_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(""));
|
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;
|
(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_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_Condition_Variable", "cv");
|
||||||
api_param(arena, call, "System_Mutex", "mutex");
|
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_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_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_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_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_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, "u64", "size");
|
||||||
api_param(arena, call, "String_Const_u8", "location");
|
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_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, "void*", "ptr");
|
||||||
api_param(arena, call, "u64", "size");
|
api_param(arena, call, "u64", "size");
|
||||||
api_param(arena, call, "u32", "flags");
|
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_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, "void*", "ptr");
|
||||||
api_param(arena, call, "u64", "size");
|
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_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_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_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_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_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_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(""));
|
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("is_fullscreen"), string_u8_litexpr("b32"), string_u8_litexpr(""));
|
||||||
(void)call;
|
(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_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_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_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_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_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, "void*", "ctx");
|
||||||
api_param(arena, call, "Audio_Mix_Sources_Function*", "mix_func");
|
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_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");
|
api_param(arena, call, "Audio_Mix_Destination_Function*", "mix_func");
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* Generated by "code/4ed_system_api.cpp" */
|
||||||
|
|
||||||
api(system) function void error_box(char* msg);
|
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_path(Arena* arena, System_Path_Code path_code);
|
||||||
api(system) function String_Const_u8 get_canonical(Arena* arena, String_Const_u8 name);
|
api(system) function String_Const_u8 get_canonical(Arena* arena, String_Const_u8 name);
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
/* Generated by "code/4ed_font_api.cpp" */
|
||||||
|
|
||||||
function void
|
function void
|
||||||
font_api_fill_vtable(API_VTable_font *vtable){
|
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)
|
#if defined(DYNAMIC_LINK_API)
|
||||||
function void
|
function void
|
||||||
font_api_read_vtable(API_VTable_font *vtable){
|
font_api_read_vtable(API_VTable_font *vtable){
|
||||||
font_make_face = vtable->make_face;
|
font_make_face = vtable->make_face;
|
||||||
}
|
}
|
||||||
#undef DYNAMIC_LINK_API
|
#undef DYNAMIC_LINK_API
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
|
/* Generated by "code/4ed_font_api.cpp" */
|
||||||
|
|
||||||
#define font_make_face_sig() Face* font_make_face(Arena* arena, Face_Description* description, f32 scale_factor)
|
#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);
|
typedef Face* font_make_face_type(Arena* arena, Face_Description* description, f32 scale_factor);
|
||||||
|
|
||||||
struct API_VTable_font{
|
struct API_VTable_font{
|
||||||
font_make_face_type *make_face;
|
font_make_face_type *make_face;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(STATIC_LINK_API)
|
#if defined(STATIC_LINK_API)
|
||||||
internal Face* font_make_face(Arena* arena, Face_Description* description, f32 scale_factor);
|
internal Face* font_make_face(Arena* arena, Face_Description* description, f32 scale_factor);
|
||||||
#undef STATIC_LINK_API
|
#undef STATIC_LINK_API
|
||||||
|
|
||||||
#elif defined(DYNAMIC_LINK_API)
|
#elif defined(DYNAMIC_LINK_API)
|
||||||
global font_make_face_type *font_make_face = 0;
|
global font_make_face_type *font_make_face = 0;
|
||||||
#undef DYNAMIC_LINK_API
|
#undef DYNAMIC_LINK_API
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
|
/* Generated by "code/4ed_graphics_api.cpp" */
|
||||||
|
|
||||||
function void
|
function void
|
||||||
graphics_api_fill_vtable(API_VTable_graphics *vtable){
|
graphics_api_fill_vtable(API_VTable_graphics *vtable){
|
||||||
vtable->get_texture = graphics_get_texture;
|
vtable->get_texture = graphics_get_texture;
|
||||||
vtable->fill_texture = graphics_fill_texture;
|
vtable->fill_texture = graphics_fill_texture;
|
||||||
|
vtable->free_texture = graphics_free_texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DYNAMIC_LINK_API)
|
#if defined(DYNAMIC_LINK_API)
|
||||||
function void
|
function void
|
||||||
graphics_api_read_vtable(API_VTable_graphics *vtable){
|
graphics_api_read_vtable(API_VTable_graphics *vtable){
|
||||||
graphics_get_texture = vtable->get_texture;
|
graphics_get_texture = vtable->get_texture;
|
||||||
graphics_fill_texture = vtable->fill_texture;
|
graphics_fill_texture = vtable->fill_texture;
|
||||||
|
graphics_free_texture = vtable->free_texture;
|
||||||
}
|
}
|
||||||
#undef DYNAMIC_LINK_API
|
#undef DYNAMIC_LINK_API
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
|
/* 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_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_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 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 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{
|
struct API_VTable_graphics{
|
||||||
graphics_get_texture_type *get_texture;
|
graphics_get_texture_type *get_texture;
|
||||||
graphics_fill_texture_type *fill_texture;
|
graphics_fill_texture_type *fill_texture;
|
||||||
|
graphics_free_texture_type *free_texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(STATIC_LINK_API)
|
#if defined(STATIC_LINK_API)
|
||||||
internal u32 graphics_get_texture(Vec3_i32 dim, Texture_Kind texture_kind);
|
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 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
|
#undef STATIC_LINK_API
|
||||||
|
|
||||||
#elif defined(DYNAMIC_LINK_API)
|
#elif defined(DYNAMIC_LINK_API)
|
||||||
global graphics_get_texture_type *graphics_get_texture = 0;
|
global graphics_get_texture_type *graphics_get_texture = 0;
|
||||||
global graphics_fill_texture_type *graphics_fill_texture = 0;
|
global graphics_fill_texture_type *graphics_fill_texture = 0;
|
||||||
|
global graphics_free_texture_type *graphics_free_texture = 0;
|
||||||
#undef DYNAMIC_LINK_API
|
#undef DYNAMIC_LINK_API
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
struct Metal_Buffer{
|
struct Metal_Buffer{
|
||||||
Node node;
|
Node node;
|
||||||
|
|
||||||
id<MTLBuffer> buffer;
|
id<MTLBuffer> buffer;
|
||||||
u32 size;
|
u32 size;
|
||||||
u64 last_reuse_time;
|
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.
|
// NOTE(yuval): This is a locator used to describe where a specific slot is located.
|
||||||
union Metal_Texture_Slot_Locator{
|
union Metal_Texture_Slot_Locator{
|
||||||
u32 packed;
|
u32 packed;
|
||||||
|
|
||||||
struct{
|
struct{
|
||||||
u16 bucket_index;
|
u16 bucket_index;
|
||||||
u16 slot_index;
|
u16 slot_index;
|
||||||
|
@ -34,7 +34,7 @@ union Metal_Texture_Slot_Locator{
|
||||||
struct Metal_Texture_Slot{
|
struct Metal_Texture_Slot{
|
||||||
// NOTE(yuval): This is a pointer to the next texture in the free texture slots list
|
// NOTE(yuval): This is a pointer to the next texture in the free texture slots list
|
||||||
Metal_Texture_Slot *next;
|
Metal_Texture_Slot *next;
|
||||||
|
|
||||||
Metal_Texture texture;
|
Metal_Texture texture;
|
||||||
Metal_Texture_Slot_Locator locator;
|
Metal_Texture_Slot_Locator locator;
|
||||||
};
|
};
|
||||||
|
@ -52,12 +52,12 @@ struct Metal_Texture_Slot_List{
|
||||||
Metal_Texture_Slot_Bucket *first_bucket;
|
Metal_Texture_Slot_Bucket *first_bucket;
|
||||||
Metal_Texture_Slot_Bucket *last_bucket;
|
Metal_Texture_Slot_Bucket *last_bucket;
|
||||||
u16 bucket_count;
|
u16 bucket_count;
|
||||||
|
|
||||||
Metal_Texture_Slot *first_free_slot;
|
Metal_Texture_Slot *first_free_slot;
|
||||||
Metal_Texture_Slot *last_free_slot;
|
Metal_Texture_Slot *last_free_slot;
|
||||||
};
|
};
|
||||||
|
|
||||||
global_const u32 metal__invalid_texture_slot_locator = (u32)-1;
|
global_const u32 metal__invalid_texture_slot_locator = 0;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ global_const u32 metal__invalid_texture_slot_locator = (u32)-1;
|
||||||
- (u32)get_texture_of_dim:(Vec3_i32)dim kind:(Texture_Kind)kind;
|
- (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;
|
- (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)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_locator:(Metal_Texture_Slot_Locator)locator;
|
||||||
- (Metal_Texture_Slot*)get_texture_slot_at_handle:(u32)handle;
|
- (Metal_Texture_Slot*)get_texture_slot_at_handle:(u32)handle;
|
||||||
|
|
||||||
|
@ -175,15 +176,15 @@ return(out_color);
|
||||||
function Metal_Buffer*
|
function Metal_Buffer*
|
||||||
metal__make_buffer(u32 size, id<MTLDevice> device){
|
metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
Metal_Buffer *result = (Metal_Buffer*)malloc(sizeof(Metal_Buffer));
|
Metal_Buffer *result = (Metal_Buffer*)malloc(sizeof(Metal_Buffer));
|
||||||
|
|
||||||
// NOTE(yuval): Create the vertex buffer
|
// NOTE(yuval): Create the vertex buffer
|
||||||
MTLResourceOptions options = MTLCPUCacheModeWriteCombined|MTLResourceStorageModeManaged;
|
MTLResourceOptions options = MTLCPUCacheModeWriteCombined|MTLResourceStorageModeManaged;
|
||||||
result->buffer = [device newBufferWithLength:size options:options];
|
result->buffer = [device newBufferWithLength:size options:options];
|
||||||
result->size = size;
|
result->size = size;
|
||||||
|
|
||||||
// NOTE(yuval): Set the last_reuse_time to the current time
|
// NOTE(yuval): Set the last_reuse_time to the current time
|
||||||
result->last_reuse_time = system_now_time();
|
result->last_reuse_time = system_now_time();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,15 +192,15 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
|
|
||||||
@implementation Metal_Renderer{
|
@implementation Metal_Renderer{
|
||||||
Render_Target *_target;
|
Render_Target *_target;
|
||||||
|
|
||||||
id<MTLDevice> _device;
|
id<MTLDevice> _device;
|
||||||
id<MTLRenderPipelineState> _pipeline_state;
|
id<MTLRenderPipelineState> _pipeline_state;
|
||||||
id<MTLCommandQueue> _command_queue;
|
id<MTLCommandQueue> _command_queue;
|
||||||
id<MTLCaptureScope> _capture_scope;
|
id<MTLCaptureScope> _capture_scope;
|
||||||
|
|
||||||
Node _buffer_cache;
|
Node _buffer_cache;
|
||||||
u64 _last_buffer_cache_purge_time;
|
u64 _last_buffer_cache_purge_time;
|
||||||
|
|
||||||
Metal_Texture_Slot_List _texture_slots;
|
Metal_Texture_Slot_List _texture_slots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,33 +209,33 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
if (self == nil){
|
if (self == nil){
|
||||||
return(nil);
|
return(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
_target = target;
|
_target = target;
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
|
||||||
_device = mtk_view.device;
|
_device = mtk_view.device;
|
||||||
|
|
||||||
// NOTE(yuval): Compile the shaders
|
// NOTE(yuval): Compile the shaders
|
||||||
id<MTLFunction> vertex_function = nil;
|
id<MTLFunction> vertex_function = nil;
|
||||||
id<MTLFunction> fragment_function = nil;
|
id<MTLFunction> fragment_function = nil;
|
||||||
{
|
{
|
||||||
NSString *shaders_source_str = [NSString stringWithUTF8String:metal__shaders_source];
|
NSString *shaders_source_str = [NSString stringWithUTF8String:metal__shaders_source];
|
||||||
|
|
||||||
MTLCompileOptions *options = [[MTLCompileOptions alloc] init];
|
MTLCompileOptions *options = [[MTLCompileOptions alloc] init];
|
||||||
options.fastMathEnabled = YES;
|
options.fastMathEnabled = YES;
|
||||||
|
|
||||||
id<MTLLibrary> shader_library = [_device newLibraryWithSource:shaders_source_str
|
id<MTLLibrary> shader_library = [_device newLibraryWithSource:shaders_source_str
|
||||||
options:options error:&error];
|
options:options error:&error];
|
||||||
vertex_function = [shader_library newFunctionWithName:@"vertex_shader"];
|
vertex_function = [shader_library newFunctionWithName:@"vertex_shader"];
|
||||||
fragment_function = [shader_library newFunctionWithName:@"fragment_shader"];
|
fragment_function = [shader_library newFunctionWithName:@"fragment_shader"];
|
||||||
|
|
||||||
[options release];
|
[options release];
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(error == nil);
|
Assert(error == nil);
|
||||||
Assert((vertex_function != nil) && (fragment_function != nil));
|
Assert((vertex_function != nil) && (fragment_function != nil));
|
||||||
|
|
||||||
// NOTE(yuval): Configure the pipeline descriptor
|
// NOTE(yuval): Configure the pipeline descriptor
|
||||||
{
|
{
|
||||||
MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
|
MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
|
||||||
|
@ -253,7 +254,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
vertexDescriptor.layouts[0].stepRate = 1;
|
vertexDescriptor.layouts[0].stepRate = 1;
|
||||||
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||||
vertexDescriptor.layouts[0].stride = sizeof(Render_Vertex);
|
vertexDescriptor.layouts[0].stride = sizeof(Render_Vertex);
|
||||||
|
|
||||||
MTLRenderPipelineDescriptor *pipeline_state_descriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
MTLRenderPipelineDescriptor *pipeline_state_descriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||||
pipeline_state_descriptor.label = @"4coder Metal Renderer Pipeline";
|
pipeline_state_descriptor.label = @"4coder Metal Renderer Pipeline";
|
||||||
pipeline_state_descriptor.vertexFunction = vertex_function;
|
pipeline_state_descriptor.vertexFunction = vertex_function;
|
||||||
|
@ -267,23 +268,28 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
pipeline_state_descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
pipeline_state_descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||||
pipeline_state_descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
pipeline_state_descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||||
pipeline_state_descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
pipeline_state_descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||||
|
|
||||||
_pipeline_state = [_device newRenderPipelineStateWithDescriptor:pipeline_state_descriptor
|
_pipeline_state = [_device newRenderPipelineStateWithDescriptor:pipeline_state_descriptor
|
||||||
error:&error];
|
error:&error];
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(error == nil);
|
Assert(error == nil);
|
||||||
|
|
||||||
// NOTE(yuval): Create the command queue
|
// NOTE(yuval): Create the command queue
|
||||||
_command_queue = [_device newCommandQueue];
|
_command_queue = [_device newCommandQueue];
|
||||||
|
|
||||||
// NOTE(yuval): Initialize buffer caching
|
// NOTE(yuval): Initialize buffer caching
|
||||||
dll_init_sentinel(&_buffer_cache);
|
dll_init_sentinel(&_buffer_cache);
|
||||||
_last_buffer_cache_purge_time = system_now_time();
|
_last_buffer_cache_purge_time = system_now_time();
|
||||||
|
|
||||||
// NOTE(yuval): Initialize the texture slot list
|
// NOTE(yuval): Initialize the texture slot list
|
||||||
block_zero_struct(&_texture_slots);
|
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
|
// NOTE(yuval): Create the fallback texture
|
||||||
_target->fallback_texture_id = [self get_texture_of_dim:V3i32(2, 2, 1)
|
_target->fallback_texture_id = [self get_texture_of_dim:V3i32(2, 2, 1)
|
||||||
kind:TextureKind_Mono];
|
kind:TextureKind_Mono];
|
||||||
|
@ -293,12 +299,12 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
pos:V3i32(0, 0, 0)
|
pos:V3i32(0, 0, 0)
|
||||||
dim:V3i32(2, 2, 1)
|
dim:V3i32(2, 2, 1)
|
||||||
data:white_block];
|
data:white_block];
|
||||||
|
|
||||||
// NOTE(yuval): Create a capture scope for gpu frame capture
|
// NOTE(yuval): Create a capture scope for gpu frame capture
|
||||||
_capture_scope = [[MTLCaptureManager sharedCaptureManager]
|
_capture_scope = [[MTLCaptureManager sharedCaptureManager]
|
||||||
newCaptureScopeWithDevice:_device];
|
newCaptureScopeWithDevice:_device];
|
||||||
_capture_scope.label = @"4coder Metal Capture Scope";
|
_capture_scope.label = @"4coder Metal Capture Scope";
|
||||||
|
|
||||||
return(self);
|
return(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,14 +316,14 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
#if FRED_INTERNAL
|
#if FRED_INTERNAL
|
||||||
[_capture_scope beginScope];
|
[_capture_scope beginScope];
|
||||||
#endif
|
#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).
|
// 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];
|
CGSize drawable_size = [view drawableSize];
|
||||||
i32 width = (i32)Min(_target->width, drawable_size.width);
|
i32 width = (i32)Min(_target->width, drawable_size.width);
|
||||||
i32 height = (i32)Min(_target->height, drawable_size.height);
|
i32 height = (i32)Min(_target->height, drawable_size.height);
|
||||||
|
|
||||||
Font_Set *font_set = (Font_Set*)_target->font_set;
|
Font_Set *font_set = (Font_Set*)_target->font_set;
|
||||||
|
|
||||||
// NOTE(yuval): Free any textures in the target's texture free list
|
// NOTE(yuval): Free any textures in the target's texture free list
|
||||||
for (Render_Free_Texture *free_texture = _target->free_texture_first;
|
for (Render_Free_Texture *free_texture = _target->free_texture_first;
|
||||||
free_texture;
|
free_texture;
|
||||||
|
@ -329,27 +335,27 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
}
|
}
|
||||||
_target->free_texture_first = 0;
|
_target->free_texture_first = 0;
|
||||||
_target->free_texture_last = 0;
|
_target->free_texture_last = 0;
|
||||||
|
|
||||||
// NOTE(yuval): Create the command buffer
|
// NOTE(yuval): Create the command buffer
|
||||||
id<MTLCommandBuffer> command_buffer = [_command_queue commandBuffer];
|
id<MTLCommandBuffer> command_buffer = [_command_queue commandBuffer];
|
||||||
command_buffer.label = @"4coder Metal Render Command";
|
command_buffer.label = @"4coder Metal Render Command";
|
||||||
|
|
||||||
// NOTE(yuval): Obtain the render pass descriptor from the renderer's view
|
// NOTE(yuval): Obtain the render pass descriptor from the renderer's view
|
||||||
MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor;
|
MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor;
|
||||||
if (render_pass_descriptor != nil){
|
if (render_pass_descriptor != nil){
|
||||||
render_pass_descriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f);
|
render_pass_descriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
// NOTE(yuval): Create the render command encoder
|
// NOTE(yuval): Create the render command encoder
|
||||||
id<MTLRenderCommandEncoder> render_encoder =
|
id<MTLRenderCommandEncoder> render_encoder =
|
||||||
[command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor];
|
[command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor];
|
||||||
render_encoder.label = @"4coder Render Encoder";
|
render_encoder.label = @"4coder Render Encoder";
|
||||||
|
|
||||||
// NOTE(yuval): Set the region of the drawable to draw into
|
// 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}];
|
[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
|
// NOTE(yuval): Set the render pipeline to use for drawing
|
||||||
[render_encoder setRenderPipelineState:_pipeline_state];
|
[render_encoder setRenderPipelineState:_pipeline_state];
|
||||||
|
|
||||||
// NOTE(yuval): Calculate the projection matrix
|
// NOTE(yuval): Calculate the projection matrix
|
||||||
float left = 0, right = (float)width;
|
float left = 0, right = (float)width;
|
||||||
float bottom = (float)height, top = 0;
|
float bottom = (float)height, top = 0;
|
||||||
|
@ -361,7 +367,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)),
|
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)),
|
||||||
-(near_depth / (far_depth - near_depth)), 1.0f
|
-(near_depth / (far_depth - near_depth)), 1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(yuval): Calculate required vertex buffer size
|
// NOTE(yuval): Calculate required vertex buffer size
|
||||||
i32 all_vertex_count = 0;
|
i32 all_vertex_count = 0;
|
||||||
for (Render_Group *group = _target->group_first;
|
for (Render_Group *group = _target->group_first;
|
||||||
|
@ -369,22 +375,22 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
group = group->next){
|
group = group->next){
|
||||||
all_vertex_count += group->vertex_list.vertex_count;
|
all_vertex_count += group->vertex_list.vertex_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 vertex_buffer_size = (all_vertex_count * sizeof(Render_Vertex));
|
u32 vertex_buffer_size = (all_vertex_count * sizeof(Render_Vertex));
|
||||||
|
|
||||||
// NOTE(yuval): Find & Get a vertex buffer matching the required size
|
// NOTE(yuval): Find & Get a vertex buffer matching the required size
|
||||||
Metal_Buffer *buffer = [self get_reusable_buffer_with_size:vertex_buffer_size];
|
Metal_Buffer *buffer = [self get_reusable_buffer_with_size:vertex_buffer_size];
|
||||||
|
|
||||||
// NOTE(yuval): Pass the vertex buffer to the vertex shader
|
// NOTE(yuval): Pass the vertex buffer to the vertex shader
|
||||||
[render_encoder setVertexBuffer:buffer->buffer
|
[render_encoder setVertexBuffer:buffer->buffer
|
||||||
offset:0
|
offset:0
|
||||||
atIndex:0];
|
atIndex:0];
|
||||||
|
|
||||||
// NOTE(yuval): Pass the projection matrix to the vertex shader
|
// NOTE(yuval): Pass the projection matrix to the vertex shader
|
||||||
[render_encoder setVertexBytes:&proj
|
[render_encoder setVertexBytes:&proj
|
||||||
length:sizeof(proj)
|
length:sizeof(proj)
|
||||||
atIndex:1];
|
atIndex:1];
|
||||||
|
|
||||||
u32 buffer_offset = 0;
|
u32 buffer_offset = 0;
|
||||||
for (Render_Group *group = _target->group_first;
|
for (Render_Group *group = _target->group_first;
|
||||||
group;
|
group;
|
||||||
|
@ -392,21 +398,21 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
// NOTE(yuval): Set scissor rect
|
// NOTE(yuval): Set scissor rect
|
||||||
{
|
{
|
||||||
Rect_i32 box = Ri32(group->clip_box);
|
Rect_i32 box = Ri32(group->clip_box);
|
||||||
|
|
||||||
NSUInteger x0 = (NSUInteger)Min(Max(0, box.x0), width - 1);
|
NSUInteger x0 = (NSUInteger)Min(Max(0, box.x0), width - 1);
|
||||||
NSUInteger x1 = (NSUInteger)Min(Max(0, box.x1), width);
|
NSUInteger x1 = (NSUInteger)Min(Max(0, box.x1), width);
|
||||||
NSUInteger y0 = (NSUInteger)Min(Max(0, box.y0), height - 1);
|
NSUInteger y0 = (NSUInteger)Min(Max(0, box.y0), height - 1);
|
||||||
NSUInteger y1 = (NSUInteger)Min(Max(0, box.y1), height);
|
NSUInteger y1 = (NSUInteger)Min(Max(0, box.y1), height);
|
||||||
|
|
||||||
MTLScissorRect scissor_rect;
|
MTLScissorRect scissor_rect;
|
||||||
scissor_rect.x = x0;
|
scissor_rect.x = x0;
|
||||||
scissor_rect.y = y0;
|
scissor_rect.y = y0;
|
||||||
scissor_rect.width = (x1 - x0);
|
scissor_rect.width = (x1 - x0);
|
||||||
scissor_rect.height = (y1 - y0);
|
scissor_rect.height = (y1 - y0);
|
||||||
|
|
||||||
[render_encoder setScissorRect:scissor_rect];
|
[render_encoder setScissorRect:scissor_rect];
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 vertex_count = group->vertex_list.vertex_count;
|
i32 vertex_count = group->vertex_list.vertex_count;
|
||||||
if (vertex_count > 0){
|
if (vertex_count > 0){
|
||||||
// NOTE(yuval): Bind a texture
|
// NOTE(yuval): Bind a texture
|
||||||
|
@ -422,10 +428,10 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
encoder:render_encoder];
|
encoder:render_encoder];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(yuval): Copy the vertex data to the vertex buffer
|
// NOTE(yuval): Copy the vertex data to the vertex buffer
|
||||||
{
|
{
|
||||||
|
|
||||||
u8 *group_buffer_contents = (u8*)[buffer->buffer contents] + buffer_offset;
|
u8 *group_buffer_contents = (u8*)[buffer->buffer contents] + buffer_offset;
|
||||||
u8 *cursor = group_buffer_contents;
|
u8 *cursor = group_buffer_contents;
|
||||||
for (Render_Vertex_Array_Node *node = group->vertex_list.first;
|
for (Render_Vertex_Array_Node *node = group->vertex_list.first;
|
||||||
|
@ -435,39 +441,39 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
memcpy(cursor, node->vertices, size);
|
memcpy(cursor, node->vertices, size);
|
||||||
cursor += size;
|
cursor += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSUInteger data_size = (NSUInteger)(cursor - group_buffer_contents);
|
NSUInteger data_size = (NSUInteger)(cursor - group_buffer_contents);
|
||||||
NSRange modify_range = NSMakeRange(buffer_offset, data_size);
|
NSRange modify_range = NSMakeRange(buffer_offset, data_size);
|
||||||
[buffer->buffer didModifyRange:modify_range];
|
[buffer->buffer didModifyRange:modify_range];
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(yuval): Set the vertex buffer offset to the beginning of the group's vertices
|
// NOTE(yuval): Set the vertex buffer offset to the beginning of the group's vertices
|
||||||
[render_encoder setVertexBufferOffset:buffer_offset atIndex:0];
|
[render_encoder setVertexBufferOffset:buffer_offset atIndex:0];
|
||||||
|
|
||||||
// NOTE(yuval): Draw the vertices
|
// NOTE(yuval): Draw the vertices
|
||||||
[render_encoder drawPrimitives:MTLPrimitiveTypeTriangle
|
[render_encoder drawPrimitives:MTLPrimitiveTypeTriangle
|
||||||
vertexStart:0
|
vertexStart:0
|
||||||
vertexCount:vertex_count];
|
vertexCount:vertex_count];
|
||||||
|
|
||||||
buffer_offset += (vertex_count * sizeof(Render_Vertex));
|
buffer_offset += (vertex_count * sizeof(Render_Vertex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[render_encoder endEncoding];
|
[render_encoder endEncoding];
|
||||||
|
|
||||||
// NOTE(yuval): Schedule a present once the framebuffer is complete using the current drawable
|
// NOTE(yuval): Schedule a present once the framebuffer is complete using the current drawable
|
||||||
[command_buffer presentDrawable:view.currentDrawable];
|
[command_buffer presentDrawable:view.currentDrawable];
|
||||||
|
|
||||||
[command_buffer addCompletedHandler:^(id<MTLCommandBuffer>){
|
[command_buffer addCompletedHandler:^(id<MTLCommandBuffer>){
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[self add_reusable_buffer:buffer];
|
[self add_reusable_buffer:buffer];
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(yuval): Finalize rendering here and push the command buffer to the GPU
|
// NOTE(yuval): Finalize rendering here and push the command buffer to the GPU
|
||||||
[command_buffer commit];
|
[command_buffer commit];
|
||||||
|
|
||||||
#if FRED_INTERNAL
|
#if FRED_INTERNAL
|
||||||
[_capture_scope endScope];
|
[_capture_scope endScope];
|
||||||
#endif
|
#endif
|
||||||
|
@ -475,14 +481,14 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
|
|
||||||
- (u32)get_texture_of_dim:(Vec3_i32)dim kind:(Texture_Kind)kind{
|
- (u32)get_texture_of_dim:(Vec3_i32)dim kind:(Texture_Kind)kind{
|
||||||
u32 handle = metal__invalid_texture_slot_locator;
|
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
|
// 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){
|
if (!_texture_slots.first_free_slot){
|
||||||
// NOTE(yuval): Assert that the next bucket's index can fit in a u16
|
// NOTE(yuval): Assert that the next bucket's index can fit in a u16
|
||||||
Assert(_texture_slots.bucket_count < ((u16)-1));
|
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);
|
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;
|
for (u16 slot_index = 0;
|
||||||
slot_index < ArrayCount(bucket->slots);
|
slot_index < ArrayCount(bucket->slots);
|
||||||
++slot_index){
|
++slot_index){
|
||||||
|
@ -490,63 +496,67 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
block_zero_struct(slot);
|
block_zero_struct(slot);
|
||||||
slot->locator.bucket_index = _texture_slots.bucket_count;
|
slot->locator.bucket_index = _texture_slots.bucket_count;
|
||||||
slot->locator.slot_index = slot_index;
|
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_free_slot, _texture_slots.last_free_slot, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
sll_queue_push(_texture_slots.first_bucket, _texture_slots.last_bucket, bucket);
|
sll_queue_push(_texture_slots.first_bucket, _texture_slots.last_bucket, bucket);
|
||||||
_texture_slots.bucket_count += 1;
|
_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).
|
// 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){
|
if (_texture_slots.first_free_slot){
|
||||||
Metal_Texture_Slot *texture_slot = _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);
|
sll_queue_pop(_texture_slots.first_free_slot, _texture_slots.last_free_slot);
|
||||||
texture_slot->next = 0;
|
texture_slot->next = 0;
|
||||||
|
|
||||||
// NOTE(yuval): Create a texture descriptor.
|
// NOTE(yuval): Create a texture descriptor.
|
||||||
MTLTextureDescriptor *texture_descriptor = [[MTLTextureDescriptor alloc] init];
|
MTLTextureDescriptor *texture_descriptor = [[MTLTextureDescriptor alloc] init];
|
||||||
texture_descriptor.textureType = MTLTextureType2DArray;
|
texture_descriptor.textureType = MTLTextureType2DArray;
|
||||||
texture_descriptor.pixelFormat = MTLPixelFormatR8Unorm;
|
texture_descriptor.pixelFormat = MTLPixelFormatR8Unorm;
|
||||||
texture_descriptor.width = dim.x;
|
texture_descriptor.width = dim.x;
|
||||||
texture_descriptor.height = dim.y;
|
texture_descriptor.height = dim.y;
|
||||||
texture_descriptor.depth = dim.z;
|
texture_descriptor.arrayLength = dim.z;
|
||||||
|
|
||||||
// NOTE(yuval): Create the texture from the device using the descriptor and add it to the textures array.
|
// 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];
|
Metal_Texture texture = [_device newTextureWithDescriptor:texture_descriptor];
|
||||||
texture_slot->texture = texture;
|
texture_slot->texture = texture;
|
||||||
|
|
||||||
handle = texture_slot->locator.packed;
|
handle = texture_slot->locator.packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (b32)fill_texture:(u32)handle kind:(Texture_Kind)kind pos:(Vec3_i32)p dim:(Vec3_i32)dim data:(void*)data{
|
- (b32)fill_texture:(u32)handle kind:(Texture_Kind)kind pos:(Vec3_i32)p dim:(Vec3_i32)dim data:(void*)data{
|
||||||
b32 result = false;
|
b32 result = false;
|
||||||
|
|
||||||
if (data){
|
if (data){
|
||||||
Metal_Texture_Slot *texture_slot = [self get_texture_slot_at_handle:handle];
|
Metal_Texture_Slot *texture_slot = [self get_texture_slot_at_handle:handle];
|
||||||
if (texture_slot){
|
if (texture_slot){
|
||||||
Metal_Texture texture = texture_slot->texture;
|
Metal_Texture texture = texture_slot->texture;
|
||||||
|
|
||||||
if (texture != 0){
|
if (texture != 0){
|
||||||
|
// https://developer.apple.com/documentation/metal/mtlregion
|
||||||
|
// for 2d texture origin.z is 0, and depth is 1
|
||||||
MTLRegion replace_region = {
|
MTLRegion replace_region = {
|
||||||
{(NSUInteger)p.x, (NSUInteger)p.y, (NSUInteger)p.z},
|
{(NSUInteger)p.x, (NSUInteger)p.y, 0},
|
||||||
{(NSUInteger)dim.x, (NSUInteger)dim.y, (NSUInteger)dim.z}
|
{(NSUInteger)dim.x, (NSUInteger)dim.y, 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(yuval): Fill the texture with data
|
// NOTE(yuval): Fill the texture with data
|
||||||
[texture replaceRegion:replace_region
|
[texture replaceRegion:replace_region
|
||||||
mipmapLevel:0
|
mipmapLevel:0
|
||||||
|
slice:p.z
|
||||||
withBytes:data
|
withBytes:data
|
||||||
bytesPerRow:dim.x];
|
bytesPerRow:dim.x
|
||||||
|
bytesPerImage:0];
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,41 +571,49 @@ 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*)get_texture_slot_at_locator:(Metal_Texture_Slot_Locator)locator{
|
||||||
Metal_Texture_Slot *result = 0;
|
Metal_Texture_Slot *result = 0;
|
||||||
|
|
||||||
if (locator.packed != metal__invalid_texture_slot_locator){
|
if (locator.packed != metal__invalid_texture_slot_locator){
|
||||||
Metal_Texture_Slot_Bucket *bucket = _texture_slots.first_bucket;
|
Metal_Texture_Slot_Bucket *bucket = _texture_slots.first_bucket;
|
||||||
for (u16 bucket_index = 0;
|
for (u16 bucket_index = 0;
|
||||||
(bucket_index < locator.bucket_index) && bucket;
|
(bucket_index < locator.bucket_index) && bucket;
|
||||||
++bucket_index, bucket = bucket->next);
|
++bucket_index, bucket = bucket->next);
|
||||||
|
|
||||||
if (bucket && (locator.slot_index < metal__texture_slots_per_bucket)){
|
if (bucket && (locator.slot_index < metal__texture_slots_per_bucket)){
|
||||||
result = &bucket->slots[locator.slot_index];
|
result = &bucket->slots[locator.slot_index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (Metal_Texture_Slot*)get_texture_slot_at_handle:(u32)handle{
|
- (Metal_Texture_Slot*)get_texture_slot_at_handle:(u32)handle{
|
||||||
Metal_Texture_Slot_Locator locator;
|
Metal_Texture_Slot_Locator locator;
|
||||||
locator.packed = handle;
|
locator.packed = handle;
|
||||||
|
|
||||||
Metal_Texture_Slot *result = [self get_texture_slot_at_locator:locator];
|
Metal_Texture_Slot *result = [self get_texture_slot_at_locator:locator];
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (Metal_Buffer*)get_reusable_buffer_with_size:(NSUInteger)size{
|
- (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
|
// NOTE(yuval): This routine is a modified version of Dear ImGui's MetalContext::dequeueReusableBufferOfLength in imgui_impl_metal.mm
|
||||||
|
|
||||||
u64 now = system_now_time();
|
u64 now = system_now_time();
|
||||||
|
|
||||||
// NOTE(yuval): Purge old buffers that haven't been useful for a while
|
// NOTE(yuval): Purge old buffers that haven't been useful for a while
|
||||||
if ((now - _last_buffer_cache_purge_time) > 1000000){
|
if ((now - _last_buffer_cache_purge_time) > 1000000){
|
||||||
Node prev_buffer_cache = _buffer_cache;
|
Node prev_buffer_cache = _buffer_cache;
|
||||||
dll_init_sentinel(&_buffer_cache);
|
dll_init_sentinel(&_buffer_cache);
|
||||||
|
|
||||||
for (Node *node = prev_buffer_cache.next;
|
for (Node *node = prev_buffer_cache.next;
|
||||||
node != &_buffer_cache;
|
node != &_buffer_cache;
|
||||||
node = node->next){
|
node = node->next){
|
||||||
|
@ -604,10 +622,10 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
dll_insert(&_buffer_cache, node);
|
dll_insert(&_buffer_cache, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_last_buffer_cache_purge_time = now;
|
_last_buffer_cache_purge_time = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(yuval): See if we have a buffer we can reuse
|
// NOTE(yuval): See if we have a buffer we can reuse
|
||||||
Metal_Buffer *best_candidate = 0;
|
Metal_Buffer *best_candidate = 0;
|
||||||
for (Node *node = _buffer_cache.next;
|
for (Node *node = _buffer_cache.next;
|
||||||
|
@ -618,7 +636,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
best_candidate = candidate;
|
best_candidate = candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Metal_Buffer *result;
|
Metal_Buffer *result;
|
||||||
if (best_candidate){
|
if (best_candidate){
|
||||||
// NOTE(yuval): A best candidate has been found! Remove it from the buffer list and set its last reuse time.
|
// NOTE(yuval): A best candidate has been found! Remove it from the buffer list and set its last reuse time.
|
||||||
|
@ -629,13 +647,13 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
// NOTE(yuval): No luck; make a new buffer.
|
// NOTE(yuval): No luck; make a new buffer.
|
||||||
result = metal__make_buffer(size, _device);
|
result = metal__make_buffer(size, _device);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)add_reusable_buffer:(Metal_Buffer*)buffer{
|
- (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
|
// 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);
|
dll_insert(&_buffer_cache, &buffer->node);
|
||||||
}
|
}
|
||||||
@end
|
@end
|
|
@ -53,6 +53,11 @@ gl__fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 di
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
gl__free_texture(u32 texture){
|
||||||
|
glDeleteTextures(1, &texture);
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam){
|
gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam){
|
||||||
switch (id){
|
switch (id){
|
||||||
|
@ -68,7 +73,7 @@ gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsiz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *gl__header = R"foo(#version 130
|
char *gl__header = R"foo(#version 150
|
||||||
)foo";
|
)foo";
|
||||||
|
|
||||||
char *gl__vertex = R"foo(
|
char *gl__vertex = R"foo(
|
||||||
|
@ -107,20 +112,20 @@ char *gl__fragment = R"foo(
|
||||||
smooth in float half_thickness;
|
smooth in float half_thickness;
|
||||||
uniform sampler2DArray sampler;
|
uniform sampler2DArray sampler;
|
||||||
out vec4 out_color;
|
out vec4 out_color;
|
||||||
|
|
||||||
float rectangle_sd(vec2 p, vec2 b){
|
float rectangle_sd(vec2 p, vec2 b){
|
||||||
vec2 d = abs(p) - b;
|
vec2 d = abs(p) - b;
|
||||||
return(length(max(d, vec2(0.0, 0.0))) + min(max(d.x, d.y), 0.0));
|
return(length(max(d, vec2(0.0, 0.0))) + min(max(d.x, d.y), 0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
float has_thickness = (step(0.49, half_thickness));
|
float has_thickness = (step(0.49, half_thickness));
|
||||||
float does_not_have_thickness = 1.0 - has_thickness;
|
float does_not_have_thickness = 1.0 - has_thickness;
|
||||||
|
|
||||||
float sample_value = texture(sampler, uvw).r;
|
float sample_value = texture(sampler, uvw).r;
|
||||||
sample_value *= does_not_have_thickness;
|
sample_value *= does_not_have_thickness;
|
||||||
|
|
||||||
vec2 center = uvw.xy;
|
vec2 center = uvw.xy;
|
||||||
float roundness = uvw.z;
|
float roundness = uvw.z;
|
||||||
float sd = rectangle_sd(xy - center, adjusted_half_dim);
|
float sd = rectangle_sd(xy - center, adjusted_half_dim);
|
||||||
|
@ -128,7 +133,7 @@ char *gl__fragment = R"foo(
|
||||||
sd = abs(sd + half_thickness) - half_thickness;
|
sd = abs(sd + half_thickness) - half_thickness;
|
||||||
float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd);
|
float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd);
|
||||||
shape_value *= has_thickness;
|
shape_value *= has_thickness;
|
||||||
|
|
||||||
out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value));
|
out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value));
|
||||||
}
|
}
|
||||||
)foo";
|
)foo";
|
||||||
|
|
|
@ -588,6 +588,11 @@ graphics_fill_texture_sig(){
|
||||||
return(gl__fill_texture(texture_kind, texture, p, dim, data));
|
return(gl__fill_texture(texture_kind, texture, p, dim, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
graphics_free_texture_sig(){
|
||||||
|
gl__free_texture(texid);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
||||||
internal Face*
|
internal Face*
|
||||||
|
@ -700,8 +705,8 @@ glx_create_context(GLXFBConfig fb_config){
|
||||||
ctx = glXCreateNewContext(linuxvars.dpy, fb_config, GLX_RGBA_TYPE, 0, True);
|
ctx = glXCreateNewContext(linuxvars.dpy, fb_config, GLX_RGBA_TYPE, 0, True);
|
||||||
} else {
|
} else {
|
||||||
static const int context_attribs[] = {
|
static const int context_attribs[] = {
|
||||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
|
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
|
||||||
GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||||
#if GL_DEBUG_MODE
|
#if GL_DEBUG_MODE
|
||||||
GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB,
|
GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||||
|
@ -709,7 +714,6 @@ glx_create_context(GLXFBConfig fb_config){
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
//LOG("Creating GL 2.1 context... ");
|
|
||||||
ctx = glXCreateContextAttribsARB(linuxvars.dpy, fb_config, 0, True, context_attribs);
|
ctx = glXCreateContextAttribsARB(linuxvars.dpy, fb_config, 0, True, context_attribs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -976,6 +976,11 @@ graphics_fill_texture_sig(){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
graphics_free_texture_sig(){
|
||||||
|
renderer->free_texture(renderer, texid);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
/******************/
|
/******************/
|
||||||
|
|
|
@ -44,6 +44,12 @@ mac_fill_texture_sig(mac_metal__fill_texture){
|
||||||
return(result);
|
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*
|
function Mac_Metal*
|
||||||
mac_metal__init(NSWindow *window, Render_Target *target){
|
mac_metal__init(NSWindow *window, Render_Target *target){
|
||||||
// NOTE(yuval): Create the Mac Metal rendere
|
// NOTE(yuval): Create the Mac Metal rendere
|
||||||
|
@ -52,7 +58,8 @@ mac_metal__init(NSWindow *window, Render_Target *target){
|
||||||
metal->base.render = mac_metal__render;
|
metal->base.render = mac_metal__render;
|
||||||
metal->base.get_texture = mac_metal__get_texture;
|
metal->base.get_texture = mac_metal__get_texture;
|
||||||
metal->base.fill_texture = mac_metal__fill_texture;
|
metal->base.fill_texture = mac_metal__fill_texture;
|
||||||
|
metal->base.free_texture = mac_metal__free_texture;
|
||||||
|
|
||||||
// NOTE(yuval): Create the Metal view
|
// NOTE(yuval): Create the Metal view
|
||||||
NSView *content_view = [window contentView];
|
NSView *content_view = [window contentView];
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,11 @@ mac_fill_texture_sig(mac_gl__fill_texture){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
mac_free_texture_sig(mac_gl__free_texture){
|
||||||
|
gl__free_texture(texture);
|
||||||
|
}
|
||||||
|
|
||||||
function Mac_OpenGL*
|
function Mac_OpenGL*
|
||||||
mac_gl__init(NSWindow *window, Render_Target *target){
|
mac_gl__init(NSWindow *window, Render_Target *target){
|
||||||
// NOTE(yuval): Create the Mac OpenGL Renderer
|
// NOTE(yuval): Create the Mac OpenGL Renderer
|
||||||
|
@ -152,6 +157,7 @@ mac_gl__init(NSWindow *window, Render_Target *target){
|
||||||
gl->base.render = mac_gl__render;
|
gl->base.render = mac_gl__render;
|
||||||
gl->base.get_texture = mac_gl__get_texture;
|
gl->base.get_texture = mac_gl__get_texture;
|
||||||
gl->base.fill_texture = mac_gl__fill_texture;
|
gl->base.fill_texture = mac_gl__fill_texture;
|
||||||
|
gl->base.free_texture = mac_gl__free_texture;
|
||||||
|
|
||||||
// NOTE(yuval): Create the OpenGL view
|
// NOTE(yuval): Create the OpenGL view
|
||||||
NSView *content_view = [window contentView];
|
NSView *content_view = [window contentView];
|
||||||
|
|
|
@ -18,6 +18,9 @@ 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)
|
#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);
|
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;
|
typedef i32 Mac_Renderer_Kind;
|
||||||
enum{
|
enum{
|
||||||
MacRenderer_OpenGL,
|
MacRenderer_OpenGL,
|
||||||
|
@ -31,6 +34,7 @@ struct Mac_Renderer{
|
||||||
|
|
||||||
mac_get_texture_type *get_texture;
|
mac_get_texture_type *get_texture;
|
||||||
mac_fill_texture_type *fill_texture;
|
mac_fill_texture_type *fill_texture;
|
||||||
|
mac_free_texture_type *free_texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
|
@ -0,0 +1,658 @@
|
||||||
|
|
||||||
|
#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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,8 @@
|
||||||
// #define FPS 144
|
// #define FPS 144
|
||||||
// #define frame_useconds (1000000 / FPS)
|
// #define frame_useconds (1000000 / FPS)
|
||||||
|
|
||||||
|
// #define WIN32_DX11
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "4coder_base_types.h"
|
#include "4coder_base_types.h"
|
||||||
|
@ -56,7 +58,6 @@
|
||||||
#define function static
|
#define function static
|
||||||
|
|
||||||
#include "win32_utf8.h"
|
#include "win32_utf8.h"
|
||||||
#include "win32_gl.h"
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
@ -447,6 +448,7 @@ win32_post_clipboard(Arena *scratch, char *text, i32 len){
|
||||||
SetClipboardData(CF_TEXT, memory_handle);
|
SetClipboardData(CF_TEXT, memory_handle);
|
||||||
}
|
}
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
win32vars.clipboard_sequence = GetClipboardSequenceNumber();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,14 +457,10 @@ system_get_clipboard_sig(){
|
||||||
String_Const_u8 result = {};
|
String_Const_u8 result = {};
|
||||||
DWORD new_number = GetClipboardSequenceNumber();
|
DWORD new_number = GetClipboardSequenceNumber();
|
||||||
if (new_number != win32vars.clipboard_sequence){
|
if (new_number != win32vars.clipboard_sequence){
|
||||||
win32vars.clipboard_sequence = new_number;
|
result = win32_read_clipboard_contents(win32vars.tctx, arena);
|
||||||
|
if (result.str != 0){
|
||||||
for (i32 R = 0; R < 8; ++R){
|
win32vars.clipboard_sequence = new_number;
|
||||||
result = win32_read_clipboard_contents(win32vars.tctx, arena);
|
}
|
||||||
if (result.str == 0){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
@ -649,18 +647,18 @@ system_cli_end_update_sig(){
|
||||||
|
|
||||||
function void
|
function void
|
||||||
os_popup_error(char *title, char *message){
|
os_popup_error(char *title, char *message){
|
||||||
MessageBoxA(0, title, message, MB_OK);
|
MessageBoxA(0, message, title, MB_OK);
|
||||||
ExitProcess(1);
|
ExitProcess(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "4ed_font_provider_freetype.h"
|
#include "4ed_font_provider_freetype.h"
|
||||||
#include "4ed_font_provider_freetype.cpp"
|
#include "4ed_font_provider_freetype.cpp"
|
||||||
|
|
||||||
#include <GL/gl.h>
|
#if defined( WIN32_DX11 )
|
||||||
#include "opengl/4ed_opengl_defines.h"
|
#include "win32_dx11.cpp"
|
||||||
#define GL_FUNC(N,R,P) typedef R (CALL_CONVENTION N##_Function)P; N##_Function *N = 0;
|
#else
|
||||||
#include "opengl/4ed_opengl_funcs.h"
|
#include "win32_opengl.cpp"
|
||||||
#include "opengl/4ed_opengl_render.cpp"
|
#endif
|
||||||
|
|
||||||
internal
|
internal
|
||||||
graphics_get_texture_sig(){
|
graphics_get_texture_sig(){
|
||||||
|
@ -672,6 +670,11 @@ graphics_fill_texture_sig(){
|
||||||
return(gl__fill_texture(texture_kind, texture, p, dim, data));
|
return(gl__fill_texture(texture_kind, texture, p, dim, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
graphics_free_texture_sig(){
|
||||||
|
gl__free_texture(texid);
|
||||||
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
font_make_face_sig(){
|
font_make_face_sig(){
|
||||||
return(ft__font_make_face(arena, description, scale_factor));
|
return(ft__font_make_face(arena, description, scale_factor));
|
||||||
|
@ -779,13 +782,13 @@ win32_keycode_init(void){
|
||||||
keycode_lookup_table[VK_NUMPAD8] = KeyCode_NumPad8;
|
keycode_lookup_table[VK_NUMPAD8] = KeyCode_NumPad8;
|
||||||
keycode_lookup_table[VK_NUMPAD9] = KeyCode_NumPad9;
|
keycode_lookup_table[VK_NUMPAD9] = KeyCode_NumPad9;
|
||||||
|
|
||||||
for (i32 i = 0xDF; i < 0xFF; i += 1){
|
for (i32 i = 0; i < 30; i += 1){
|
||||||
keycode_lookup_table[i] = KeyCode_Ex0 + 1;
|
keycode_lookup_table[0xDF + i] = KeyCode_Ex0 + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal b32
|
internal b32
|
||||||
keycode_physical_translaion_is_wrong(u64 vk){
|
keycode_physical_translation_is_wrong(u64 vk){
|
||||||
b32 result = false;
|
b32 result = false;
|
||||||
switch (vk){
|
switch (vk){
|
||||||
case VK_UP: case VK_DOWN: case VK_LEFT: case VK_RIGHT:
|
case VK_UP: case VK_DOWN: case VK_LEFT: case VK_RIGHT:
|
||||||
|
@ -823,6 +826,73 @@ win32_resize(i32 width, i32 height){
|
||||||
if (width > 0 && height > 0){
|
if (width > 0 && height > 0){
|
||||||
target.width = width;
|
target.width = width;
|
||||||
target.height = height;
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,10 +971,10 @@ internal void
|
||||||
date_time_from_win32_system_time(Date_Time *out, SYSTEMTIME *in){
|
date_time_from_win32_system_time(Date_Time *out, SYSTEMTIME *in){
|
||||||
out->year = in->wYear;
|
out->year = in->wYear;
|
||||||
out->mon = (u8)(in->wMonth - 1);
|
out->mon = (u8)(in->wMonth - 1);
|
||||||
out->day = (u8)(in->wDay - 1);
|
out->day = (u8)(in->wDay - 1);
|
||||||
out->hour = (u8)(in->wHour);
|
out->hour = (u8)(in->wHour);
|
||||||
out->min = (u8)(in->wMinute);
|
out->min = (u8)(in->wMinute);
|
||||||
out->sec = (u8)(in->wSecond);
|
out->sec = (u8)(in->wSecond);
|
||||||
out->msec = in->wMilliseconds;
|
out->msec = in->wMilliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1157,7 +1227,7 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
|
||||||
u64 vk = wParam;
|
u64 vk = wParam;
|
||||||
|
|
||||||
if (win32vars.key_mode == KeyMode_Physical &&
|
if (win32vars.key_mode == KeyMode_Physical &&
|
||||||
!keycode_physical_translaion_is_wrong(vk)){
|
!keycode_physical_translation_is_wrong(vk)){
|
||||||
UINT scan_code = ((lParam >> 16) & bitmask_8);
|
UINT scan_code = ((lParam >> 16) & bitmask_8);
|
||||||
vk = MapVirtualKeyEx(scan_code, MAPVK_VSC_TO_VK_EX, win32vars.kl_universal);
|
vk = MapVirtualKeyEx(scan_code, MAPVK_VSC_TO_VK_EX, win32vars.kl_universal);
|
||||||
}
|
}
|
||||||
|
@ -1191,7 +1261,7 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 ctrl = (controls->r_ctrl || (controls->l_ctrl && !controls->r_alt));
|
b8 ctrl = (controls->r_ctrl || (controls->l_ctrl && !controls->r_alt));
|
||||||
b8 alt = (controls->l_alt || (controls->r_alt && !controls->l_ctrl));
|
b8 alt = (controls->l_alt || (controls->r_alt && !controls->l_ctrl));
|
||||||
if (win32vars.lctrl_lalt_is_altgr && controls->l_alt && controls->l_ctrl){
|
if (win32vars.lctrl_lalt_is_altgr && controls->l_alt && controls->l_ctrl){
|
||||||
|
@ -1432,249 +1502,7 @@ 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-
|
//-
|
||||||
|
|
||||||
|
@ -1918,15 +1746,21 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
||||||
window_style |= WS_MAXIMIZE;
|
window_style |= WS_MAXIMIZE;
|
||||||
}
|
}
|
||||||
log_os(" windowed dimensions: %d, %d\n"
|
log_os(" windowed dimensions: %d, %d\n"
|
||||||
" initially maximized: %d",
|
" initially maximized: %d\n",
|
||||||
window_rect.right - window_rect.left,
|
window_rect.right - window_rect.left,
|
||||||
window_rect.bottom - window_rect.top,
|
window_rect.bottom - window_rect.top,
|
||||||
((window_style & WS_MAXIMIZE) != 0));
|
((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;
|
HGLRC window_opengl_context = 0;
|
||||||
if (!win32_gl_create_window(&win32vars.window_handle, &window_opengl_context, window_style, window_rect)){
|
if (!win32_gl_create_window(&win32vars.window_handle, &window_opengl_context, window_style, window_rect)){
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
log_os(" window created successfully\n");
|
log_os(" window created successfully\n");
|
||||||
|
|
||||||
|
@ -2027,7 +1861,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
||||||
|
|
||||||
// NOTE(allen): while we're doing this (and possibly sleeping)
|
// NOTE(allen): while we're doing this (and possibly sleeping)
|
||||||
// we can let async processes get there time in.
|
// 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;
|
b32 get_more_messages = true;
|
||||||
do{
|
do{
|
||||||
|
@ -2105,7 +1939,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
||||||
}
|
}
|
||||||
}while (get_more_messages);
|
}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
|
// NOTE(allen): Mouse Out of Window Detection
|
||||||
|
@ -2210,10 +2044,15 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
||||||
win32vars.lctrl_lalt_is_altgr = (b8)result.lctrl_lalt_is_altgr;
|
win32vars.lctrl_lalt_is_altgr = (b8)result.lctrl_lalt_is_altgr;
|
||||||
|
|
||||||
// NOTE(allen): render
|
// NOTE(allen): render
|
||||||
|
#if defined( WIN32_DX11 )
|
||||||
|
gl_render(&target);
|
||||||
|
g_dx11.swap_chain->Present( 1, 0 );
|
||||||
|
#else
|
||||||
HDC hdc = GetDC(win32vars.window_handle);
|
HDC hdc = GetDC(win32vars.window_handle);
|
||||||
gl_render(&target);
|
gl_render(&target);
|
||||||
SwapBuffers(hdc);
|
SwapBuffers(hdc);
|
||||||
ReleaseDC(win32vars.window_handle, hdc);
|
ReleaseDC(win32vars.window_handle, hdc);
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE(allen): toggle full screen
|
// NOTE(allen): toggle full screen
|
||||||
if (win32vars.do_toggle){
|
if (win32vars.do_toggle){
|
||||||
|
@ -2230,7 +2069,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): sleep a bit to cool off :)
|
// 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 timer_end = system_now_time();
|
||||||
u64 end_target = timer_start + frame_useconds;
|
u64 end_target = timer_start + frame_useconds;
|
||||||
|
@ -2249,6 +2088,10 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
||||||
win32vars.first = false;
|
win32vars.first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined( WIN32_DX11 ) && !SHIP_MODE
|
||||||
|
win32_gl_cleanup( );
|
||||||
|
#endif
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,544 @@
|
||||||
|
|
||||||
|
#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
|
|
@ -0,0 +1,257 @@
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
Loading…
Reference in New Issue