Merge branch 'win32' into orca

This commit is contained in:
Martin Fouilleul 2023-05-24 15:11:32 +02:00
commit 43c23627e2
20 changed files with 10099 additions and 8710 deletions

View File

@ -1,11 +1,11 @@
if not exist bin mkdir bin if not exist bin mkdir bin
set glsl_shaders=src\glsl_shaders\common.glsl src\glsl_shaders\blit_vertex.glsl src\glsl_shaders\blit_fragment.glsl src\glsl_shaders\clear_counters.glsl src\glsl_shaders\tile.glsl src\glsl_shaders\sort.glsl src\glsl_shaders\draw.glsl set glsl_shaders=src\glsl_shaders\common.glsl src\glsl_shaders\blit_vertex.glsl src\glsl_shaders\blit_fragment.glsl src\glsl_shaders\clear_counters.glsl src\glsl_shaders\tile.glsl src\glsl_shaders\sort.glsl src\glsl_shaders\draw.glsl
call python3 scripts\embed_text.py %glsl_shaders% --prefix=glsl_ --output src\glsl_shaders.h call python3 scripts\embed_text.py %glsl_shaders% --prefix=glsl_ --output src\glsl_shaders.h
set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers
set LIBS=user32.lib opengl32.lib gdi32.lib shcore.lib delayimp.lib dwmapi.lib /LIBPATH:./bin libEGL.dll.lib libGLESv2.dll.lib /DELAYLOAD:libEGL.dll /DELAYLOAD:libGLESv2.dll set LIBS=user32.lib opengl32.lib gdi32.lib shcore.lib delayimp.lib dwmapi.lib comctl32.lib ole32.lib shell32.lib /LIBPATH:./bin libEGL.dll.lib libGLESv2.dll.lib /DELAYLOAD:libEGL.dll /DELAYLOAD:libGLESv2.dll
cl /we4013 /Zi /Zc:preprocessor /DMP_BUILD_DLL /std:c11 %INCLUDES% src/milepost.c /Fo:bin/milepost.o /LD /link %LIBS% /OUT:bin/milepost.dll /IMPLIB:bin/milepost.dll.lib cl /we4013 /Zi /Zc:preprocessor /DMP_BUILD_DLL /std:c11 %INCLUDES% src/milepost.c /Fo:bin/milepost.o /LD /link /MANIFEST:EMBED /MANIFESTINPUT:src/win32_manifest.xml %LIBS% /OUT:bin/milepost.dll /IMPLIB:bin/milepost.dll.lib

View File

@ -1,209 +1,210 @@
/************************************************************//** /************************************************************//**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 30/07/2022 * @date: 30/07/2022
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include<stdlib.h>
#include<string.h> #include<stdio.h>
#include<errno.h> #include<string.h>
#include<errno.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h>
#include"milepost.h"
#include"milepost.h"
#define LOG_SUBSYSTEM "Main"
#define LOG_SUBSYSTEM "Main"
mg_font create_font()
{ mg_font create_font()
//NOTE(martin): create font {
str8 fontPath = mp_app_get_resource_path(mem_scratch(), "../resources/OpenSansLatinSubset.ttf"); //NOTE(martin): create font
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath); str8 fontPath = mp_app_get_resource_path(mem_scratch(), "../resources/OpenSansLatinSubset.ttf");
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath);
FILE* fontFile = fopen(fontPathCString, "r");
if(!fontFile) FILE* fontFile = fopen(fontPathCString, "r");
{ if(!fontFile)
log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno)); {
return(mg_font_nil()); log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno));
} return(mg_font_nil());
unsigned char* fontData = 0; }
fseek(fontFile, 0, SEEK_END); unsigned char* fontData = 0;
u32 fontDataSize = ftell(fontFile); fseek(fontFile, 0, SEEK_END);
rewind(fontFile); u32 fontDataSize = ftell(fontFile);
fontData = (unsigned char*)malloc(fontDataSize); rewind(fontFile);
fread(fontData, 1, fontDataSize, fontFile); fontData = (unsigned char*)malloc(fontDataSize);
fclose(fontFile); fread(fontData, 1, fontDataSize, fontFile);
fclose(fontFile);
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT, unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_LATIN_EXTENDED_A, UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
UNICODE_RANGE_LATIN_EXTENDED_B, UNICODE_RANGE_LATIN_EXTENDED_A,
UNICODE_RANGE_SPECIALS}; UNICODE_RANGE_LATIN_EXTENDED_B,
UNICODE_RANGE_SPECIALS};
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData); mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData);
return(font);
} return(font);
}
int main()
{ int main()
mp_init(); {
mp_clock_init(); //TODO put that in mp_init()? mp_init();
mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
mp_window window = mp_window_create(windowRect, "test", 0); mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window);
mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); //NOTE: create surface
mg_surface_swap_interval(surface, 0); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
mg_surface_swap_interval(surface, 0);
mg_canvas canvas = mg_canvas_create();
mg_canvas canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas))
{ if(mg_canvas_is_nil(canvas))
printf("Error: couldn't create canvas\n"); {
return(-1); printf("Error: couldn't create canvas\n");
} return(-1);
}
mg_font font = create_font();
mg_font font = create_font();
// start app
mp_window_bring_to_front(window); // start app
mp_window_focus(window); mp_window_bring_to_front(window);
mp_window_focus(window);
f32 x = 400, y = 300;
f32 speed = 0; f32 x = 400, y = 300;
f32 dx = speed, dy = speed; f32 speed = 0;
f64 frameTime = 0; f32 dx = speed, dy = speed;
f64 frameTime = 0;
while(!mp_should_quit())
{ while(!mp_should_quit())
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC); {
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0);
mp_event* event = 0; mp_pump_events(0);
while((event = mp_next_event(mem_scratch())) != 0) mp_event* event = 0;
{ while((event = mp_next_event(mem_scratch())) != 0)
switch(event->type) {
{ switch(event->type)
case MP_EVENT_WINDOW_CLOSE: {
{ case MP_EVENT_WINDOW_CLOSE:
mp_request_quit(); {
} break; mp_request_quit();
} break;
case MP_EVENT_KEYBOARD_KEY:
{ case MP_EVENT_KEYBOARD_KEY:
if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT) {
{ if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT)
f32 factor = (event->key.mods & MP_KEYMOD_SHIFT) ? 10 : 1; {
f32 factor = (event->key.mods & MP_KEYMOD_SHIFT) ? 10 : 1;
if(event->key.code == MP_KEY_LEFT)
{ if(event->key.code == MP_KEY_LEFT)
x-=0.3*factor; {
} x-=0.3*factor;
else if(event->key.code == MP_KEY_RIGHT) }
{ else if(event->key.code == MP_KEY_RIGHT)
x+=0.3*factor; {
} x+=0.3*factor;
else if(event->key.code == MP_KEY_UP) }
{ else if(event->key.code == MP_KEY_UP)
y-=0.3*factor; {
} y-=0.3*factor;
else if(event->key.code == MP_KEY_DOWN) }
{ else if(event->key.code == MP_KEY_DOWN)
y+=0.3*factor; {
} y+=0.3*factor;
} }
} break; }
} break;
default:
break; default:
} break;
} }
}
if(x-200 < 0)
{ if(x-200 < 0)
x = 200; {
dx = speed; x = 200;
} dx = speed;
if(x+200 > contentRect.w) }
{ if(x+200 > contentRect.w)
x = contentRect.w - 200; {
dx = -speed; x = contentRect.w - 200;
} dx = -speed;
if(y-200 < 0) }
{ if(y-200 < 0)
y = 200; {
dy = speed; y = 200;
} dy = speed;
if(y+200 > contentRect.h) }
{ if(y+200 > contentRect.h)
y = contentRect.h - 200; {
dy = -speed; y = contentRect.h - 200;
} dy = -speed;
x += dx; }
y += dy; x += dx;
y += dy;
// background
mg_set_color_rgba(0, 1, 1, 1); // background
mg_clear(); mg_set_color_rgba(0, 1, 1, 1);
mg_clear();
// head
mg_set_color_rgba(1, 1, 0, 1); // head
mg_set_color_rgba(1, 1, 0, 1);
mg_circle_fill(x, y, 200);
mg_circle_fill(x, y, 200);
// smile
f32 frown = frameTime > 0.033 ? -100 : 0; // smile
f32 frown = frameTime > 0.033 ? -100 : 0;
mg_set_color_rgba(0, 0, 0, 1);
mg_set_width(20); mg_set_color_rgba(0, 0, 0, 1);
mg_move_to(x-100, y+100); mg_set_width(20);
mg_cubic_to(x-50, y+150+frown, x+50, y+150+frown, x+100, y+100); mg_move_to(x-100, y+100);
mg_stroke(); mg_cubic_to(x-50, y+150+frown, x+50, y+150+frown, x+100, y+100);
mg_stroke();
// eyes
mg_ellipse_fill(x-70, y-50, 30, 50); // eyes
mg_ellipse_fill(x+70, y-50, 30, 50); mg_ellipse_fill(x-70, y-50, 30, 50);
mg_ellipse_fill(x+70, y-50, 30, 50);
// text
mg_set_color_rgba(0, 0, 1, 1); // text
mg_set_font(font); mg_set_color_rgba(0, 0, 1, 1);
mg_set_font_size(12); mg_set_font(font);
mg_move_to(50, 600-50); mg_set_font_size(12);
mg_move_to(50, 600-50);
str8 text = str8_pushf(mem_scratch(),
"Milepost vector graphics test program (frame time = %fs, fps = %f)...", str8 text = str8_pushf(mem_scratch(),
frameTime, "Milepost vector graphics test program (frame time = %fs, fps = %f)...",
1./frameTime); frameTime,
mg_text_outlines(text); 1./frameTime);
mg_fill(); mg_text_outlines(text);
mg_fill();
printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
frameTime, printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
1./frameTime); frameTime,
1./frameTime);
mg_surface_prepare(surface);
mg_render(surface, canvas); mg_surface_prepare(surface);
mg_surface_present(surface); mg_render(surface, canvas);
mg_surface_present(surface);
mem_arena_clear(mem_scratch());
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime; mem_arena_clear(mem_scratch());
} frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
}
mg_font_destroy(font);
mg_canvas_destroy(canvas); mg_font_destroy(font);
mg_surface_destroy(surface); mg_canvas_destroy(canvas);
mp_window_destroy(window); mg_surface_destroy(surface);
mp_window_destroy(window);
mp_terminate();
mp_terminate();
return(0);
} return(0);
}

View File

@ -1,326 +1,327 @@
#include<stdio.h> #include<stdio.h>
#include<stdlib.h> #include<stdlib.h>
#define LOG_DEFAULT_LEVEL LOG_LEVEL_MESSAGE #define LOG_DEFAULT_LEVEL LOG_LEVEL_MESSAGE
#define LOG_COMPILE_DEBUG #define LOG_COMPILE_DEBUG
#include"milepost.h" #include"milepost.h"
#define LOG_SUBSYSTEM "Main" #define LOG_SUBSYSTEM "Main"
static const char* TEST_STRING = static const char* TEST_STRING =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla quam enim, aliquam in placerat luctus, rutrum in quam. " "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla quam enim, aliquam in placerat luctus, rutrum in quam. "
"Cras urna elit, pellentesque ac ipsum at, lobortis scelerisque eros. Aenean et turpis nibh. Maecenas lectus augue, eleifend " "Cras urna elit, pellentesque ac ipsum at, lobortis scelerisque eros. Aenean et turpis nibh. Maecenas lectus augue, eleifend "
"nec efficitur eu, faucibus eget turpis. Suspendisse vel nulla mi. Duis imperdiet neque orci, ac ultrices orci molestie a. " "nec efficitur eu, faucibus eget turpis. Suspendisse vel nulla mi. Duis imperdiet neque orci, ac ultrices orci molestie a. "
"Etiam malesuada vulputate hendrerit. Cras ultricies diam in lectus finibus, eu laoreet diam rutrum.\n" "Etiam malesuada vulputate hendrerit. Cras ultricies diam in lectus finibus, eu laoreet diam rutrum.\n"
"\n" "\n"
"Etiam dictum orci arcu, ac fermentum leo dapibus lacinia. Integer vitae elementum ex. Vestibulum tempor nunc eu hendrerit " "Etiam dictum orci arcu, ac fermentum leo dapibus lacinia. Integer vitae elementum ex. Vestibulum tempor nunc eu hendrerit "
"ornare. Nunc pretium ligula sit amet massa pulvinar, vitae imperdiet justo bibendum. Maecenas consectetur elementum mi, sed " "ornare. Nunc pretium ligula sit amet massa pulvinar, vitae imperdiet justo bibendum. Maecenas consectetur elementum mi, sed "
"vehicula neque pulvinar sit amet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tortor erat, accumsan in laoreet " "vehicula neque pulvinar sit amet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tortor erat, accumsan in laoreet "
"quis, placerat nec enim. Nulla facilisi. Morbi vitae nibh ligula. Suspendisse in molestie magna, eget aliquet mauris. Sed " "quis, placerat nec enim. Nulla facilisi. Morbi vitae nibh ligula. Suspendisse in molestie magna, eget aliquet mauris. Sed "
"aliquam faucibus magna.\n" "aliquam faucibus magna.\n"
"\n" "\n"
"Sed metus odio, imperdiet et consequat non, faucibus nec risus. Suspendisse facilisis sem neque, id scelerisque dui mattis sit " "Sed metus odio, imperdiet et consequat non, faucibus nec risus. Suspendisse facilisis sem neque, id scelerisque dui mattis sit "
"amet. Nullam tincidunt nisl nec dui dignissim mattis. Proin fermentum ornare ipsum. Proin eleifend, mi vitae porttitor placerat, " "amet. Nullam tincidunt nisl nec dui dignissim mattis. Proin fermentum ornare ipsum. Proin eleifend, mi vitae porttitor placerat, "
"neque magna elementum turpis, eu aliquet mi urna et leo. Pellentesque interdum est mauris, sed pellentesque risus blandit in. " "neque magna elementum turpis, eu aliquet mi urna et leo. Pellentesque interdum est mauris, sed pellentesque risus blandit in. "
"Phasellus dignissim consequat eros, at aliquam elit finibus posuere. Proin suscipit tortor leo, id vulputate odio lobortis in. " "Phasellus dignissim consequat eros, at aliquam elit finibus posuere. Proin suscipit tortor leo, id vulputate odio lobortis in. "
"Vestibulum et orci ligula. Sed scelerisque nunc non nisi aliquam, vel eleifend felis suscipit. Integer posuere sapien elit, " "Vestibulum et orci ligula. Sed scelerisque nunc non nisi aliquam, vel eleifend felis suscipit. Integer posuere sapien elit, "
"lacinia ultricies nibh sodales nec.\n" "lacinia ultricies nibh sodales nec.\n"
"\n" "\n"
"Etiam aliquam purus sit amet purus ultricies tristique. Nunc maximus nunc quis magna ornare, vel interdum urna fermentum. " "Etiam aliquam purus sit amet purus ultricies tristique. Nunc maximus nunc quis magna ornare, vel interdum urna fermentum. "
"Vestibulum cursus nisl ut nulla egestas, quis mattis elit venenatis. Praesent malesuada mi non magna aliquam fringilla eget eu " "Vestibulum cursus nisl ut nulla egestas, quis mattis elit venenatis. Praesent malesuada mi non magna aliquam fringilla eget eu "
"turpis. Integer suscipit elit vel consectetur vulputate. Integer euismod, erat eget elementum tempus, magna metus consectetur " "turpis. Integer suscipit elit vel consectetur vulputate. Integer euismod, erat eget elementum tempus, magna metus consectetur "
"elit, sed feugiat urna sapien sodales sapien. Sed sit amet varius nunc. Curabitur sodales nunc justo, ac scelerisque ipsum semper " "elit, sed feugiat urna sapien sodales sapien. Sed sit amet varius nunc. Curabitur sodales nunc justo, ac scelerisque ipsum semper "
"eget. Integer ornare, velit ut hendrerit dapibus, erat mauris commodo justo, vel semper urna justo non mauris. Proin blandit, " "eget. Integer ornare, velit ut hendrerit dapibus, erat mauris commodo justo, vel semper urna justo non mauris. Proin blandit, "
"enim ut posuere placerat, leo nibh tristique eros, ut pulvinar sapien elit eget enim. Pellentesque et mauris lectus. Curabitur " "enim ut posuere placerat, leo nibh tristique eros, ut pulvinar sapien elit eget enim. Pellentesque et mauris lectus. Curabitur "
"quis lobortis leo, sit amet egestas dui. Nullam ut sapien eu justo lacinia ultrices. Ut tincidunt, sem non luctus tempus, felis " "quis lobortis leo, sit amet egestas dui. Nullam ut sapien eu justo lacinia ultrices. Ut tincidunt, sem non luctus tempus, felis "
"purus imperdiet nisi, non ultricies libero ipsum eu augue. Mauris at luctus enim.\n" "purus imperdiet nisi, non ultricies libero ipsum eu augue. Mauris at luctus enim.\n"
"\n" "\n"
"Aliquam sed tortor a justo pulvinar dictum consectetur eu felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices " "Aliquam sed tortor a justo pulvinar dictum consectetur eu felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices "
"posuere cubilia curae; Etiam vehicula porttitor volutpat. Morbi fringilla tortor nec accumsan aliquet. Aliquam in commodo neque. " "posuere cubilia curae; Etiam vehicula porttitor volutpat. Morbi fringilla tortor nec accumsan aliquet. Aliquam in commodo neque. "
"Sed laoreet tellus in consectetur aliquet. Nullam nibh eros, feugiat sit amet aliquam non, malesuada vel urna. Ut vel egestas nunc. " "Sed laoreet tellus in consectetur aliquet. Nullam nibh eros, feugiat sit amet aliquam non, malesuada vel urna. Ut vel egestas nunc. "
"Pellentesque vitae ante quis ante pharetra pretium. Nam quis eros commodo, mattis enim sed, finibus ante. Quisque lacinia tortor ut " "Pellentesque vitae ante quis ante pharetra pretium. Nam quis eros commodo, mattis enim sed, finibus ante. Quisque lacinia tortor ut "
"odio laoreet, vel viverra libero porttitor. Vestibulum vitae dapibus ex. Phasellus varius lorem sed justo sollicitudin faucibus. " "odio laoreet, vel viverra libero porttitor. Vestibulum vitae dapibus ex. Phasellus varius lorem sed justo sollicitudin faucibus. "
"Etiam aliquam lacinia consectetur. Phasellus nulla ipsum, viverra non nulla in, rhoncus posuere nunc.\n" "Etiam aliquam lacinia consectetur. Phasellus nulla ipsum, viverra non nulla in, rhoncus posuere nunc.\n"
"\n" "\n"
"Phasellus efficitur commodo tellus, eget lobortis erat porta quis. Aenean condimentum tortor ut neque dapibus, vitae vulputate quam " "Phasellus efficitur commodo tellus, eget lobortis erat porta quis. Aenean condimentum tortor ut neque dapibus, vitae vulputate quam "
"condimentum. Aliquam elementum vitae nulla vitae tristique. Suspendisse feugiat turpis ac magna dapibus, ut blandit diam tincidunt. " "condimentum. Aliquam elementum vitae nulla vitae tristique. Suspendisse feugiat turpis ac magna dapibus, ut blandit diam tincidunt. "
"Integer id dui id enim ullamcorper dictum. Maecenas malesuada vitae ex pharetra iaculis. Curabitur eu dolor consectetur, tempus augue " "Integer id dui id enim ullamcorper dictum. Maecenas malesuada vitae ex pharetra iaculis. Curabitur eu dolor consectetur, tempus augue "
"sed, finibus est. Nulla facilisi. Vivamus sed lacinia turpis, in gravida dolor. Aenean interdum consectetur enim a malesuada. Sed turpis " "sed, finibus est. Nulla facilisi. Vivamus sed lacinia turpis, in gravida dolor. Aenean interdum consectetur enim a malesuada. Sed turpis "
"nisi, lacinia et fermentum nec, pharetra id dui. Vivamus neque ligula, iaculis sed tempor eget, vehicula blandit quam. Morbi rhoncus quam " "nisi, lacinia et fermentum nec, pharetra id dui. Vivamus neque ligula, iaculis sed tempor eget, vehicula blandit quam. Morbi rhoncus quam "
"semper magna mollis luctus. Donec eu dolor ut ante ullamcorper porta. Mauris et est tristique libero pharetra faucibus.\n" "semper magna mollis luctus. Donec eu dolor ut ante ullamcorper porta. Mauris et est tristique libero pharetra faucibus.\n"
"\n" "\n"
"Duis ut elementum sem. Praesent commodo erat nec sem ultricies sollicitudin. Suspendisse a pellentesque sapien. Nunc ac magna a dui " "Duis ut elementum sem. Praesent commodo erat nec sem ultricies sollicitudin. Suspendisse a pellentesque sapien. Nunc ac magna a dui "
"elementum luctus non a mi. Cras elementum nunc sed nunc gravida, sit amet accumsan tortor pulvinar. Etiam elit arcu, pellentesque non ex " "elementum luctus non a mi. Cras elementum nunc sed nunc gravida, sit amet accumsan tortor pulvinar. Etiam elit arcu, pellentesque non ex "
"id, vestibulum pellentesque velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque habitant morbi tristique senectus " "id, vestibulum pellentesque velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque habitant morbi tristique senectus "
"et netus et malesuada fames ac turpis egestas. Proin sit amet velit eget tellus vulputate sagittis eget non massa. Cras accumsan tempor " "et netus et malesuada fames ac turpis egestas. Proin sit amet velit eget tellus vulputate sagittis eget non massa. Cras accumsan tempor "
"tortor, quis rutrum neque placerat id. Nullam a egestas eros, eu porta nisi. Aenean rutrum, sapien quis fermentum tempus, dolor orci " "tortor, quis rutrum neque placerat id. Nullam a egestas eros, eu porta nisi. Aenean rutrum, sapien quis fermentum tempus, dolor orci "
"faucibus eros, vel luctus justo leo vitae ante. Curabitur aliquam condimentum ipsum sit amet ultrices. Nullam ac velit semper, dapibus urna " "faucibus eros, vel luctus justo leo vitae ante. Curabitur aliquam condimentum ipsum sit amet ultrices. Nullam ac velit semper, dapibus urna "
"sit amet, malesuada enim. Mauris ultricies nibh orci."; "sit amet, malesuada enim. Mauris ultricies nibh orci.";
mg_font create_font(const char* path) mg_font create_font(const char* path)
{ {
//NOTE(martin): create font //NOTE(martin): create font
str8 fontPath = mp_app_get_resource_path(mem_scratch(), path); str8 fontPath = mp_app_get_resource_path(mem_scratch(), path);
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath); char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath);
FILE* fontFile = fopen(fontPathCString, "r"); FILE* fontFile = fopen(fontPathCString, "r");
if(!fontFile) if(!fontFile)
{ {
log_error("Could not load font file '%s'\n", fontPathCString); log_error("Could not load font file '%s'\n", fontPathCString);
return(mg_font_nil()); return(mg_font_nil());
} }
unsigned char* fontData = 0; unsigned char* fontData = 0;
fseek(fontFile, 0, SEEK_END); fseek(fontFile, 0, SEEK_END);
u32 fontDataSize = ftell(fontFile); u32 fontDataSize = ftell(fontFile);
rewind(fontFile); rewind(fontFile);
fontData = (unsigned char*)malloc(fontDataSize); fontData = (unsigned char*)malloc(fontDataSize);
fread(fontData, 1, fontDataSize, fontFile); fread(fontData, 1, fontDataSize, fontFile);
fclose(fontFile); fclose(fontFile);
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN, unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT, UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
UNICODE_RANGE_LATIN_EXTENDED_A, UNICODE_RANGE_LATIN_EXTENDED_A,
UNICODE_RANGE_LATIN_EXTENDED_B, UNICODE_RANGE_LATIN_EXTENDED_B,
UNICODE_RANGE_SPECIALS}; UNICODE_RANGE_SPECIALS};
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges); mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData); free(fontData);
return(font); return(font);
} }
int main() enum { FONT_COUNT = 3 };
{
mp_init(); int main()
mp_clock_init(); {
mp_init();
mp_rect rect = {.x = 100, .y = 100, .w = 980, .h = 600}; mp_clock_init();
mp_window window = mp_window_create(rect, "test", 0);
mp_rect rect = {.x = 100, .y = 100, .w = 980, .h = 600};
mp_rect contentRect = mp_window_get_content_rect(window); mp_window window = mp_window_create(rect, "test", 0);
//NOTE: create surface, canvas and font mp_rect contentRect = mp_window_get_content_rect(window);
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); //NOTE: create surface, canvas and font
mg_surface_swap_interval(surface, 0);
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
mg_canvas canvas = mg_canvas_create(); mg_surface_swap_interval(surface, 0);
const int fontCount = 3; mg_canvas canvas = mg_canvas_create();
int fontIndex = 0;
mg_font fonts[fontCount] = {create_font("../resources/OpenSansLatinSubset.ttf"), int fontIndex = 0;
create_font("../resources/CMUSerif-Roman.ttf"), mg_font fonts[FONT_COUNT] = {create_font("../resources/OpenSansLatinSubset.ttf"),
create_font("../resources/courier.ttf")}; create_font("../resources/CMUSerif-Roman.ttf"),
create_font("../resources/courier.ttf")};
mg_font_extents extents[fontCount];
f32 fontScales[fontCount]; mg_font_extents extents[FONT_COUNT];
f32 lineHeights[fontCount]; f32 fontScales[FONT_COUNT];
f32 lineHeights[FONT_COUNT];
for(int i=0; i<fontCount; i++)
{ for(int i=0; i<FONT_COUNT; i++)
extents[i] = mg_font_get_extents(fonts[i]); {
fontScales[i] = mg_font_get_scale_for_em_pixels(fonts[i], 14); extents[i] = mg_font_get_extents(fonts[i]);
lineHeights[i] = fontScales[i]*(extents[i].ascent + extents[i].descent + extents[i].leading); fontScales[i] = mg_font_get_scale_for_em_pixels(fonts[i], 14);
} lineHeights[i] = fontScales[i]*(extents[i].ascent + extents[i].descent + extents[i].leading);
}
int codePointCount = utf8_codepoint_count_for_string(STR8((char*)TEST_STRING));
u32* codePoints = malloc_array(utf32, codePointCount); int codePointCount = utf8_codepoint_count_for_string(STR8((char*)TEST_STRING));
utf8_to_codepoints(codePointCount, codePoints, STR8((char*)TEST_STRING)); u32* codePoints = malloc_array(utf32, codePointCount);
utf8_to_codepoints(codePointCount, codePoints, STR8((char*)TEST_STRING));
u32 glyphCount = 0;
for(int i=0; i<codePointCount; i++) u32 glyphCount = 0;
{ for(int i=0; i<codePointCount; i++)
if(codePoints[i] != ' ' && codePoints[i] != '\n') {
{ if(codePoints[i] != ' ' && codePoints[i] != '\n')
glyphCount++; {
} glyphCount++;
} }
}
// start app
mp_window_bring_to_front(window); // start app
mp_window_focus(window); mp_window_bring_to_front(window);
mp_window_focus(window);
f64 frameTime = 0;
f64 frameTime = 0;
bool tracked = false;
vec2 trackPoint = {0}; bool tracked = false;
f32 zoom = 1; vec2 trackPoint = {0};
f32 zoom = 1;
f32 startX = 10;
f32 startY = 10 + lineHeights[fontIndex]; f32 startX = 10;
f32 startY = 10 + lineHeights[fontIndex];
mp_input_state inputState = {0};
mp_input_state inputState = {0};
while(!mp_should_quit())
{ while(!mp_should_quit())
f64 startFrameTime = mp_get_time(MP_CLOCK_MONOTONIC); {
f64 startFrameTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0);
mp_event* event = 0; mp_pump_events(0);
while((event = mp_next_event(mem_scratch())) != 0) mp_event* event = 0;
{ while((event = mp_next_event(mem_scratch())) != 0)
mp_input_process_event(&inputState, event); {
mp_input_process_event(&inputState, event);
switch(event->type)
{ switch(event->type)
case MP_EVENT_WINDOW_CLOSE: {
{ case MP_EVENT_WINDOW_CLOSE:
mp_request_quit(); {
} break; mp_request_quit();
} break;
case MP_EVENT_MOUSE_BUTTON:
{ case MP_EVENT_MOUSE_BUTTON:
if(event->key.code == MP_MOUSE_LEFT) {
{ if(event->key.code == MP_MOUSE_LEFT)
if(event->key.action == MP_KEY_PRESS) {
{ if(event->key.action == MP_KEY_PRESS)
tracked = true; {
vec2 mousePos = mp_mouse_position(&inputState); tracked = true;
trackPoint.x = mousePos.x/zoom - startX; vec2 mousePos = mp_mouse_position(&inputState);
trackPoint.y = mousePos.y/zoom - startY; trackPoint.x = mousePos.x/zoom - startX;
} trackPoint.y = mousePos.y/zoom - startY;
else }
{ else
tracked = false; {
} tracked = false;
} }
} break; }
} break;
case MP_EVENT_MOUSE_WHEEL:
{ case MP_EVENT_MOUSE_WHEEL:
vec2 mousePos = mp_mouse_position(&inputState); {
f32 trackX = mousePos.x/zoom - startX; vec2 mousePos = mp_mouse_position(&inputState);
f32 trackY = mousePos.y/zoom - startY; f32 trackX = mousePos.x/zoom - startX;
f32 trackY = mousePos.y/zoom - startY;
zoom *= 1 + event->move.deltaY * 0.01;
zoom = Clamp(zoom, 0.2, 10); zoom *= 1 + event->move.deltaY * 0.01;
zoom = Clamp(zoom, 0.2, 10);
startX = mousePos.x/zoom - trackX;
startY = mousePos.y/zoom - trackY; startX = mousePos.x/zoom - trackX;
} break; startY = mousePos.y/zoom - trackY;
} break;
case MP_EVENT_KEYBOARD_KEY:
{ case MP_EVENT_KEYBOARD_KEY:
if(event->key.code == MP_KEY_SPACE && event->key.action == MP_KEY_PRESS) {
{ if(event->key.code == MP_KEY_SPACE && event->key.action == MP_KEY_PRESS)
fontIndex = (fontIndex+1)%fontCount; {
} fontIndex = (fontIndex+1)%FONT_COUNT;
} break; }
} break;
default:
break; default:
} break;
} }
}
if(tracked)
{ if(tracked)
vec2 mousePos = mp_mouse_position(&inputState); {
startX = mousePos.x/zoom - trackPoint.x; vec2 mousePos = mp_mouse_position(&inputState);
startY = mousePos.y/zoom - trackPoint.y; startX = mousePos.x/zoom - trackPoint.x;
} startY = mousePos.y/zoom - trackPoint.y;
}
f32 textX = startX;
f32 textY = startY; f32 textX = startX;
f32 textY = startY;
/*
mg_set_color_rgba(1, 1, 1, 1); /*
mg_clear(); mg_set_color_rgba(1, 1, 1, 1);
mg_set_color_rgba(1, 0, 0, 1); mg_clear();
for(int i=0; i<1000; i++) mg_set_color_rgba(1, 0, 0, 1);
{ for(int i=0; i<1000; i++)
mg_rectangle_fill(0, 0, 100, 100); {
} mg_rectangle_fill(0, 0, 100, 100);
*/ }
*/
mg_matrix_push((mg_mat2x3){zoom, 0, 0,
0, zoom, 0}); mg_matrix_push((mg_mat2x3){zoom, 0, 0,
0, zoom, 0});
mg_set_color_rgba(1, 1, 1, 1);
mg_clear(); mg_set_color_rgba(1, 1, 1, 1);
mg_clear();
mg_set_font(fonts[fontIndex]);
mg_set_font_size(14); mg_set_font(fonts[fontIndex]);
mg_set_color_rgba(0, 0, 0, 1); mg_set_font_size(14);
mg_set_color_rgba(0, 0, 0, 1);
mg_move_to(textX, textY);
mg_move_to(textX, textY);
int startIndex = 0;
while(startIndex < codePointCount) int startIndex = 0;
{ while(startIndex < codePointCount)
bool lineBreak = false; {
int subIndex = 0; bool lineBreak = false;
for(; (startIndex+subIndex) < codePointCount && subIndex < 120; subIndex++) int subIndex = 0;
{ for(; (startIndex+subIndex) < codePointCount && subIndex < 120; subIndex++)
if(codePoints[startIndex + subIndex] == '\n') {
{ if(codePoints[startIndex + subIndex] == '\n')
break; {
} break;
} }
}
u32 glyphs[512];
mg_font_get_glyph_indices(fonts[fontIndex], (str32){subIndex, codePoints+startIndex}, (str32){512, glyphs}); u32 glyphs[512];
mg_font_get_glyph_indices(fonts[fontIndex], (str32){subIndex, codePoints+startIndex}, (str32){512, glyphs});
mg_glyph_outlines((str32){subIndex, glyphs});
mg_fill(); mg_glyph_outlines((str32){subIndex, glyphs});
mg_fill();
textY += lineHeights[fontIndex];
mg_move_to(textX, textY); textY += lineHeights[fontIndex];
startIndex++; mg_move_to(textX, textY);
startIndex++;
startIndex += subIndex;
} startIndex += subIndex;
}
mg_matrix_pop();
mg_matrix_pop();
mg_set_color_rgba(0, 0, 1, 1);
mg_set_font(fonts[fontIndex]); mg_set_color_rgba(0, 0, 1, 1);
mg_set_font_size(14); mg_set_font(fonts[fontIndex]);
mg_move_to(10, contentRect.h - 10 - lineHeights[fontIndex]); mg_set_font_size(14);
mg_move_to(10, contentRect.h - 10 - lineHeights[fontIndex]);
str8 text = str8_pushf(mem_scratch(),
"Test program: %i glyphs, frame time = %fs, fps = %f", str8 text = str8_pushf(mem_scratch(),
glyphCount, "Test program: %i glyphs, frame time = %fs, fps = %f",
frameTime, glyphCount,
1./frameTime); frameTime,
mg_text_outlines(text); 1./frameTime);
mg_fill(); mg_text_outlines(text);
mg_fill();
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC);
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC);
mg_surface_prepare(surface);
mg_render(surface, canvas); mg_surface_prepare(surface);
mg_render(surface, canvas);
f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC);
mg_surface_present(surface); f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC);
mg_surface_present(surface);
f64 endFrameTime = mp_get_time(MP_CLOCK_MONOTONIC);
f64 endFrameTime = mp_get_time(MP_CLOCK_MONOTONIC);
frameTime = (endFrameTime - startFrameTime);
frameTime = (endFrameTime - startFrameTime);
printf("frame time: %.2fms (%.2fFPS), draw = %f.2ms, flush = %.2fms, present = %.2fms\n",
frameTime*1000, printf("frame time: %.2fms (%.2fFPS), draw = %f.2ms, flush = %.2fms, present = %.2fms\n",
1./frameTime, frameTime*1000,
(startFlushTime - startFrameTime)*1000, 1./frameTime,
(startPresentTime - startFlushTime)*1000, (startFlushTime - startFrameTime)*1000,
(endFrameTime - startPresentTime)*1000); (startPresentTime - startFlushTime)*1000,
(endFrameTime - startPresentTime)*1000);
mp_input_next_frame(&inputState);
mem_arena_clear(mem_scratch()); mp_input_next_frame(&inputState);
} mem_arena_clear(mem_scratch());
}
for(int i=0; i<fontCount; i++)
{ for(int i=0; i<FONT_COUNT; i++)
mg_font_destroy(fonts[i]); {
} mg_font_destroy(fonts[i]);
mg_canvas_destroy(canvas); }
mg_surface_destroy(surface); mg_canvas_destroy(canvas);
mp_window_destroy(window); mg_surface_destroy(surface);
mp_terminate(); mp_window_destroy(window);
mp_terminate();
return(0);
} return(0);
}

View File

@ -1,2 +1,2 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib /out:test.exe cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib user32.lib opengl32.lib gdi32.lib /out:../../bin/example_window.exe

View File

@ -1,113 +1,111 @@
/************************************************************//** /************************************************************//**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 30/07/2022 * @date: 30/07/2022
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include<stdlib.h>
#include<string.h> #include<stdio.h>
#include<string.h>
#include"milepost.h"
#include"milepost.h"
#define LOG_SUBSYSTEM "Main"
int main()
int main() {
{ mp_init();
LogLevel(LOG_LEVEL_DEBUG);
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
mp_init(); mp_window window = mp_window_create(rect, "test", 0);
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_window_bring_to_front(window);
mp_window window = mp_window_create(rect, "test", 0); mp_window_focus(window);
mp_window_bring_to_front(window); while(!mp_should_quit())
mp_window_focus(window); {
mp_pump_events(0);
while(!mp_should_quit()) mp_event *event = 0;
{ while((event = mp_next_event(mem_scratch())) != 0)
mp_pump_events(0); {
mp_event event = {0}; switch(event->type)
while(mp_next_event(&event)) {
{ case MP_EVENT_WINDOW_CLOSE:
switch(event.type) {
{ mp_request_quit();
case MP_EVENT_WINDOW_CLOSE: } break;
{
mp_request_quit(); case MP_EVENT_WINDOW_RESIZE:
} break; {
printf("resized, rect = {%f, %f, %f, %f}\n",
case MP_EVENT_WINDOW_RESIZE: event->frame.rect.x,
{ event->frame.rect.y,
printf("resized, rect = {%f, %f, %f, %f}\n", event->frame.rect.w,
event.frame.rect.x, event->frame.rect.h);
event.frame.rect.y, } break;
event.frame.rect.w,
event.frame.rect.h); case MP_EVENT_WINDOW_MOVE:
} break; {
printf("moved, rect = {%f, %f, %f, %f}\n",
case MP_EVENT_WINDOW_MOVE: event->frame.rect.x,
{ event->frame.rect.y,
printf("moved, rect = {%f, %f, %f, %f}\n", event->frame.rect.w,
event.frame.rect.x, event->frame.rect.h);
event.frame.rect.y, } break;
event.frame.rect.w,
event.frame.rect.h); case MP_EVENT_MOUSE_MOVE:
} break; {
printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n",
case MP_EVENT_MOUSE_MOVE: event->move.x,
{ event->move.y,
printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n", event->move.deltaX,
event.move.x, event->move.deltaY);
event.move.y, } break;
event.move.deltaX,
event.move.deltaY); case MP_EVENT_MOUSE_WHEEL:
} break; {
printf("mouse wheel, delta = {%f, %f}\n",
case MP_EVENT_MOUSE_WHEEL: event->move.deltaX,
{ event->move.deltaY);
printf("mouse wheel, delta = {%f, %f}\n", } break;
event.move.deltaX,
event.move.deltaY); case MP_EVENT_MOUSE_ENTER:
} break; {
printf("mouse enter\n");
case MP_EVENT_MOUSE_ENTER: } break;
{
printf("mouse enter\n"); case MP_EVENT_MOUSE_LEAVE:
} break; {
printf("mouse leave\n");
case MP_EVENT_MOUSE_LEAVE: } break;
{
printf("mouse leave\n"); case MP_EVENT_MOUSE_BUTTON:
} break; {
printf("mouse button %i: %i\n",
case MP_EVENT_MOUSE_BUTTON: event->key.code,
{ event->key.action == MP_KEY_PRESS ? 1 : 0);
printf("mouse button %i: %i\n", } break;
event.key.code,
event.key.action == MP_KEY_PRESS ? 1 : 0); case MP_EVENT_KEYBOARD_KEY:
} break; {
printf("key %i: %s\n",
case MP_EVENT_KEYBOARD_KEY: event->key.code,
{ event->key.action == MP_KEY_PRESS ? "press" : (event->key.action == MP_KEY_RELEASE ? "release" : "repeat"));
printf("key %i: %s\n", } break;
event.key.code,
event.key.action == MP_KEY_PRESS ? "press" : (event.key.action == MP_KEY_RELEASE ? "release" : "repeat")); case MP_EVENT_KEYBOARD_CHAR:
} break; {
printf("entered char %s\n", event->character.sequence);
case MP_EVENT_KEYBOARD_CHAR: } break;
{
printf("entered char %s\n", event.character.sequence); default:
} break; break;
}
default: }
break; mem_arena_clear(mem_scratch());
} }
}
} mp_terminate();
mp_terminate(); return(0);
}
return(0);
}

View File

@ -1,4 +1,4 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_canvas.exe cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_tiger.exe

View File

@ -1,247 +1,248 @@
/************************************************************//** /************************************************************//**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 30/07/2022 * @date: 30/07/2022
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include<stdlib.h>
#include<string.h> #include<string.h>
#include<errno.h> #include<stdio.h>
#include<errno.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h>
#include"milepost.h"
#include"milepost.h"
#include"tiger.c"
#include"tiger.c"
mg_font create_font()
{ mg_font create_font()
//NOTE(martin): create font {
str8 fontPath = mp_app_get_resource_path(mem_scratch(), "../resources/OpenSansLatinSubset.ttf"); //NOTE(martin): create font
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath); str8 fontPath = mp_app_get_resource_path(mem_scratch(), "../resources/OpenSansLatinSubset.ttf");
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath);
FILE* fontFile = fopen(fontPathCString, "r");
if(!fontFile) FILE* fontFile = fopen(fontPathCString, "r");
{ if(!fontFile)
log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno)); {
return(mg_font_nil()); log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno));
} return(mg_font_nil());
unsigned char* fontData = 0; }
fseek(fontFile, 0, SEEK_END); unsigned char* fontData = 0;
u32 fontDataSize = ftell(fontFile); fseek(fontFile, 0, SEEK_END);
rewind(fontFile); u32 fontDataSize = ftell(fontFile);
fontData = (unsigned char*)malloc(fontDataSize); rewind(fontFile);
fread(fontData, 1, fontDataSize, fontFile); fontData = (unsigned char*)malloc(fontDataSize);
fclose(fontFile); fread(fontData, 1, fontDataSize, fontFile);
fclose(fontFile);
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT, unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_LATIN_EXTENDED_A, UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
UNICODE_RANGE_LATIN_EXTENDED_B, UNICODE_RANGE_LATIN_EXTENDED_A,
UNICODE_RANGE_SPECIALS}; UNICODE_RANGE_LATIN_EXTENDED_B,
UNICODE_RANGE_SPECIALS};
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData); mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData);
return(font);
} return(font);
}
int main()
{ int main()
mp_init(); {
mp_clock_init(); //TODO put that in mp_init()? mp_init();
mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
mp_window window = mp_window_create(windowRect, "test", 0); mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window);
mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); //NOTE: create surface
mg_surface_swap_interval(surface, 0); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
mg_surface_swap_interval(surface, 0);
//TODO: create canvas
mg_canvas canvas = mg_canvas_create(); //TODO: create canvas
mg_canvas canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas))
{ if(mg_canvas_is_nil(canvas))
printf("Error: couldn't create canvas\n"); {
return(-1); printf("Error: couldn't create canvas\n");
} return(-1);
}
mg_font font = create_font();
mg_font font = create_font();
// start app
mp_window_bring_to_front(window); // start app
mp_window_focus(window); mp_window_bring_to_front(window);
mp_window_focus(window);
bool tracked = false;
vec2 trackPoint = {0}; bool tracked = false;
vec2 trackPoint = {0};
f32 zoom = 1;
f32 startX = 300, startY = 200; f32 zoom = 1;
bool singlePath = false; f32 startX = 300, startY = 200;
int singlePathIndex = 0; bool singlePath = false;
int singlePathIndex = 0;
f64 frameTime = 0;
f64 frameTime = 0;
mp_input_state inputState = {0};
mp_input_state inputState = {0};
while(!mp_should_quit())
{ while(!mp_should_quit())
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC); {
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0);
mp_event* event = 0; mp_pump_events(0);
while((event = mp_next_event(mem_scratch())) != 0) mp_event* event = 0;
{ while((event = mp_next_event(mem_scratch())) != 0)
mp_input_process_event(&inputState, event); {
mp_input_process_event(&inputState, event);
switch(event->type)
{ switch(event->type)
case MP_EVENT_WINDOW_CLOSE: {
{ case MP_EVENT_WINDOW_CLOSE:
mp_request_quit(); {
} break; mp_request_quit();
} break;
case MP_EVENT_WINDOW_RESIZE:
{ case MP_EVENT_WINDOW_RESIZE:
mp_rect frame = {0, 0, event->frame.rect.w, event->frame.rect.h}; {
mg_surface_set_frame(surface, frame); mp_rect frame = {0, 0, event->frame.rect.w, event->frame.rect.h};
} break; mg_surface_set_frame(surface, frame);
} break;
case MP_EVENT_MOUSE_BUTTON:
{ case MP_EVENT_MOUSE_BUTTON:
if(event->key.code == MP_MOUSE_LEFT) {
{ if(event->key.code == MP_MOUSE_LEFT)
if(event->key.action == MP_KEY_PRESS) {
{ if(event->key.action == MP_KEY_PRESS)
tracked = true; {
vec2 mousePos = mp_mouse_position(&inputState); tracked = true;
trackPoint.x = (mousePos.x - startX)/zoom; vec2 mousePos = mp_mouse_position(&inputState);
trackPoint.y = (mousePos.y - startY)/zoom; trackPoint.x = (mousePos.x - startX)/zoom;
} trackPoint.y = (mousePos.y - startY)/zoom;
else }
{ else
tracked = false; {
} tracked = false;
} }
} break; }
} break;
case MP_EVENT_MOUSE_WHEEL:
{ case MP_EVENT_MOUSE_WHEEL:
vec2 mousePos = mp_mouse_position(&inputState); {
f32 pinX = (mousePos.x - startX)/zoom; vec2 mousePos = mp_mouse_position(&inputState);
f32 pinY = (mousePos.y - startY)/zoom; f32 pinX = (mousePos.x - startX)/zoom;
f32 pinY = (mousePos.y - startY)/zoom;
zoom *= 1 + event->move.deltaY * 0.01;
zoom = Clamp(zoom, 0.5, 5); zoom *= 1 + event->move.deltaY * 0.01;
zoom = Clamp(zoom, 0.5, 5);
startX = mousePos.x - pinX*zoom;
startY = mousePos.y - pinY*zoom; startX = mousePos.x - pinX*zoom;
} break; startY = mousePos.y - pinY*zoom;
} break;
case MP_EVENT_KEYBOARD_KEY:
{ case MP_EVENT_KEYBOARD_KEY:
if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT) {
{ if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT)
switch(event->key.code) {
{ switch(event->key.code)
case MP_KEY_SPACE: {
singlePath = !singlePath; case MP_KEY_SPACE:
break; singlePath = !singlePath;
break;
case MP_KEY_UP:
{ case MP_KEY_UP:
if(event->key.mods & MP_KEYMOD_SHIFT) {
{ if(event->key.mods & MP_KEYMOD_SHIFT)
singlePathIndex++; {
} singlePathIndex++;
else }
{ else
zoom += 0.001; {
} zoom += 0.001;
} break; }
} break;
case MP_KEY_DOWN:
{ case MP_KEY_DOWN:
if(event->key.mods & MP_KEYMOD_SHIFT) {
{ if(event->key.mods & MP_KEYMOD_SHIFT)
singlePathIndex--; {
} singlePathIndex--;
else }
{ else
zoom -= 0.001; {
} zoom -= 0.001;
} break; }
} } break;
} }
} break; }
} break;
default:
break; default:
} break;
} }
}
if(tracked)
{ if(tracked)
vec2 mousePos = mp_mouse_position(&inputState); {
startX = mousePos.x - trackPoint.x*zoom; vec2 mousePos = mp_mouse_position(&inputState);
startY = mousePos.y - trackPoint.y*zoom; startX = mousePos.x - trackPoint.x*zoom;
} startY = mousePos.y - trackPoint.y*zoom;
}
mg_surface_prepare(surface);
mg_surface_prepare(surface);
mg_set_color_rgba(1, 0, 1, 1);
mg_clear(); mg_set_color_rgba(1, 0, 1, 1);
mg_clear();
mg_matrix_push((mg_mat2x3){zoom, 0, startX,
0, zoom, startY}); mg_matrix_push((mg_mat2x3){zoom, 0, startX,
0, zoom, startY});
draw_tiger(singlePath, singlePathIndex);
draw_tiger(singlePath, singlePathIndex);
if(singlePath)
{ if(singlePath)
printf("display single path %i\n", singlePathIndex); {
printf("viewpos = (%f, %f), zoom = %f\n", startX, startY, zoom); printf("display single path %i\n", singlePathIndex);
} printf("viewpos = (%f, %f), zoom = %f\n", startX, startY, zoom);
}
mg_matrix_pop();
mg_matrix_pop();
// text
mg_set_color_rgba(0, 0, 1, 1); // text
mg_set_font(font); mg_set_color_rgba(0, 0, 1, 1);
mg_set_font_size(12); mg_set_font(font);
mg_move_to(50, 600-50); mg_set_font_size(12);
mg_move_to(50, 600-50);
str8 text = str8_pushf(mem_scratch(),
"Milepost vector graphics test program (frame time = %fs, fps = %f)...", str8 text = str8_pushf(mem_scratch(),
frameTime, "Milepost vector graphics test program (frame time = %fs, fps = %f)...",
1./frameTime); frameTime,
mg_text_outlines(text); 1./frameTime);
mg_fill(); mg_text_outlines(text);
mg_fill();
printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
frameTime, printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
1./frameTime); frameTime,
1./frameTime);
mg_render(surface, canvas);
mg_surface_present(surface); mg_render(surface, canvas);
mg_surface_present(surface);
mp_input_next_frame(&inputState);
mem_arena_clear(mem_scratch()); mp_input_next_frame(&inputState);
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime; mem_arena_clear(mem_scratch());
} frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
}
mg_font_destroy(font);
mg_canvas_destroy(canvas); mg_font_destroy(font);
mg_surface_destroy(surface); mg_canvas_destroy(canvas);
mp_window_destroy(window); mg_surface_destroy(surface);
mp_window_destroy(window);
mp_terminate();
mp_terminate();
return(0);
} return(0);
}

View File

@ -1,165 +1,163 @@
/************************************************************//** /************************************************************//**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 30/07/2022 * @date: 30/07/2022
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include<stdio.h>
#include<string.h> #include<string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include<math.h>
#define MG_INCLUDE_GL_API #define MG_INCLUDE_GL_API
#include"milepost.h" #include"milepost.h"
#define LOG_SUBSYSTEM "Main" unsigned int program;
unsigned int program; const char* vshaderSource =
"#version 430\n"
const char* vshaderSource = "attribute vec4 vPosition;\n"
"#version 430\n" "uniform mat4 transform;\n"
"attribute vec4 vPosition;\n" "void main()\n"
"uniform mat4 transform;\n" "{\n"
"void main()\n" " gl_Position = transform*vPosition;\n"
"{\n" "}\n";
" gl_Position = transform*vPosition;\n"
"}\n"; const char* fshaderSource =
"#version 430\n"
const char* fshaderSource = "precision mediump float;\n"
"#version 430\n" "void main()\n"
"precision mediump float;\n" "{\n"
"void main()\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"{\n" "}\n";
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"; void compile_shader(GLuint shader, const char* source)
{
void compile_shader(GLuint shader, const char* source) glShaderSource(shader, 1, &source, 0);
{ glCompileShader(shader);
glShaderSource(shader, 1, &source, 0);
glCompileShader(shader); int err = glGetError();
if(err)
int err = glGetError(); {
if(err) printf("gl error: %i\n", err);
{ }
printf("gl error: %i\n", err);
} int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
int status = 0; if(!status)
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); {
if(!status) char buffer[256];
{ int size = 0;
char buffer[256]; glGetShaderInfoLog(shader, 256, &size, buffer);
int size = 0; printf("shader error: %.*s\n", size, buffer);
glGetShaderInfoLog(shader, 256, &size, buffer); }
printf("shader error: %.*s\n", size, buffer); }
}
} int main()
{
int main() mp_init();
{
LogLevel(LOG_LEVEL_DEBUG); mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
mp_window window = mp_window_create(rect, "test", 0);
mp_init();
//NOTE: create surface
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mg_surface surface = mg_surface_create_for_window(window, MG_GL);
mp_window window = mp_window_create(rect, "test", 0);
//NOTE: init shader and gl state
//NOTE: create surface mg_surface_prepare(surface);
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_GL);
GLuint vao;
//NOTE: init shader and gl state glGenVertexArrays(1, &vao);
mg_surface_prepare(surface); glBindVertexArray(vao);
GLuint vao; GLuint vertexBuffer;
glGenVertexArrays(1, &vao); glGenBuffers(1, &vertexBuffer);
glBindVertexArray(vao);
GLfloat vertices[] = {
GLuint vertexBuffer; -0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0};
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLfloat vertices[] = { glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); compile_shader(vshader, vshaderSource);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); compile_shader(fshader, fshaderSource);
program = glCreateProgram();
glAttachShader(program, vshader);
compile_shader(vshader, vshaderSource); glAttachShader(program, fshader);
compile_shader(fshader, fshaderSource); glLinkProgram(program);
glAttachShader(program, vshader); int status = 0;
glAttachShader(program, fshader); glGetProgramiv(program, GL_LINK_STATUS, &status);
glLinkProgram(program); if(!status)
{
int status = 0; char buffer[256];
glGetProgramiv(program, GL_LINK_STATUS, &status); int size = 0;
if(!status) glGetProgramInfoLog(program, 256, &size, buffer);
{ printf("link error: %.*s\n", size, buffer);
char buffer[256]; }
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer); glUseProgram(program);
printf("link error: %.*s\n", size, buffer);
} mp_window_bring_to_front(window);
// mp_window_focus(window);
glUseProgram(program);
while(!mp_should_quit())
mp_window_bring_to_front(window); {
// mp_window_focus(window); mp_pump_events(0);
mp_event* event = 0;
while(!mp_should_quit()) while((event = mp_next_event(mem_scratch())) != 0)
{ {
mp_pump_events(0); switch(event->type)
mp_event event = {0}; {
while(mp_next_event(&event)) case MP_EVENT_WINDOW_CLOSE:
{ {
switch(event.type) mp_request_quit();
{ } break;
case MP_EVENT_WINDOW_CLOSE:
{ default:
mp_request_quit(); break;
} break; }
}
default:
break; mg_surface_prepare(surface);
}
} glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
mg_surface_prepare(surface);
static float alpha = 0;
glClearColor(0.3, 0.3, 1, 1); //f32 aspect = frameSize.x/frameSize.y;
glClear(GL_COLOR_BUFFER_BIT); f32 aspect = 800/(f32)600;
static float alpha = 0; GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0,
//f32 aspect = frameSize.x/frameSize.y; -sinf(alpha)/aspect, cosf(alpha), 0, 0,
f32 aspect = 800/(f32)600; 0, 0, 1, 0,
0, 0, 0, 1};
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0,
-sinf(alpha)/aspect, cosf(alpha), 0, 0, alpha += 2*M_PI/120;
0, 0, 1, 0,
0, 0, 0, 1}; glUniformMatrix4fv(0, 1, false, matrix);
alpha += 2*M_PI/120;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glUniformMatrix4fv(0, 1, false, matrix); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glDrawArrays(GL_TRIANGLES, 0, 3);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0); mg_surface_present(surface);
glDrawArrays(GL_TRIANGLES, 0, 3); mem_arena_clear(mem_scratch());
}
mg_surface_present(surface);
} mp_terminate();
mp_terminate(); return(0);
}
return(0);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,77 +1,84 @@
## Angle install on macOS ## Angle install on macOS
* Get ninja if needed: `brew install ninja` * Get ninja if needed: `brew install ninja`
* Get the `depot_tools`repo: `git clone https://chromium.googlesource.com/* chromium/tools/depot_tools.git` * Get the `depot_tools`repo: `git clone https://chromium.googlesource.com/* chromium/tools/depot_tools.git`
* Set path: `export PATH=/path/to/depot_tools:$PATH` * Set path: `export PATH=/path/to/depot_tools:$PATH`
* Maybe necessary to fiddle with certificates here, otherwise `fetch angle` fails in the subsequent steps. * Maybe necessary to fiddle with certificates here, otherwise `fetch angle` fails in the subsequent steps.
``` ```
cd /Applications/Python\ 3.6 cd /Applications/Python\ 3.6
sudo ./Install\ Certificates.command sudo ./Install\ Certificates.command
``` ```
* Fetch angle: * Fetch angle:
``` ```
mkdir angle mkdir angle
cd angle cd angle
fetch angle fetch angle
``` ```
* Generate build config: `gn gen out/Debug` * Generate build config: `gn gen out/Debug`
* To see available arguments: `gn args out/Debug --list` * To see available arguments: `gn args out/Debug --list`
* To change arguments: `gn args out/Debug` * To change arguments: `gn args out/Debug`
For example, to generate dwarf dsyms files, set: For example, to generate dwarf dsyms files, set:
``` ```
enable_dsyms=true enable_dsyms=true
use_debug_fission=true use_debug_fission=true
symbol_level=2 symbol_level=2
``` ```
We also need to set `is_component_build=false` in order to have self-contained librarries. We also need to set `is_component_build=false` in order to have self-contained librarries.
Then, build with `autoninja -C out/Debug`and wait until you pass out. Then, build with `autoninja -C out/Debug`and wait until you pass out.
## Angle install on windows ## Angle install on windows
* need Python3 (can install through win app store) * need Python3 (can install through win app store)
* need Windows SDK * need Windows SDK
* clone `depot_tools`: `git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git` * clone `depot_tools`: `git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git`
or download and unzip bundle at [https://storage.googleapis.com/chrome-infra/depot_tools.zip](https://storage.googleapis.com/chrome-infra/depot_tools.zip) or download and unzip bundle at [https://storage.googleapis.com/chrome-infra/depot_tools.zip](https://storage.googleapis.com/chrome-infra/depot_tools.zip)
* set `depot_tools` in path env variable through control panel>System and security>system>advanced system settings * set `depot_tools` in path env variable through control panel>System and security>system>advanced system settings
* run `gclient` in a cmd shell * run `gclient` in a cmd shell
* set `DEPOT_TOOLS_WIN_TOOLCHAIN=0` * set `DEPOT_TOOLS_WIN_TOOLCHAIN=0`
* `mkdir angle` * `mkdir angle`
* `cd angle` * `cd angle`
* `fetch angle` * `fetch angle`
* wait a million years * wait a million years
* if it fails when running `python3 third_party/depot_tools/download_from_google_storage.py ...` * if it fails when running `python3 third_party/depot_tools/download_from_google_storage.py ...`
-> open `DEPS` and change `third_party/depot_tools` to `../depot/tools` -> open `DEPS` and change `third_party/depot_tools` to `../depot_tools`
* run `gclient sync` to complete previous step * run `gclient sync` to complete previous step
* `gn gen out/Debug` * `gn gen out/Debug`
* `gn args out/Debug` and edit arguments: * `gn args out/Debug` and edit arguments:
* `angle_enable_vulkan = false` ```
* `angle_build_tests = false` is_component_build = false
* `is_component_build = false` angle_build_tests = false
angle_enable_metal = false
* link with `libEGL.dll.lib` and `libGLESv2.dll.lib` angle_enable_d3d9 = false
* put `libEGL.dll` and `libGLESv2.dll` in same directory as executable angle_enable_gl = false
angle_enable_vulkan = false
## To get debugging kinda working with renderdoc: ```
Run `gn args out/Debug` and set
* `angle_enable_trace = true` * `ninja -C out/Debug`
* `angle_enable_annotator_run_time_checks = true` * link with `libEGL.dll.lib` and `libGLESv2.dll.lib`
* put `libEGL.dll` and `libGLESv2.dll` in same directory as executable
* `autoninja -C out/Debug`
* wait a while ## To get debugging kinda working with renderdoc:
In renderdoc, set env variables Run `gn args out/Debug` and set
`RENDERDOC_HOOK_EGL 0` (if you want to trace underlying native API) * `angle_enable_trace = true`
`RENDERDOC_HOOK_EGL 1` (if you want to trace EGL calls. You also need to put `libEGL` in the renderdoc folder so it's found when capturing stuff. Unfortunately though, that seems to provoke crashes...) * `angle_enable_annotator_run_time_checks = true`
`ANGLE_ENABLE_DEBUG_MARKERS 1` (to turn on debug markers) * `autoninja -C out/Debug`
* wait a while
In renderdoc, set env variables
`RENDERDOC_HOOK_EGL 0` (if you want to trace underlying native API)
`RENDERDOC_HOOK_EGL 1` (if you want to trace EGL calls. You also need to put `libEGL` in the renderdoc folder so it's found when capturing stuff. Unfortunately though, that seems to provoke crashes...)
`ANGLE_ENABLE_DEBUG_MARKERS 1` (to turn on debug markers)

File diff suppressed because it is too large Load Diff

View File

@ -1,469 +0,0 @@
/*********************************************************************
*
* file: glsl_shaders.h
* note: string literals auto-generated by embed_text.py
* date: 09/032023
*
**********************************************************************/
#ifndef __GLSL_SHADERS_H__
#define __GLSL_SHADERS_H__
//NOTE: string imported from src\glsl_shaders\common.glsl
const char* glsl_common =
"\n"
"layout(std430) buffer;\n"
"\n"
"struct vertex {\n"
" vec4 cubic;\n"
" vec2 pos;\n"
" int shapeIndex;\n"
"};\n"
"\n"
"struct shape {\n"
" vec4 color;\n"
" vec4 clip;\n"
" float uvTransform[6];\n"
"};\n";
//NOTE: string imported from src\glsl_shaders\blit_vertex.glsl
const char* glsl_blit_vertex =
"\n"
"precision mediump float;\n"
"\n"
"out vec2 uv;\n"
"\n"
"void main()\n"
"{\n"
" /* generate (0, 0) (1, 0) (1, 1) (1, 1) (0, 1) (0, 0)*/\n"
"\n"
" float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u);\n"
" float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u);\n"
"\n"
" gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);\n"
" uv = vec2(x, 1-y);\n"
"}\n";
//NOTE: string imported from src\glsl_shaders\blit_fragment.glsl
const char* glsl_blit_fragment =
"\n"
"precision mediump float;\n"
"\n"
"in vec2 uv;\n"
"out vec4 fragColor;\n"
"\n"
"layout(location=0) uniform sampler2D tex;\n"
"\n"
"void main()\n"
"{\n"
" fragColor = texture(tex, uv);\n"
"}\n";
//NOTE: string imported from src\glsl_shaders\clear_counters.glsl
const char* glsl_clear_counters =
"\n"
"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
"\n"
"precision mediump float;\n"
"layout(std430) buffer;\n"
"\n"
"layout(binding = 0) coherent restrict writeonly buffer tileCounterBufferSSBO {\n"
" uint elements[];\n"
"} tileCounterBuffer ;\n"
"\n"
"void main()\n"
"{\n"
" uint tileIndex = gl_WorkGroupID.x;\n"
" tileCounterBuffer.elements[tileIndex] = 0u;\n"
"}\n";
//NOTE: string imported from src\glsl_shaders\tile.glsl
const char* glsl_tile =
"\n"
"layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;\n"
"\n"
"precision mediump float;\n"
"\n"
"layout(binding = 0) restrict readonly buffer vertexBufferSSBO {\n"
" vertex elements[];\n"
"} vertexBuffer ;\n"
"\n"
"layout(binding = 1) restrict readonly buffer shapeBufferSSBO {\n"
" shape elements[];\n"
"} shapeBuffer ;\n"
"\n"
"layout(binding = 2) restrict readonly buffer indexBufferSSBO {\n"
" uint elements[];\n"
"} indexBuffer ;\n"
"\n"
"layout(binding = 3) coherent restrict buffer tileCounterBufferSSBO {\n"
" uint elements[];\n"
"} tileCounterBuffer ;\n"
"\n"
"layout(binding = 4) coherent restrict writeonly buffer tileArrayBufferSSBO {\n"
" uint elements[];\n"
"} tileArrayBuffer ;\n"
"\n"
"layout(location = 0) uniform uint indexCount;\n"
"layout(location = 1) uniform uvec2 tileCount;\n"
"layout(location = 2) uniform uint tileSize;\n"
"layout(location = 3) uniform uint tileArraySize;\n"
"layout(location = 4) uniform vec2 scaling;\n"
"\n"
"void main()\n"
"{\n"
" uint triangleIndex = (gl_WorkGroupID.x*gl_WorkGroupSize.x + gl_LocalInvocationIndex) * 3u;\n"
" if(triangleIndex >= indexCount)\n"
" {\n"
" return;\n"
" }\n"
"\n"
" uint i0 = indexBuffer.elements[triangleIndex];\n"
" uint i1 = indexBuffer.elements[triangleIndex+1u];\n"
" uint i2 = indexBuffer.elements[triangleIndex+2u];\n"
"\n"
" vec2 p0 = vertexBuffer.elements[i0].pos * scaling;\n"
" vec2 p1 = vertexBuffer.elements[i1].pos * scaling;\n"
" vec2 p2 = vertexBuffer.elements[i2].pos * scaling;\n"
"\n"
" int shapeIndex = vertexBuffer.elements[i0].shapeIndex;\n"
" vec4 clip = shapeBuffer.elements[shapeIndex].clip * vec4(scaling, scaling);\n"
"\n"
" vec4 fbox = vec4(max(min(min(p0.x, p1.x), p2.x), clip.x),\n"
" max(min(min(p0.y, p1.y), p2.y), clip.y),\n"
" min(max(max(p0.x, p1.x), p2.x), clip.z),\n"
" min(max(max(p0.y, p1.y), p2.y), clip.w));\n"
"\n"
" ivec4 box = ivec4(floor(fbox))/int(tileSize);\n"
"\n"
" //NOTE(martin): it's importat to do the computation with signed int, so that we can have negative xMax/yMax\n"
" // otherwise all triangles on the left or below the x/y axis are attributed to tiles on row/column 0.\n"
" int xMin = max(0, box.x);\n"
" int yMin = max(0, box.y);\n"
" int xMax = min(box.z, int(tileCount.x) - 1);\n"
" int yMax = min(box.w, int(tileCount.y) - 1);\n"
"\n"
" for(int y = yMin; y <= yMax; y++)\n"
" {\n"
" for(int x = xMin ; x <= xMax; x++)\n"
" {\n"
" uint tileIndex = uint(y)*tileCount.x + uint(x);\n"
" uint tileCounter = atomicAdd(tileCounterBuffer.elements[tileIndex], 1u);\n"
" if(tileCounter < tileArraySize)\n"
" {\n"
" tileArrayBuffer.elements[tileArraySize*tileIndex + tileCounter] = triangleIndex;\n"
" }\n"
" }\n"
" }\n"
"}\n";
//NOTE: string imported from src\glsl_shaders\sort.glsl
const char* glsl_sort =
"\n"
"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
"\n"
"precision mediump float;\n"
"\n"
"layout(binding = 0) restrict readonly buffer vertexBufferSSBO {\n"
" vertex elements[];\n"
"} vertexBuffer ;\n"
"\n"
"layout(binding = 1) restrict readonly buffer shapeBufferSSBO {\n"
" shape elements[];\n"
"} shapeBuffer ;\n"
"\n"
"layout(binding = 2) restrict readonly buffer indexBufferSSBO {\n"
" uint elements[];\n"
"} indexBuffer ;\n"
"\n"
"layout(binding = 3) coherent readonly restrict buffer tileCounterBufferSSBO {\n"
" uint elements[];\n"
"} tileCounterBuffer ;\n"
"\n"
"layout(binding = 4) coherent restrict buffer tileArrayBufferSSBO {\n"
" uint elements[];\n"
"} tileArrayBuffer ;\n"
"\n"
"layout(location = 0) uniform uint indexCount;\n"
"layout(location = 1) uniform uvec2 tileCount;\n"
"layout(location = 2) uniform uint tileSize;\n"
"layout(location = 3) uniform uint tileArraySize;\n"
"\n"
"int get_shape_index(uint tileArrayOffset, uint tileArrayIndex)\n"
"{\n"
" uint triangleIndex = tileArrayBuffer.elements[tileArrayOffset + tileArrayIndex];\n"
" uint i0 = indexBuffer.elements[triangleIndex];\n"
" int shapeIndex = vertexBuffer.elements[i0].shapeIndex;\n"
" return(shapeIndex);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" uint tileIndex = gl_WorkGroupID.x;\n"
" uint tileArrayOffset = tileArraySize * tileIndex;\n"
" uint tileArrayCount = min(tileCounterBuffer.elements[tileIndex], tileArraySize);\n"
"\n"
" for(uint tileArrayIndex=1u; tileArrayIndex < tileArrayCount; tileArrayIndex++)\n"
" {\n"
" for(uint sortIndex = tileArrayIndex; sortIndex > 0u; sortIndex--)\n"
" {\n"
" int shapeIndex = get_shape_index(tileArrayOffset, sortIndex);\n"
" int prevShapeIndex = get_shape_index(tileArrayOffset, sortIndex-1u);\n"
"\n"
" if(shapeIndex >= prevShapeIndex)\n"
" {\n"
" break;\n"
" }\n"
" uint tmp = tileArrayBuffer.elements[tileArrayOffset + sortIndex];\n"
" tileArrayBuffer.elements[tileArrayOffset + sortIndex] = tileArrayBuffer.elements[tileArrayOffset + sortIndex - 1u];\n"
" tileArrayBuffer.elements[tileArrayOffset + sortIndex - 1u] = tmp;\n"
" }\n"
" }\n"
"}\n";
//NOTE: string imported from src\glsl_shaders\draw.glsl
const char* glsl_draw =
"\n"
"#extension GL_ARB_gpu_shader_int64 : require\n"
"layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;\n"
"\n"
"precision mediump float;\n"
"//precision mediump image2D;\n"
"\n"
"layout(binding = 0) restrict readonly buffer vertexBufferSSBO {\n"
" vertex elements[];\n"
"} vertexBuffer ;\n"
"\n"
"layout(binding = 1) restrict readonly buffer shapeBufferSSBO {\n"
" shape elements[];\n"
"} shapeBuffer ;\n"
"\n"
"layout(binding = 2) restrict readonly buffer indexBufferSSBO {\n"
" uint elements[];\n"
"} indexBuffer ;\n"
"\n"
"layout(binding = 3) restrict readonly buffer tileCounterBufferSSBO {\n"
" uint elements[];\n"
"} tileCounterBuffer ;\n"
"\n"
"layout(binding = 4) restrict readonly buffer tileArrayBufferSSBO {\n"
" uint elements[];\n"
"} tileArrayBuffer ;\n"
"\n"
"layout(location = 0) uniform uint indexCount;\n"
"layout(location = 1) uniform uvec2 tileCount;\n"
"layout(location = 2) uniform uint tileSize;\n"
"layout(location = 3) uniform uint tileArraySize;\n"
"layout(location = 4) uniform vec2 scaling;\n"
"layout(location = 5) uniform uint useTexture;\n"
"\n"
"layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;\n"
"\n"
"layout(binding = 1) uniform sampler2D srcTexture;\n"
"\n"
"\n"
"bool is_top_left(ivec2 a, ivec2 b)\n"
"{\n"
" return( (a.y == b.y && b.x < a.x)\n"
" ||(b.y < a.y));\n"
"}\n"
"\n"
"//////////////////////////////////////////////////////////////////////////////\n"
"//TODO: we should do these computations on 64bits, because otherwise\n"
"// we might overflow for values > 2048.\n"
"// Unfortunately this is costly.\n"
"// Another way is to precompute triangle edges (b - a) in full precision\n"
"// once to avoid doing it all the time...\n"
"//////////////////////////////////////////////////////////////////////////////\n"
"int orient2d(ivec2 a, ivec2 b, ivec2 p)\n"
"{\n"
" return((b.x-a.x)*(p.y-a.y) - (b.y-a.y)*(p.x-a.x));\n"
"}\n"
"\n"
"int is_clockwise(ivec2 p0, ivec2 p1, ivec2 p2)\n"
"{\n"
" return((p1 - p0).x*(p2 - p0).y - (p1 - p0).y*(p2 - p0).x);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" ivec2 pixelCoord = ivec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy);\n"
" uvec2 tileCoord = uvec2(pixelCoord) / tileSize;\n"
" uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x;\n"
" uint tileCounter = min(tileCounterBuffer.elements[tileIndex], tileArraySize);\n"
"\n"
" const float subPixelFactor = 16.;\n"
" ivec2 centerPoint = ivec2((vec2(pixelCoord) + vec2(0.5, 0.5)) * subPixelFactor);\n"
"\n"
"//*\n"
" const int sampleCount = 8;\n"
" ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3),\n"
" centerPoint + ivec2(-1, -3),\n"
" centerPoint + ivec2(5, -1),\n"
" centerPoint + ivec2(-3, 5),\n"
" centerPoint + ivec2(-5, -5),\n"
" centerPoint + ivec2(-7, 1),\n"
" centerPoint + ivec2(3, -7),\n"
" centerPoint + ivec2(7, 7));\n"
"/*/\n"
" const int sampleCount = 4;\n"
" ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(-2, 6),\n"
" centerPoint + ivec2(6, 2),\n"
" centerPoint + ivec2(-6, -2),\n"
" centerPoint + ivec2(2, -6));\n"
"//*/\n"
" //DEBUG\n"
"/*\n"
" {\n"
" vec4 fragColor = vec4(0);\n"
"\n"
" if( pixelCoord.x % 16 == 0\n"
" ||pixelCoord.y % 16 == 0)\n"
" {\n"
" fragColor = vec4(0, 0, 0, 1);\n"
" }\n"
" else if(tileCounterBuffer.elements[tileIndex] == 0xffffu)\n"
" {\n"
" fragColor = vec4(1, 0, 1, 1);\n"
" }\n"
" else if(tileCounter != 0u)\n"
" {\n"
" fragColor = vec4(0, 1, 0, 1);\n"
" }\n"
" else\n"
" {\n"
" fragColor = vec4(1, 0, 0, 1);\n"
" }\n"
" imageStore(outTexture, pixelCoord, fragColor);\n"
" return;\n"
" }\n"
"//*/\n"
" //----\n"
"\n"
" vec4 sampleColor[sampleCount];\n"
" vec4 currentColor[sampleCount];\n"
" int currentShapeIndex[sampleCount];\n"
" int flipCount[sampleCount];\n"
"\n"
" for(int i=0; i<sampleCount; i++)\n"
" {\n"
" currentShapeIndex[i] = -1;\n"
" flipCount[i] = 0;\n"
" sampleColor[i] = vec4(0, 0, 0, 0);\n"
" currentColor[i] = vec4(0, 0, 0, 0);\n"
" }\n"
"\n"
" for(uint tileArrayIndex=0u; tileArrayIndex < tileCounter; tileArrayIndex++)\n"
" {\n"
" uint triangleIndex = tileArrayBuffer.elements[tileArraySize * tileIndex + tileArrayIndex];\n"
"\n"
" uint i0 = indexBuffer.elements[triangleIndex];\n"
" uint i1 = indexBuffer.elements[triangleIndex+1u];\n"
" uint i2 = indexBuffer.elements[triangleIndex+2u];\n"
"\n"
" ivec2 p0 = ivec2((vertexBuffer.elements[i0].pos * scaling) * subPixelFactor);\n"
" ivec2 p1 = ivec2((vertexBuffer.elements[i1].pos * scaling) * subPixelFactor);\n"
" ivec2 p2 = ivec2((vertexBuffer.elements[i2].pos * scaling) * subPixelFactor);\n"
"\n"
" int shapeIndex = vertexBuffer.elements[i0].shapeIndex;\n"
" vec4 color = shapeBuffer.elements[shapeIndex].color;\n"
" color.rgb *= color.a;\n"
"\n"
" ivec4 clip = ivec4(round((shapeBuffer.elements[shapeIndex].clip * vec4(scaling, scaling) + vec4(0.5, 0.5, 0.5, 0.5)) * subPixelFactor));\n"
"\n"
" mat3 uvTransform = mat3(shapeBuffer.elements[shapeIndex].uvTransform[0],\n"
" shapeBuffer.elements[shapeIndex].uvTransform[3],\n"
" 0.,\n"
" shapeBuffer.elements[shapeIndex].uvTransform[1],\n"
" shapeBuffer.elements[shapeIndex].uvTransform[4],\n"
" 0.,\n"
" shapeBuffer.elements[shapeIndex].uvTransform[2],\n"
" shapeBuffer.elements[shapeIndex].uvTransform[5],\n"
" 1.);\n"
"\n"
" //NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge\n"
" int cw = is_clockwise(p0, p1, p2);\n"
" if(cw < 0)\n"
" {\n"
" uint tmpIndex = i1;\n"
" i1 = i2;\n"
" i2 = tmpIndex;\n"
"\n"
" ivec2 tmpPoint = p1;\n"
" p1 = p2;\n"
" p2 = tmpPoint;\n"
" }\n"
"\n"
" vec4 cubic0 = vertexBuffer.elements[i0].cubic;\n"
" vec4 cubic1 = vertexBuffer.elements[i1].cubic;\n"
" vec4 cubic2 = vertexBuffer.elements[i2].cubic;\n"
"\n"
" int bias0 = is_top_left(p1, p2) ? 0 : -1;\n"
" int bias1 = is_top_left(p2, p0) ? 0 : -1;\n"
" int bias2 = is_top_left(p0, p1) ? 0 : -1;\n"
"\n"
" for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)\n"
" {\n"
" ivec2 samplePoint = samplePoints[sampleIndex];\n"
"\n"
" if( samplePoint.x < clip.x\n"
" || samplePoint.x > clip.z\n"
" || samplePoint.y < clip.y\n"
" || samplePoint.y > clip.w)\n"
" {\n"
" continue;\n"
" }\n"
"\n"
" int w0 = orient2d(p1, p2, samplePoint);\n"
" int w1 = orient2d(p2, p0, samplePoint);\n"
" int w2 = orient2d(p0, p1, samplePoint);\n"
"\n"
" if((w0+bias0) >= 0 && (w1+bias1) >= 0 && (w2+bias2) >= 0)\n"
" {\n"
" vec4 cubic = (cubic0*float(w0) + cubic1*float(w1) + cubic2*float(w2))/(float(w0)+float(w1)+float(w2));\n"
"\n"
" float eps = 0.0001;\n"
" if(cubic.w*(cubic.x*cubic.x*cubic.x - cubic.y*cubic.z) <= eps)\n"
" {\n"
" if(shapeIndex == currentShapeIndex[sampleIndex])\n"
" {\n"
" flipCount[sampleIndex]++;\n"
" }\n"
" else\n"
" {\n"
" if((flipCount[sampleIndex] & 0x01) != 0)\n"
" {\n"
" sampleColor[sampleIndex] = currentColor[sampleIndex];\n"
" }\n"
"\n"
" vec4 nextColor = color;\n"
" if(useTexture)\n"
" {\n"
" vec3 sampleFP = vec3(vec2(samplePoint).xy/(subPixelFactor*2.), 1);\n"
" vec2 uv = (uvTransform * sampleFP).xy;\n"
" vec4 texColor = texture(srcTexture, uv);\n"
" texColor.rgb *= texColor.a;\n"
" nextColor *= texColor;\n"
" }\n"
" currentColor[sampleIndex] = sampleColor[sampleIndex]*(1.-nextColor.a) + nextColor;\n"
" currentShapeIndex[sampleIndex] = shapeIndex;\n"
" flipCount[sampleIndex] = 1;\n"
" }\n"
" }\n"
" }\n"
" }\n"
" }\n"
" vec4 pixelColor = vec4(0);\n"
" for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)\n"
" {\n"
" if((flipCount[sampleIndex] & 0x01) != 0)\n"
" {\n"
" sampleColor[sampleIndex] = currentColor[sampleIndex];\n"
" }\n"
" pixelColor += sampleColor[sampleIndex];\n"
" }\n"
"\n"
" imageStore(outTexture, pixelCoord, pixelColor/float(sampleCount));\n"
"}\n";
#endif // __GLSL_SHADERS_H__

View File

@ -1,407 +1,407 @@
/************************************************************//** /************************************************************//**
* *
* @file: graphics_surface.c * @file: graphics_surface.c
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 25/04/2023 * @date: 25/04/2023
* *
*****************************************************************/ *****************************************************************/
#include"graphics_surface.h" #include"graphics_surface.h"
//--------------------------------------------------------------- //---------------------------------------------------------------
// typed handles functions // typed handles functions
//--------------------------------------------------------------- //---------------------------------------------------------------
mg_surface mg_surface_handle_alloc(mg_surface_data* surface) mg_surface mg_surface_handle_alloc(mg_surface_data* surface)
{ {
mg_surface handle = {.h = mg_handle_alloc(MG_HANDLE_SURFACE, (void*)surface) }; mg_surface handle = {.h = mg_handle_alloc(MG_HANDLE_SURFACE, (void*)surface) };
return(handle); return(handle);
} }
mg_surface_data* mg_surface_data_from_handle(mg_surface handle) mg_surface_data* mg_surface_data_from_handle(mg_surface handle)
{ {
mg_surface_data* data = mg_data_from_handle(MG_HANDLE_SURFACE, handle.h); mg_surface_data* data = mg_data_from_handle(MG_HANDLE_SURFACE, handle.h);
return(data); return(data);
} }
mg_image mg_image_handle_alloc(mg_image_data* image) mg_image mg_image_handle_alloc(mg_image_data* image)
{ {
mg_image handle = {.h = mg_handle_alloc(MG_HANDLE_IMAGE, (void*)image) }; mg_image handle = {.h = mg_handle_alloc(MG_HANDLE_IMAGE, (void*)image) };
return(handle); return(handle);
} }
mg_image_data* mg_image_data_from_handle(mg_image handle) mg_image_data* mg_image_data_from_handle(mg_image handle)
{ {
mg_image_data* data = mg_data_from_handle(MG_HANDLE_IMAGE, handle.h); mg_image_data* data = mg_data_from_handle(MG_HANDLE_IMAGE, handle.h);
return(data); return(data);
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
// surface API // surface API
//--------------------------------------------------------------- //---------------------------------------------------------------
#if MG_COMPILE_GL #if MG_COMPILE_GL
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
#include"wgl_surface.h" #include"wgl_surface.h"
#define gl_surface_create_for_window mg_wgl_surface_create_for_window #define gl_surface_create_for_window mg_wgl_surface_create_for_window
#endif #endif
#endif #endif
#if MG_COMPILE_GLES #if MG_COMPILE_GLES
#include"egl_surface.h" #include"egl_surface.h"
#endif #endif
#if MG_COMPILE_METAL #if MG_COMPILE_METAL
#include"mtl_surface.h" #include"mtl_surface.h"
#endif #endif
#if MG_COMPILE_CANVAS #if MG_COMPILE_CANVAS
#if PLATFORM_MACOS #if PLATFORM_MACOS
mg_surface_data* mtl_canvas_surface_create_for_window(mp_window window); mg_surface_data* mtl_canvas_surface_create_for_window(mp_window window);
#elif PLATFORM_WINDOWS #elif PLATFORM_WINDOWS
//TODO mg_surface_data* gl_canvas_surface_create_for_window(mp_window window);
#endif #endif
#endif #endif
bool mg_is_surface_backend_available(mg_surface_api api) bool mg_is_surface_backend_available(mg_surface_api api)
{ {
bool result = false; bool result = false;
switch(api) switch(api)
{ {
#if MG_COMPILE_METAL #if MG_COMPILE_METAL
case MG_METAL: case MG_METAL:
#endif #endif
#if MG_COMPILE_GL #if MG_COMPILE_GL
case MG_GL: case MG_GL:
#endif #endif
#if MG_COMPILE_GLES #if MG_COMPILE_GLES
case MG_GLES: case MG_GLES:
#endif #endif
#if MG_COMPILE_CANVAS #if MG_COMPILE_CANVAS
case MG_CANVAS: case MG_CANVAS:
#endif #endif
result = true; result = true;
break; break;
default: default:
break; break;
} }
return(result); return(result);
} }
mg_surface mg_surface_nil() { return((mg_surface){.h = 0}); } mg_surface mg_surface_nil() { return((mg_surface){.h = 0}); }
bool mg_surface_is_nil(mg_surface surface) { return(surface.h == 0); } bool mg_surface_is_nil(mg_surface surface) { return(surface.h == 0); }
mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api) mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api)
{ {
if(__mgData.init) if(__mgData.init)
{ {
mg_init(); mg_init();
} }
mg_surface surfaceHandle = mg_surface_nil(); mg_surface surfaceHandle = mg_surface_nil();
mg_surface_data* surface = 0; mg_surface_data* surface = 0;
switch(api) switch(api)
{ {
#if MG_COMPILE_GL #if MG_COMPILE_GL
case MG_GL: case MG_GL:
surface = gl_surface_create_for_window(window); surface = gl_surface_create_for_window(window);
break; break;
#endif #endif
#if MG_COMPILE_GLES #if MG_COMPILE_GLES
case MG_GLES: case MG_GLES:
surface = mg_egl_surface_create_for_window(window); surface = mg_egl_surface_create_for_window(window);
break; break;
#endif #endif
#if MG_COMPILE_METAL #if MG_COMPILE_METAL
case MG_METAL: case MG_METAL:
surface = mg_mtl_surface_create_for_window(window); surface = mg_mtl_surface_create_for_window(window);
break; break;
#endif #endif
#if MG_COMPILE_CANVAS #if MG_COMPILE_CANVAS
case MG_CANVAS: case MG_CANVAS:
#if PLATFORM_MACOS #if PLATFORM_MACOS
surface = mtl_canvas_surface_create_for_window(window); surface = mtl_canvas_surface_create_for_window(window);
#elif PLATFORM_WINDOWS #elif PLATFORM_WINDOWS
surface = gl_canvas_surface_create_for_window(window); surface = gl_canvas_surface_create_for_window(window);
#endif #endif
break; break;
#endif #endif
default: default:
break; break;
} }
if(surface) if(surface)
{ {
surfaceHandle = mg_surface_handle_alloc(surface); surfaceHandle = mg_surface_handle_alloc(surface);
} }
return(surfaceHandle); return(surfaceHandle);
} }
mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api) mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api)
{ {
if(__mgData.init) if(__mgData.init)
{ {
mg_init(); mg_init();
} }
mg_surface surfaceHandle = mg_surface_nil(); mg_surface surfaceHandle = mg_surface_nil();
mg_surface_data* surface = 0; mg_surface_data* surface = 0;
switch(api) switch(api)
{ {
#if MG_COMPILE_GLES #if MG_COMPILE_GLES
case MG_GLES: case MG_GLES:
surface = mg_egl_surface_create_remote(width, height); surface = mg_egl_surface_create_remote(width, height);
break; break;
#endif #endif
default: default:
break; break;
} }
if(surface) if(surface)
{ {
surfaceHandle = mg_surface_handle_alloc(surface); surfaceHandle = mg_surface_handle_alloc(surface);
} }
return(surfaceHandle); return(surfaceHandle);
} }
mg_surface mg_surface_create_host(mp_window window) mg_surface mg_surface_create_host(mp_window window)
{ {
if(__mgData.init) if(__mgData.init)
{ {
mg_init(); mg_init();
} }
mg_surface handle = mg_surface_nil(); mg_surface handle = mg_surface_nil();
mg_surface_data* surface = 0; mg_surface_data* surface = 0;
#if PLATFORM_MACOS #if PLATFORM_MACOS
surface = mg_osx_surface_create_host(window); surface = mg_osx_surface_create_host(window);
#elif PLATFORM_WINDOWS #elif PLATFORM_WINDOWS
surface = mg_win32_surface_create_host(window); surface = mg_win32_surface_create_host(window);
#endif #endif
if(surface) if(surface)
{ {
handle = mg_surface_handle_alloc(surface); handle = mg_surface_handle_alloc(surface);
} }
return(handle); return(handle);
} }
void mg_surface_destroy(mg_surface handle) void mg_surface_destroy(mg_surface handle)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
mg_surface_data* surface = mg_surface_data_from_handle(handle); mg_surface_data* surface = mg_surface_data_from_handle(handle);
if(surface) if(surface)
{ {
if(surface->backend && surface->backend->destroy) if(surface->backend && surface->backend->destroy)
{ {
surface->backend->destroy(surface->backend); surface->backend->destroy(surface->backend);
} }
surface->destroy(surface); surface->destroy(surface);
mg_handle_recycle(handle.h); mg_handle_recycle(handle.h);
} }
} }
void mg_surface_prepare(mg_surface surface) void mg_surface_prepare(mg_surface surface)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->prepare) if(surfaceData && surfaceData->prepare)
{ {
surfaceData->prepare(surfaceData); surfaceData->prepare(surfaceData);
} }
} }
void mg_surface_present(mg_surface surface) void mg_surface_present(mg_surface surface)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->present) if(surfaceData && surfaceData->present)
{ {
surfaceData->present(surfaceData); surfaceData->present(surfaceData);
} }
} }
void mg_surface_swap_interval(mg_surface surface, int swap) void mg_surface_swap_interval(mg_surface surface, int swap)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->swapInterval) if(surfaceData && surfaceData->swapInterval)
{ {
surfaceData->swapInterval(surfaceData, swap); surfaceData->swapInterval(surfaceData, swap);
} }
} }
vec2 mg_surface_contents_scaling(mg_surface surface) vec2 mg_surface_contents_scaling(mg_surface surface)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
vec2 scaling = {1, 1}; vec2 scaling = {1, 1};
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->contentsScaling) if(surfaceData && surfaceData->contentsScaling)
{ {
scaling = surfaceData->contentsScaling(surfaceData); scaling = surfaceData->contentsScaling(surfaceData);
} }
return(scaling); return(scaling);
} }
void mg_surface_set_frame(mg_surface surface, mp_rect frame) void mg_surface_set_frame(mg_surface surface, mp_rect frame)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->setFrame) if(surfaceData && surfaceData->setFrame)
{ {
surfaceData->setFrame(surfaceData, frame); surfaceData->setFrame(surfaceData, frame);
} }
} }
mp_rect mg_surface_get_frame(mg_surface surface) mp_rect mg_surface_get_frame(mg_surface surface)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
mp_rect res = {0}; mp_rect res = {0};
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->getFrame) if(surfaceData && surfaceData->getFrame)
{ {
res = surfaceData->getFrame(surfaceData); res = surfaceData->getFrame(surfaceData);
} }
return(res); return(res);
} }
void mg_surface_set_hidden(mg_surface surface, bool hidden) void mg_surface_set_hidden(mg_surface surface, bool hidden)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->setHidden) if(surfaceData && surfaceData->setHidden)
{ {
surfaceData->setHidden(surfaceData, hidden); surfaceData->setHidden(surfaceData, hidden);
} }
} }
bool mg_surface_get_hidden(mg_surface surface) bool mg_surface_get_hidden(mg_surface surface)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);
bool res = false; bool res = false;
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->getHidden) if(surfaceData && surfaceData->getHidden)
{ {
res = surfaceData->getHidden(surfaceData); res = surfaceData->getHidden(surfaceData);
} }
return(res); return(res);
} }
void* mg_surface_native_layer(mg_surface surface) void* mg_surface_native_layer(mg_surface surface)
{ {
void* res = 0; void* res = 0;
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->nativeLayer) if(surfaceData && surfaceData->nativeLayer)
{ {
res = surfaceData->nativeLayer(surfaceData); res = surfaceData->nativeLayer(surfaceData);
} }
return(res); return(res);
} }
mg_surface_id mg_surface_remote_id(mg_surface handle) mg_surface_id mg_surface_remote_id(mg_surface handle)
{ {
mg_surface_id remoteId = 0; mg_surface_id remoteId = 0;
mg_surface_data* surface = mg_surface_data_from_handle(handle); mg_surface_data* surface = mg_surface_data_from_handle(handle);
if(surface && surface->remoteID) if(surface && surface->remoteID)
{ {
remoteId = surface->remoteID(surface); remoteId = surface->remoteID(surface);
} }
return(remoteId); return(remoteId);
} }
void mg_surface_host_connect(mg_surface handle, mg_surface_id remoteID) void mg_surface_host_connect(mg_surface handle, mg_surface_id remoteID)
{ {
mg_surface_data* surface = mg_surface_data_from_handle(handle); mg_surface_data* surface = mg_surface_data_from_handle(handle);
if(surface && surface->hostConnect) if(surface && surface->hostConnect)
{ {
surface->hostConnect(surface, remoteID); surface->hostConnect(surface, remoteID);
} }
} }
void mg_surface_render_commands(mg_surface surface, void mg_surface_render_commands(mg_surface surface,
mg_color clearColor, mg_color clearColor,
u32 primitiveCount, u32 primitiveCount,
mg_primitive* primitives, mg_primitive* primitives,
u32 eltCount, u32 eltCount,
mg_path_elt* elements) mg_path_elt* elements)
{ {
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->backend) if(surfaceData && surfaceData->backend)
{ {
surfaceData->backend->render(surfaceData->backend, surfaceData->backend->render(surfaceData->backend,
clearColor, clearColor,
primitiveCount, primitiveCount,
primitives, primitives,
eltCount, eltCount,
elements); elements);
} }
} }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
//NOTE(martin): images //NOTE(martin): images
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
vec2 mg_image_size(mg_image image) vec2 mg_image_size(mg_image image)
{ {
vec2 res = {0}; vec2 res = {0};
mg_image_data* imageData = mg_image_data_from_handle(image); mg_image_data* imageData = mg_image_data_from_handle(image);
if(imageData) if(imageData)
{ {
res = imageData->size; res = imageData->size;
} }
return(res); return(res);
} }
mg_image mg_image_create(mg_surface surface, u32 width, u32 height) mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
{ {
mg_image image = mg_image_nil(); mg_image image = mg_image_nil();
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->backend) if(surfaceData && surfaceData->backend)
{ {
DEBUG_ASSERT(surfaceData->api == MG_CANVAS); DEBUG_ASSERT(surfaceData->api == MG_CANVAS);
mg_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (vec2){width, height}); mg_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (vec2){width, height});
if(imageData) if(imageData)
{ {
imageData->surface = surface; imageData->surface = surface;
image = mg_image_handle_alloc(imageData); image = mg_image_handle_alloc(imageData);
} }
} }
return(image); return(image);
} }
void mg_image_destroy(mg_image image) void mg_image_destroy(mg_image image)
{ {
mg_image_data* imageData = mg_image_data_from_handle(image); mg_image_data* imageData = mg_image_data_from_handle(image);
if(imageData) if(imageData)
{ {
mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface); mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface);
if(surface && surface->backend) if(surface && surface->backend)
{ {
surface->backend->imageDestroy(surface->backend, imageData); surface->backend->imageDestroy(surface->backend, imageData);
mg_handle_recycle(image.h); mg_handle_recycle(image.h);
} }
} }
} }
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels) void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
{ {
mg_image_data* imageData = mg_image_data_from_handle(image); mg_image_data* imageData = mg_image_data_from_handle(image);
if(imageData) if(imageData)
{ {
mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface); mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface);
if(surfaceData) if(surfaceData)
{ {
DEBUG_ASSERT(surfaceData->backend); DEBUG_ASSERT(surfaceData->backend);
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels); surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
} }
} }
} }

View File

@ -1,158 +1,154 @@
/************************************************************//** /************************************************************//**
* *
* @file: graphics_surface.h * @file: graphics_surface.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 26/04/2023 * @date: 26/04/2023
* *
*****************************************************************/ *****************************************************************/
#ifndef __GRAPHICS_SURFACE_H_ #ifndef __GRAPHICS_SURFACE_H_
#define __GRAPHICS_SURFACE_H_ #define __GRAPHICS_SURFACE_H_
#include"graphics_common.h" #include"graphics_common.h"
#include"mp_app_internal.h" #include"mp_app_internal.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
//--------------------------------------------------------------- //---------------------------------------------------------------
// surface interface // surface interface
//--------------------------------------------------------------- //---------------------------------------------------------------
typedef struct mg_surface_data mg_surface_data; typedef struct mg_surface_data mg_surface_data;
typedef struct mg_canvas_backend mg_canvas_backend; typedef struct mg_canvas_backend mg_canvas_backend;
typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface); typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface);
typedef void (*mg_surface_prepare_proc)(mg_surface_data* surface); typedef void (*mg_surface_prepare_proc)(mg_surface_data* surface);
typedef void (*mg_surface_present_proc)(mg_surface_data* surface); typedef void (*mg_surface_present_proc)(mg_surface_data* surface);
typedef void (*mg_surface_swap_interval_proc)(mg_surface_data* surface, int swap); typedef void (*mg_surface_swap_interval_proc)(mg_surface_data* surface, int swap);
typedef vec2 (*mg_surface_contents_scaling_proc)(mg_surface_data* surface); typedef vec2 (*mg_surface_contents_scaling_proc)(mg_surface_data* surface);
typedef mp_rect (*mg_surface_get_frame_proc)(mg_surface_data* surface); typedef mp_rect (*mg_surface_get_frame_proc)(mg_surface_data* surface);
typedef void (*mg_surface_set_frame_proc)(mg_surface_data* surface, mp_rect frame); typedef void (*mg_surface_set_frame_proc)(mg_surface_data* surface, mp_rect frame);
typedef bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface); typedef bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface);
typedef void (*mg_surface_set_hidden_proc)(mg_surface_data* surface, bool hidden); typedef void (*mg_surface_set_hidden_proc)(mg_surface_data* surface, bool hidden);
typedef void* (*mg_surface_native_layer_proc)(mg_surface_data* surface); typedef void* (*mg_surface_native_layer_proc)(mg_surface_data* surface);
typedef mg_surface_id (*mg_surface_remote_id_proc)(mg_surface_data* surface); typedef mg_surface_id (*mg_surface_remote_id_proc)(mg_surface_data* surface);
typedef void (*mg_surface_host_connect_proc)(mg_surface_data* surface, mg_surface_id remoteId); typedef void (*mg_surface_host_connect_proc)(mg_surface_data* surface, mg_surface_id remoteId);
typedef struct mg_surface_data typedef struct mg_surface_data
{ {
mg_surface_api api; mg_surface_api api;
mp_layer layer; mp_layer layer;
mg_surface_destroy_proc destroy; mg_surface_destroy_proc destroy;
mg_surface_prepare_proc prepare; mg_surface_prepare_proc prepare;
mg_surface_present_proc present; mg_surface_present_proc present;
mg_surface_swap_interval_proc swapInterval; mg_surface_swap_interval_proc swapInterval;
mg_surface_contents_scaling_proc contentsScaling; mg_surface_contents_scaling_proc contentsScaling;
mg_surface_get_frame_proc getFrame; mg_surface_get_frame_proc getFrame;
mg_surface_set_frame_proc setFrame; mg_surface_set_frame_proc setFrame;
mg_surface_get_hidden_proc getHidden; mg_surface_get_hidden_proc getHidden;
mg_surface_set_hidden_proc setHidden; mg_surface_set_hidden_proc setHidden;
mg_surface_native_layer_proc nativeLayer; mg_surface_native_layer_proc nativeLayer;
mg_surface_remote_id_proc remoteID; mg_surface_remote_id_proc remoteID;
mg_surface_host_connect_proc hostConnect; mg_surface_host_connect_proc hostConnect;
mg_canvas_backend* backend; mg_canvas_backend* backend;
} mg_surface_data; } mg_surface_data;
mg_surface mg_surface_alloc_handle(mg_surface_data* surface); mg_surface mg_surface_alloc_handle(mg_surface_data* surface);
mg_surface_data* mg_surface_data_from_handle(mg_surface handle); mg_surface_data* mg_surface_data_from_handle(mg_surface handle);
void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window); void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window);
void mg_surface_init_remote(mg_surface_data* surface, u32 width, u32 height); void mg_surface_init_remote(mg_surface_data* surface, u32 width, u32 height);
void mg_surface_init_host(mg_surface_data* surface, mp_window_data* window); void mg_surface_init_host(mg_surface_data* surface, mp_window_data* window);
void mg_surface_cleanup(mg_surface_data* surface); void mg_surface_cleanup(mg_surface_data* surface);
void* mg_surface_native_layer(mg_surface surface); void* mg_surface_native_layer(mg_surface surface);
//--------------------------------------------------------------- //---------------------------------------------------------------
// canvas backend interface // canvas backend interface
//--------------------------------------------------------------- //---------------------------------------------------------------
typedef struct mg_image_data typedef struct mg_image_data
{ {
list_elt listElt; list_elt listElt;
u32 generation; u32 generation;
mg_surface surface; mg_surface surface;
vec2 size; vec2 size;
} mg_image_data; } mg_image_data;
typedef struct mg_vertex_layout typedef struct mg_vertex_layout
{ {
u32 maxVertexCount; u32 maxVertexCount;
u32 maxIndexCount; u32 maxIndexCount;
char* posBuffer; char* posBuffer;
u32 posStride; u32 posStride;
char* cubicBuffer; char* cubicBuffer;
u32 cubicStride; u32 cubicStride;
char* uvTransformBuffer; char* shapeIndexBuffer;
u32 uvTransformStride; u32 shapeIndexStride;
char* colorBuffer; char* colorBuffer;
u32 colorStride; u32 colorStride;
char* texturedBuffer; char* clipBuffer;
u32 texturedStride; u32 clipStride;
char* shapeIndexBuffer; char* uvTransformBuffer;
u32 shapeIndexStride; u32 uvTransformStride;
char* clipBuffer; char* indexBuffer;
u32 clipStride; u32 indexStride;
char* indexBuffer; } mg_vertex_layout;
u32 indexStride;
typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend);
} mg_vertex_layout; typedef void (*mg_canvas_backend_begin_proc)(mg_canvas_backend* backend, mg_color clearColor);
typedef void (*mg_canvas_backend_end_proc)(mg_canvas_backend* backend);
typedef void (*mg_canvas_backend_draw_batch_proc)(mg_canvas_backend* backend,
typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend); mg_image_data* imageData,
typedef void (*mg_canvas_backend_begin_proc)(mg_canvas_backend* backend, mg_color clearColor); u32 vertexCount,
typedef void (*mg_canvas_backend_end_proc)(mg_canvas_backend* backend); u32 shapeCount,
typedef void (*mg_canvas_backend_draw_batch_proc)(mg_canvas_backend* backend, u32 indexCount);
mg_image_data* imageData,
u32 vertexCount,
u32 shapeCount, typedef mg_image_data* (*mg_canvas_backend_image_create_proc)(mg_canvas_backend* backend, vec2 size);
u32 indexCount); typedef void (*mg_canvas_backend_image_destroy_proc)(mg_canvas_backend* backend, mg_image_data* image);
typedef void (*mg_canvas_backend_image_upload_region_proc)(mg_canvas_backend* backend,
mg_image_data* image,
typedef mg_image_data* (*mg_canvas_backend_image_create_proc)(mg_canvas_backend* backend, vec2 size); mp_rect region,
typedef void (*mg_canvas_backend_image_destroy_proc)(mg_canvas_backend* backend, mg_image_data* image); u8* pixels);
typedef void (*mg_canvas_backend_image_upload_region_proc)(mg_canvas_backend* backend,
mg_image_data* image, typedef void (*mg_canvas_backend_render_proc)(mg_canvas_backend* backend,
mp_rect region, mg_color clearColor,
u8* pixels); u32 primitiveCount,
mg_primitive* primitives,
typedef void (*mg_canvas_backend_render_proc)(mg_canvas_backend* backend, u32 eltCount,
mg_color clearColor, mg_path_elt* pathElements);
u32 primitiveCount,
mg_primitive* primitives, typedef struct mg_canvas_backend
u32 eltCount, {
mg_path_elt* pathElements); // mg_vertex_layout vertexLayout;
typedef struct mg_canvas_backend mg_canvas_backend_destroy_proc destroy;
{ mg_canvas_backend_begin_proc begin;
mg_vertex_layout vertexLayout; mg_canvas_backend_end_proc end;
mg_canvas_backend_draw_batch_proc drawBatch;
mg_canvas_backend_destroy_proc destroy;
mg_canvas_backend_begin_proc begin; mg_canvas_backend_image_create_proc imageCreate;
mg_canvas_backend_end_proc end; mg_canvas_backend_image_destroy_proc imageDestroy;
mg_canvas_backend_draw_batch_proc drawBatch; mg_canvas_backend_image_upload_region_proc imageUploadRegion;
mg_canvas_backend_image_create_proc imageCreate;
mg_canvas_backend_image_destroy_proc imageDestroy; mg_canvas_backend_render_proc render;
mg_canvas_backend_image_upload_region_proc imageUploadRegion;
} mg_canvas_backend;
mg_canvas_backend_render_proc render; #ifdef __cplusplus
} // extern "C"
} mg_canvas_backend; #endif
#ifdef __cplusplus #endif //__GRAPHICS_SURFACE_H_
} // extern "C"
#endif
#endif //__GRAPHICS_SURFACE_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,27 @@
/************************************************************//** /************************************************************//**
* *
* @file: platform_math.h * @file: platform_math.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 26/04/2023 * @date: 26/04/2023
* *
*****************************************************************/ *****************************************************************/
#ifndef __PLATFORM_MATH_H_ #ifndef __PLATFORM_MATH_H_
#define __PLATFORM_MATH_H_ #define __PLATFORM_MATH_H_
#include"platform.h" #include"platform.h"
#if !PLATFORM_ORCA #if !PLATFORM_ORCA
#include<math.h> #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#else #include<math.h>
#else
#define M_PI 3.14159265358979323846
#define M_PI 3.14159265358979323846
double fabs(double x);
double sqrt(double sqrt); double fabs(double x);
double cos(double x); double sqrt(double sqrt);
double sin(double x); double cos(double x);
double sin(double x);
#endif
#endif
#endif //__PLATFORM_MATH_H_
#endif //__PLATFORM_MATH_H_

5632
src/ui.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@ typedef struct win32_app_data
int mouseCaptureMask; int mouseCaptureMask;
bool mouseTracked; bool mouseTracked;
vec2 lastMousePos;
} win32_app_data; } win32_app_data;

22
src/win32_manifest.xml Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="0.0.0.1"
processorArchitecture="*"
name="forkingpaths.orca.runtime"
type="win32"
/>
<description>Orca Runtime</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>