[canvas] change surface/canvas APIs to treat canvas a 'just another kind of surface', and split canvas implementation (managed by surface) from canvas _command buffer_ and implicit context (represented by mg_canvas)
This commit is contained in:
parent
32d7d91893
commit
346979a21a
|
@ -52,8 +52,6 @@ mg_font create_font()
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
LogLevel(LOG_LEVEL_WARNING);
|
|
||||||
|
|
||||||
mp_init();
|
mp_init();
|
||||||
mp_clock_init(); //TODO put that in mp_init()?
|
mp_clock_init(); //TODO put that in mp_init()?
|
||||||
|
|
||||||
|
@ -63,11 +61,10 @@ int main()
|
||||||
mp_rect contentRect = mp_window_get_content_rect(window);
|
mp_rect contentRect = mp_window_get_content_rect(window);
|
||||||
|
|
||||||
//NOTE: create surface
|
//NOTE: create surface
|
||||||
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_DEFAULT);
|
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
|
||||||
mg_surface_swap_interval(surface, 0);
|
mg_surface_swap_interval(surface, 0);
|
||||||
|
|
||||||
//TODO: create canvas
|
mg_canvas canvas = mg_canvas_create();
|
||||||
mg_canvas canvas = mg_canvas_create(surface);
|
|
||||||
|
|
||||||
if(mg_canvas_is_nil(canvas))
|
if(mg_canvas_is_nil(canvas))
|
||||||
{
|
{
|
||||||
|
@ -91,10 +88,10 @@ int main()
|
||||||
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
||||||
|
|
||||||
mp_pump_events(0);
|
mp_pump_events(0);
|
||||||
mp_event event = {0};
|
mp_event* event = 0;
|
||||||
while(mp_next_event(&event))
|
while((event = mp_next_event(mem_scratch())) != 0)
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event->type)
|
||||||
{
|
{
|
||||||
case MP_EVENT_WINDOW_CLOSE:
|
case MP_EVENT_WINDOW_CLOSE:
|
||||||
{
|
{
|
||||||
|
@ -103,23 +100,23 @@ int main()
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -154,17 +151,10 @@ int main()
|
||||||
x += dx;
|
x += dx;
|
||||||
y += dy;
|
y += dy;
|
||||||
|
|
||||||
mg_surface_prepare(surface);
|
|
||||||
|
|
||||||
// background
|
// background
|
||||||
mg_set_color_rgba(0, 1, 1, 1);
|
mg_set_color_rgba(0, 1, 1, 1);
|
||||||
mg_clear();
|
mg_clear();
|
||||||
|
|
||||||
mg_set_color_rgba(1, 0, 0, 1);
|
|
||||||
mg_set_width(2);
|
|
||||||
mg_rectangle_stroke(304, 100, 300, 250);
|
|
||||||
|
|
||||||
mg_clip_push(304, 100, 300, 250);
|
|
||||||
// head
|
// head
|
||||||
mg_set_color_rgba(1, 1, 0, 1);
|
mg_set_color_rgba(1, 1, 0, 1);
|
||||||
|
|
||||||
|
@ -183,8 +173,6 @@ int main()
|
||||||
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);
|
mg_ellipse_fill(x+70, y-50, 30, 50);
|
||||||
|
|
||||||
mg_clip_pop();
|
|
||||||
|
|
||||||
// text
|
// text
|
||||||
mg_set_color_rgba(0, 0, 1, 1);
|
mg_set_color_rgba(0, 0, 1, 1);
|
||||||
mg_set_font(font);
|
mg_set_font(font);
|
||||||
|
@ -202,7 +190,8 @@ int main()
|
||||||
frameTime,
|
frameTime,
|
||||||
1./frameTime);
|
1./frameTime);
|
||||||
|
|
||||||
mg_flush();
|
mg_surface_prepare(surface);
|
||||||
|
mg_flush(surface);
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
|
||||||
mem_arena_clear(mem_scratch());
|
mem_arena_clear(mem_scratch());
|
||||||
|
|
|
@ -94,7 +94,6 @@ mg_font create_font(const char* path)
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
LogLevel(LOG_LEVEL_MESSAGE);
|
|
||||||
mp_init();
|
mp_init();
|
||||||
mp_clock_init();
|
mp_clock_init();
|
||||||
|
|
||||||
|
@ -105,10 +104,10 @@ int main()
|
||||||
|
|
||||||
//NOTE: create surface, canvas and font
|
//NOTE: create surface, canvas and font
|
||||||
|
|
||||||
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_DEFAULT);
|
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
|
||||||
mg_surface_swap_interval(surface, 0);
|
mg_surface_swap_interval(surface, 0);
|
||||||
|
|
||||||
mg_canvas canvas = mg_canvas_create(surface);
|
mg_canvas canvas = mg_canvas_create();
|
||||||
|
|
||||||
const int fontCount = 3;
|
const int fontCount = 3;
|
||||||
int fontIndex = 0;
|
int fontIndex = 0;
|
||||||
|
@ -153,15 +152,19 @@ int main()
|
||||||
f32 startX = 10;
|
f32 startX = 10;
|
||||||
f32 startY = 10 + lineHeights[fontIndex];
|
f32 startY = 10 + lineHeights[fontIndex];
|
||||||
|
|
||||||
|
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_pump_events(0);
|
||||||
mp_event event = {0};
|
mp_event* event = 0;
|
||||||
while(mp_next_event(&event))
|
while((event = mp_next_event(mem_scratch())) != 0)
|
||||||
{
|
{
|
||||||
switch(event.type)
|
mp_input_process_event(&inputState, event);
|
||||||
|
|
||||||
|
switch(event->type)
|
||||||
{
|
{
|
||||||
case MP_EVENT_WINDOW_CLOSE:
|
case MP_EVENT_WINDOW_CLOSE:
|
||||||
{
|
{
|
||||||
|
@ -170,12 +173,12 @@ int main()
|
||||||
|
|
||||||
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;
|
tracked = true;
|
||||||
vec2 mousePos = mp_mouse_position();
|
vec2 mousePos = mp_mouse_position(&inputState);
|
||||||
trackPoint.x = mousePos.x/zoom - startX;
|
trackPoint.x = mousePos.x/zoom - startX;
|
||||||
trackPoint.y = mousePos.y/zoom - startY;
|
trackPoint.y = mousePos.y/zoom - startY;
|
||||||
}
|
}
|
||||||
|
@ -188,11 +191,11 @@ int main()
|
||||||
|
|
||||||
case MP_EVENT_MOUSE_WHEEL:
|
case MP_EVENT_MOUSE_WHEEL:
|
||||||
{
|
{
|
||||||
vec2 mousePos = mp_mouse_position();
|
vec2 mousePos = mp_mouse_position(&inputState);
|
||||||
f32 trackX = mousePos.x/zoom - startX;
|
f32 trackX = mousePos.x/zoom - startX;
|
||||||
f32 trackY = mousePos.y/zoom - startY;
|
f32 trackY = mousePos.y/zoom - startY;
|
||||||
|
|
||||||
zoom *= 1 + event.move.deltaY * 0.01;
|
zoom *= 1 + event->move.deltaY * 0.01;
|
||||||
zoom = Clamp(zoom, 0.2, 10);
|
zoom = Clamp(zoom, 0.2, 10);
|
||||||
|
|
||||||
startX = mousePos.x/zoom - trackX;
|
startX = mousePos.x/zoom - trackX;
|
||||||
|
@ -201,7 +204,7 @@ int main()
|
||||||
|
|
||||||
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)%fontCount;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +217,7 @@ int main()
|
||||||
|
|
||||||
if(tracked)
|
if(tracked)
|
||||||
{
|
{
|
||||||
vec2 mousePos = mp_mouse_position();
|
vec2 mousePos = mp_mouse_position(&inputState);
|
||||||
startX = mousePos.x/zoom - trackPoint.x;
|
startX = mousePos.x/zoom - trackPoint.x;
|
||||||
startY = mousePos.y/zoom - trackPoint.y;
|
startY = mousePos.y/zoom - trackPoint.y;
|
||||||
}
|
}
|
||||||
|
@ -289,8 +292,7 @@ int main()
|
||||||
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
||||||
|
|
||||||
mg_surface_prepare(surface);
|
mg_surface_prepare(surface);
|
||||||
|
mg_flush(surface);
|
||||||
mg_flush();
|
|
||||||
|
|
||||||
f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
@ -306,6 +308,7 @@ int main()
|
||||||
(startPresentTime - startFlushTime)*1000,
|
(startPresentTime - startFlushTime)*1000,
|
||||||
(endFrameTime - startPresentTime)*1000);
|
(endFrameTime - startPresentTime)*1000);
|
||||||
|
|
||||||
|
mp_input_next_frame(&inputState);
|
||||||
mem_arena_clear(mem_scratch());
|
mem_arena_clear(mem_scratch());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
|
|
||||||
#include"milepost.h"
|
#include"milepost.h"
|
||||||
|
|
||||||
#define LOG_SUBSYSTEM "Main"
|
|
||||||
|
|
||||||
#include"tiger.c"
|
#include"tiger.c"
|
||||||
|
|
||||||
mg_font create_font()
|
mg_font create_font()
|
||||||
|
@ -53,8 +51,6 @@ mg_font create_font()
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
LogLevel(LOG_LEVEL_WARNING);
|
|
||||||
|
|
||||||
mp_init();
|
mp_init();
|
||||||
mp_clock_init(); //TODO put that in mp_init()?
|
mp_clock_init(); //TODO put that in mp_init()?
|
||||||
|
|
||||||
|
@ -64,11 +60,11 @@ int main()
|
||||||
mp_rect contentRect = mp_window_get_content_rect(window);
|
mp_rect contentRect = mp_window_get_content_rect(window);
|
||||||
|
|
||||||
//NOTE: create surface
|
//NOTE: create surface
|
||||||
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_DEFAULT);
|
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
|
||||||
mg_surface_swap_interval(surface, 0);
|
mg_surface_swap_interval(surface, 0);
|
||||||
|
|
||||||
//TODO: create canvas
|
//TODO: create canvas
|
||||||
mg_canvas canvas = mg_canvas_create(surface);
|
mg_canvas canvas = mg_canvas_create();
|
||||||
|
|
||||||
if(mg_canvas_is_nil(canvas))
|
if(mg_canvas_is_nil(canvas))
|
||||||
{
|
{
|
||||||
|
@ -92,15 +88,19 @@ int main()
|
||||||
|
|
||||||
f64 frameTime = 0;
|
f64 frameTime = 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_pump_events(0);
|
||||||
mp_event event = {0};
|
mp_event* event = 0;
|
||||||
while(mp_next_event(&event))
|
while((event = mp_next_event(mem_scratch())) != 0)
|
||||||
{
|
{
|
||||||
switch(event.type)
|
mp_input_process_event(&inputState, event);
|
||||||
|
|
||||||
|
switch(event->type)
|
||||||
{
|
{
|
||||||
case MP_EVENT_WINDOW_CLOSE:
|
case MP_EVENT_WINDOW_CLOSE:
|
||||||
{
|
{
|
||||||
|
@ -109,18 +109,18 @@ int main()
|
||||||
|
|
||||||
case MP_EVENT_WINDOW_RESIZE:
|
case MP_EVENT_WINDOW_RESIZE:
|
||||||
{
|
{
|
||||||
mp_rect frame = {0, 0, event.frame.rect.w, event.frame.rect.h};
|
mp_rect frame = {0, 0, event->frame.rect.w, event->frame.rect.h};
|
||||||
mg_surface_set_frame(surface, frame);
|
mg_surface_set_frame(surface, frame);
|
||||||
} break;
|
} 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;
|
tracked = true;
|
||||||
vec2 mousePos = mp_mouse_position();
|
vec2 mousePos = mp_mouse_position(&inputState);
|
||||||
trackPoint.x = (mousePos.x - startX)/zoom;
|
trackPoint.x = (mousePos.x - startX)/zoom;
|
||||||
trackPoint.y = (mousePos.y - startY)/zoom;
|
trackPoint.y = (mousePos.y - startY)/zoom;
|
||||||
}
|
}
|
||||||
|
@ -133,11 +133,11 @@ int main()
|
||||||
|
|
||||||
case MP_EVENT_MOUSE_WHEEL:
|
case MP_EVENT_MOUSE_WHEEL:
|
||||||
{
|
{
|
||||||
vec2 mousePos = mp_mouse_position();
|
vec2 mousePos = mp_mouse_position(&inputState);
|
||||||
f32 pinX = (mousePos.x - startX)/zoom;
|
f32 pinX = (mousePos.x - startX)/zoom;
|
||||||
f32 pinY = (mousePos.y - startY)/zoom;
|
f32 pinY = (mousePos.y - startY)/zoom;
|
||||||
|
|
||||||
zoom *= 1 + event.move.deltaY * 0.01;
|
zoom *= 1 + event->move.deltaY * 0.01;
|
||||||
zoom = Clamp(zoom, 0.5, 5);
|
zoom = Clamp(zoom, 0.5, 5);
|
||||||
|
|
||||||
startX = mousePos.x - pinX*zoom;
|
startX = mousePos.x - pinX*zoom;
|
||||||
|
@ -146,9 +146,9 @@ int main()
|
||||||
|
|
||||||
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:
|
case MP_KEY_SPACE:
|
||||||
singlePath = !singlePath;
|
singlePath = !singlePath;
|
||||||
|
@ -156,7 +156,7 @@ int main()
|
||||||
|
|
||||||
case MP_KEY_UP:
|
case MP_KEY_UP:
|
||||||
{
|
{
|
||||||
if(event.key.mods & MP_KEYMOD_SHIFT)
|
if(event->key.mods & MP_KEYMOD_SHIFT)
|
||||||
{
|
{
|
||||||
singlePathIndex++;
|
singlePathIndex++;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ int main()
|
||||||
|
|
||||||
case MP_KEY_DOWN:
|
case MP_KEY_DOWN:
|
||||||
{
|
{
|
||||||
if(event.key.mods & MP_KEYMOD_SHIFT)
|
if(event->key.mods & MP_KEYMOD_SHIFT)
|
||||||
{
|
{
|
||||||
singlePathIndex--;
|
singlePathIndex--;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ int main()
|
||||||
|
|
||||||
if(tracked)
|
if(tracked)
|
||||||
{
|
{
|
||||||
vec2 mousePos = mp_mouse_position();
|
vec2 mousePos = mp_mouse_position(&inputState);
|
||||||
startX = mousePos.x - trackPoint.x*zoom;
|
startX = mousePos.x - trackPoint.x*zoom;
|
||||||
startY = mousePos.y - trackPoint.y*zoom;
|
startY = mousePos.y - trackPoint.y*zoom;
|
||||||
}
|
}
|
||||||
|
@ -228,9 +228,10 @@ int main()
|
||||||
frameTime,
|
frameTime,
|
||||||
1./frameTime);
|
1./frameTime);
|
||||||
|
|
||||||
mg_flush();
|
mg_flush(surface);
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
|
||||||
|
mp_input_next_frame(&inputState);
|
||||||
mem_arena_clear(mem_scratch());
|
mem_arena_clear(mem_scratch());
|
||||||
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
|
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
|
||||||
}
|
}
|
||||||
|
|
1930
src/graphics.c
1930
src/graphics.c
File diff suppressed because it is too large
Load Diff
|
@ -27,43 +27,51 @@ typedef enum {
|
||||||
|
|
||||||
//NOTE: these macros are used to select which backend to include when building milepost
|
//NOTE: these macros are used to select which backend to include when building milepost
|
||||||
// they can be overridden by passing them to the compiler command line
|
// they can be overridden by passing them to the compiler command line
|
||||||
#if defined(PLATFORM_MACOS)
|
#if PLATFORM_MACOS
|
||||||
#ifndef MG_COMPILE_BACKEND_METAL
|
#ifndef MG_COMPILE_METAL
|
||||||
#define MG_COMPILE_BACKEND_METAL 1
|
#define MG_COMPILE_METAL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_BACKEND_GLES
|
#ifndef MG_COMPILE_GLES
|
||||||
#define MG_COMPILE_BACKEND_GLES 1
|
#define MG_COMPILE_GLES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_BACKEND_CANVAS
|
#ifndef MG_COMPILE_CANVAS
|
||||||
#define MG_COMPILE_BACKEND_CANVAS 1
|
#if !MG_COMPILE_METAL
|
||||||
|
#error "Canvas surface requires a Metal backend on macOS. Make sure you define MG_COMPILE_METAL to 1."
|
||||||
|
#endif
|
||||||
|
#define MG_COMPILE_CANVAS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MG_COMPILE_BACKEND_GL 0
|
#define MG_COMPILE_GL 0
|
||||||
|
|
||||||
#elif defined(PLATFORM_WIN64)
|
#elif PLATFORM_WINDOWS
|
||||||
#ifndef MG_COMPILE_BACKEND_GL
|
#ifndef MG_COMPILE_GL
|
||||||
#define MG_COMPILE_BACKEND_GL 1
|
#define MG_COMPILE_GL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_BACKEND_GLES
|
#ifndef MG_COMPILE_GLES
|
||||||
#define MG_COMPILE_BACKEND_GLES 1
|
#define MG_COMPILE_GLES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_BACKEND_CANVAS
|
#ifndef MG_COMPILE_CANVAS
|
||||||
#define MG_COMPILE_BACKEND_CANVAS 1
|
#if !MG_COMPILE_GL
|
||||||
|
#error "Canvas surface requires an OpenGL backend on Windows. Make sure you define MG_COMPILE_GL to 1."
|
||||||
|
#endif
|
||||||
|
#define MG_COMPILE_CANVAS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(PLATFORM_LINUX)
|
#elif PLATFORM_LINUX
|
||||||
#ifndef MG_COMPILE_BACKEND_GL
|
#ifndef MG_COMPILE_GL
|
||||||
#define MG_COMPILE_BACKEND_GL 1
|
#define MG_COMPILE_GL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_COMPILE_BACKEND_CANVAS
|
#ifndef MG_COMPILE_CANVAS
|
||||||
#define MG_COMPILE_BACKEND_CANVAS 1
|
#if !MG_COMPILE_GL
|
||||||
|
#error "Canvas surface requires an OpenGL backend on Linux. Make sure you define MG_COMPILE_GL to 1."
|
||||||
|
#endif
|
||||||
|
#define MG_COMPILE_CANVAS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//NOTE: these macros are used to select backend-specific APIs to include when using milepost
|
//NOTE: these macros are used to select backend-specific APIs to include when using milepost
|
||||||
|
@ -170,14 +178,11 @@ typedef struct mg_text_extents
|
||||||
MP_API mg_canvas mg_canvas_nil(void);
|
MP_API mg_canvas mg_canvas_nil(void);
|
||||||
MP_API bool mg_canvas_is_nil(mg_canvas canvas);
|
MP_API bool mg_canvas_is_nil(mg_canvas canvas);
|
||||||
|
|
||||||
MP_API mg_canvas mg_canvas_create(mg_surface surface);
|
MP_API mg_canvas mg_canvas_create();
|
||||||
MP_API void mg_canvas_destroy(mg_canvas canvas);
|
MP_API void mg_canvas_destroy(mg_canvas canvas);
|
||||||
|
mg_canvas mg_canvas_set_current(mg_canvas canvas);
|
||||||
|
MP_API void mg_flush(mg_surface surface); //TODO change to mg_canvas_render(mg_surface surface, mg_canvas canvas);
|
||||||
|
|
||||||
MP_API mg_canvas mg_canvas_prepare(mg_canvas canvas);
|
|
||||||
MP_API void mg_flush(void);
|
|
||||||
MP_API void mg_present(void);
|
|
||||||
|
|
||||||
MP_API vec2 mg_canvas_size(void);
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): fonts
|
//NOTE(martin): fonts
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
@ -212,10 +217,10 @@ MP_API mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text);
|
||||||
MP_API mg_image mg_image_nil();
|
MP_API mg_image mg_image_nil();
|
||||||
MP_API bool mg_image_is_nil(mg_image a);
|
MP_API bool mg_image_is_nil(mg_image a);
|
||||||
|
|
||||||
MP_API mg_image mg_image_create(u32 width, u32 height);
|
MP_API mg_image mg_image_create(mg_surface surface, u32 width, u32 height);
|
||||||
MP_API mg_image mg_image_create_from_rgba8(u32 width, u32 height, u8* pixels);
|
MP_API mg_image mg_image_create_from_rgba8(mg_surface surface, u32 width, u32 height, u8* pixels);
|
||||||
MP_API mg_image mg_image_create_from_data(str8 data, bool flip);
|
MP_API mg_image mg_image_create_from_data(mg_surface surface, str8 data, bool flip);
|
||||||
MP_API mg_image mg_image_create_from_file(str8 path, bool flip);
|
MP_API mg_image mg_image_create_from_file(mg_surface surface, str8 path, bool flip);
|
||||||
|
|
||||||
MP_API void mg_image_destroy(mg_image image);
|
MP_API void mg_image_destroy(mg_image image);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ extern "C" {
|
||||||
// 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 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);
|
||||||
|
@ -51,6 +52,9 @@ typedef struct mg_surface_data
|
||||||
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_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);
|
||||||
|
@ -69,6 +73,7 @@ typedef struct mg_image_data
|
||||||
{
|
{
|
||||||
list_elt listElt;
|
list_elt listElt;
|
||||||
u32 generation;
|
u32 generation;
|
||||||
|
mg_surface surface;
|
||||||
vec2 size;
|
vec2 size;
|
||||||
|
|
||||||
} mg_image_data;
|
} mg_image_data;
|
||||||
|
@ -104,7 +109,6 @@ typedef struct mg_vertex_layout
|
||||||
|
|
||||||
} mg_vertex_layout;
|
} mg_vertex_layout;
|
||||||
|
|
||||||
typedef struct mg_canvas_backend mg_canvas_backend;
|
|
||||||
|
|
||||||
typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend);
|
typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend);
|
||||||
typedef void (*mg_canvas_backend_begin_proc)(mg_canvas_backend* backend, mg_color clearColor);
|
typedef void (*mg_canvas_backend_begin_proc)(mg_canvas_backend* backend, mg_color clearColor);
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
|
|
||||||
#include"platform/std_log.c"
|
#include"platform/std_log.c"
|
||||||
|
|
||||||
#if defined(PLATFORM_WIN64)
|
#if PLATFORM_WINDOWS
|
||||||
#include"platform/win32_memory.c"
|
#include"platform/win32_memory.c"
|
||||||
#include"platform/win32_clock.c"
|
#include"platform/win32_clock.c"
|
||||||
//TODO
|
//TODO
|
||||||
#elif defined(PLATFORM_MACOS)
|
#elif PLATFORM_MACOS
|
||||||
#include"platform/unix_memory.c"
|
#include"platform/unix_memory.c"
|
||||||
#include"platform/osx_clock.c"
|
#include"platform/osx_clock.c"
|
||||||
/*
|
/*
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
#include"platform/posix_socket.c"
|
#include"platform/posix_socket.c"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#elif defined(PLATFORM_LINUX)
|
#elif PLATFORM_LINUX
|
||||||
#include"platform/unix_base_memory.c"
|
#include"platform/unix_base_memory.c"
|
||||||
#include"platform/linux_clock.c"
|
#include"platform/linux_clock.c"
|
||||||
/*
|
/*
|
||||||
|
@ -52,24 +52,27 @@
|
||||||
// app/graphics layer
|
// app/graphics layer
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(PLATFORM_WIN64)
|
#if PLATFORM_WINDOWS
|
||||||
#include"win32_app.c"
|
#include"win32_app.c"
|
||||||
#include"graphics.c"
|
#include"graphics.c"
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_GL || MG_COMPILE_BACKEND_GLES
|
#if MG_COMPILE_GL || MG_COMPILE_GLES
|
||||||
#include"gl_loader.c"
|
#include"gl_loader.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_GL
|
#if MG_COMPILE_GL
|
||||||
#include"wgl_surface.c"
|
#include"wgl_surface.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_CANVAS
|
||||||
#include"gl_canvas.c"
|
#include"gl_canvas.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_GLES
|
#if MG_COMPILE_GLES
|
||||||
#include"egl_surface.c"
|
#include"egl_surface.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(PLATFORM_MACOS)
|
#elif PLATFORM_MACOS
|
||||||
//NOTE: macos application layer and graphics backends are defined in milepost.m
|
//NOTE: macos application layer and graphics backends are defined in milepost.m
|
||||||
#else
|
#else
|
||||||
#error "Unsupported platform"
|
#error "Unsupported platform"
|
||||||
|
|
|
@ -10,21 +10,15 @@
|
||||||
#include"osx_app.m"
|
#include"osx_app.m"
|
||||||
#include"graphics.c"
|
#include"graphics.c"
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_METAL
|
#if MG_COMPILE_METAL
|
||||||
#include"mtl_surface.m"
|
#include"mtl_surface.m"
|
||||||
// #include"mtl_canvas.m"
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_CANVAS
|
||||||
#include"mtl_renderer.m"
|
#include"mtl_renderer.m"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_GLES
|
#if MG_COMPILE_GLES
|
||||||
#include"gl_loader.c"
|
#include"gl_loader.c"
|
||||||
#include"egl_surface.c"
|
#include"egl_surface.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#include"osx_gles_surface.m"
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
*/
|
|
||||||
//#include"osx_surface_client.m"
|
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
#include"platform.h"
|
#include"platform.h"
|
||||||
#include"ringbuffer.h"
|
#include"ringbuffer.h"
|
||||||
|
|
||||||
#if defined(PLATFORM_WIN64) || defined(PLATFORM_WIN32)
|
#if PLATFORM_WINDOWS
|
||||||
#include"win32_app.h"
|
#include"win32_app.h"
|
||||||
#elif defined(PLATFORM_MACOS)
|
#elif PLATFORM_MACOS
|
||||||
#include"osx_app.h"
|
#include"osx_app.h"
|
||||||
#else
|
#else
|
||||||
#error "platform not supported yet"
|
#error "platform not supported yet"
|
||||||
|
|
|
@ -23,7 +23,7 @@ const int MG_MTL_INPUT_BUFFERS_COUNT = 3,
|
||||||
typedef struct mg_mtl_canvas_backend
|
typedef struct mg_mtl_canvas_backend
|
||||||
{
|
{
|
||||||
mg_canvas_backend interface;
|
mg_canvas_backend interface;
|
||||||
mg_surface surface;
|
mg_mtl_surface* surface;
|
||||||
|
|
||||||
id<MTLComputePipelineState> pathPipeline;
|
id<MTLComputePipelineState> pathPipeline;
|
||||||
id<MTLComputePipelineState> segmentPipeline;
|
id<MTLComputePipelineState> segmentPipeline;
|
||||||
|
@ -64,15 +64,6 @@ typedef struct mg_mtl_image_data
|
||||||
id<MTLTexture> texture;
|
id<MTLTexture> texture;
|
||||||
} mg_mtl_image_data;
|
} mg_mtl_image_data;
|
||||||
|
|
||||||
|
|
||||||
static void mg_update_path_extents(vec4* extents, vec2 p)
|
|
||||||
{
|
|
||||||
extents->x = minimum(extents->x, p.x);
|
|
||||||
extents->y = minimum(extents->y, p.y);
|
|
||||||
extents->z = maximum(extents->z, p.x);
|
|
||||||
extents->w = maximum(extents->w, p.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_mtl_print_log(int bufferIndex, id<MTLBuffer> logBuffer, id<MTLBuffer> logOffsetBuffer)
|
void mg_mtl_print_log(int bufferIndex, id<MTLBuffer> logBuffer, id<MTLBuffer> logOffsetBuffer)
|
||||||
{
|
{
|
||||||
char* log = [logBuffer contents];
|
char* log = [logBuffer contents];
|
||||||
|
@ -106,6 +97,14 @@ typedef struct mg_mtl_encoding_context
|
||||||
|
|
||||||
} mg_mtl_encoding_context;
|
} mg_mtl_encoding_context;
|
||||||
|
|
||||||
|
static void mg_update_path_extents(vec4* extents, vec2 p)
|
||||||
|
{
|
||||||
|
extents->x = minimum(extents->x, p.x);
|
||||||
|
extents->y = minimum(extents->y, p.y);
|
||||||
|
extents->z = maximum(extents->z, p.x);
|
||||||
|
extents->w = maximum(extents->w, p.y);
|
||||||
|
}
|
||||||
|
|
||||||
void mg_mtl_canvas_encode_element(mg_mtl_encoding_context* context, mg_path_elt_type kind, vec2* p)
|
void mg_mtl_canvas_encode_element(mg_mtl_encoding_context* context, mg_path_elt_type kind, vec2* p)
|
||||||
{
|
{
|
||||||
mg_mtl_path_elt* mtlElt = &context->elementBufferData[context->mtlEltCount];
|
mg_mtl_path_elt* mtlElt = &context->elementBufferData[context->mtlEltCount];
|
||||||
|
@ -147,6 +146,198 @@ void mg_mtl_canvas_encode_element(mg_mtl_encoding_context* context, mg_path_elt_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool mg_intersect_hull_legs(vec2 p0, vec2 p1, vec2 p2, vec2 p3, vec2* intersection)
|
||||||
|
{
|
||||||
|
/*NOTE: check intersection of lines (p0-p1) and (p2-p3)
|
||||||
|
|
||||||
|
P = p0 + u(p1-p0)
|
||||||
|
P = p2 + w(p3-p2)
|
||||||
|
*/
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
f32 den = (p0.x - p1.x)*(p2.y - p3.y) - (p0.y - p1.y)*(p2.x - p3.x);
|
||||||
|
if(fabs(den) > 0.0001)
|
||||||
|
{
|
||||||
|
f32 u = ((p0.x - p2.x)*(p2.y - p3.y) - (p0.y - p2.y)*(p2.x - p3.x))/den;
|
||||||
|
f32 w = ((p0.x - p2.x)*(p0.y - p1.y) - (p0.y - p2.y)*(p0.x - p1.x))/den;
|
||||||
|
|
||||||
|
intersection->x = p0.x + u*(p1.x - p0.x);
|
||||||
|
intersection->y = p0.y + u*(p1.y - p0.y);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
return(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_offset_hull(int count, vec2* p, vec2* result, f32 offset)
|
||||||
|
{
|
||||||
|
//NOTE: we should have no more than two coincident points here. This means the leg between
|
||||||
|
// those two points can't be offset, but we can set a double point at the start of first leg,
|
||||||
|
// end of first leg, or we can join the first and last leg to create a missing middle one
|
||||||
|
|
||||||
|
vec2 legs[3][2] = {0};
|
||||||
|
bool valid[3] = {0};
|
||||||
|
|
||||||
|
for(int i=0; i<count-1; i++)
|
||||||
|
{
|
||||||
|
vec2 n = {p[i].y - p[i+1].y,
|
||||||
|
p[i+1].x - p[i].x};
|
||||||
|
|
||||||
|
f32 norm = sqrt(n.x*n.x + n.y*n.y);
|
||||||
|
if(norm >= 1e-6)
|
||||||
|
{
|
||||||
|
n = vec2_mul(offset/norm, n);
|
||||||
|
legs[i][0] = vec2_add(p[i], n);
|
||||||
|
legs[i][1] = vec2_add(p[i+1], n);
|
||||||
|
valid[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//NOTE: now we find intersections
|
||||||
|
|
||||||
|
// first point is either the start of the first or second leg
|
||||||
|
if(valid[0])
|
||||||
|
{
|
||||||
|
result[0] = legs[0][0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(valid[1]);
|
||||||
|
result[0] = legs[1][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=1; i<count-1; i++)
|
||||||
|
{
|
||||||
|
//NOTE: we're computing the control point i, at the end of leg (i-1)
|
||||||
|
|
||||||
|
if(!valid[i-1])
|
||||||
|
{
|
||||||
|
ASSERT(valid[i]);
|
||||||
|
result[i] = legs[i][0];
|
||||||
|
}
|
||||||
|
else if(!valid[i])
|
||||||
|
{
|
||||||
|
ASSERT(valid[i-1]);
|
||||||
|
result[i] = legs[i-1][0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!mg_intersect_hull_legs(legs[i-1][0], legs[i-1][1], legs[i][0], legs[i][1], &result[i]))
|
||||||
|
{
|
||||||
|
// legs don't intersect.
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(valid[count-2])
|
||||||
|
{
|
||||||
|
result[count-1] = legs[count-2][1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(valid[count-3]);
|
||||||
|
result[count-1] = legs[count-3][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 mg_quadratic_get_point(vec2 p[3], f32 t)
|
||||||
|
{
|
||||||
|
vec2 r;
|
||||||
|
|
||||||
|
f32 oneMt = 1-t;
|
||||||
|
f32 oneMt2 = Square(oneMt);
|
||||||
|
f32 t2 = Square(t);
|
||||||
|
|
||||||
|
r.x = oneMt2*p[0].x + 2*oneMt*t*p[1].x + t2*p[2].x;
|
||||||
|
r.y = oneMt2*p[0].y + 2*oneMt*t*p[1].y + t2*p[2].y;
|
||||||
|
|
||||||
|
return(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_quadratic_split(vec2 p[3], f32 t, vec2 outLeft[3], vec2 outRight[3])
|
||||||
|
{
|
||||||
|
//DEBUG
|
||||||
|
__mgCurrentCanvas->splitCount++;
|
||||||
|
|
||||||
|
//NOTE(martin): split bezier curve p at parameter t, using De Casteljau's algorithm
|
||||||
|
// the q_n are the points along the hull's segments at parameter t
|
||||||
|
// s is the split point.
|
||||||
|
|
||||||
|
f32 oneMt = 1-t;
|
||||||
|
|
||||||
|
vec2 q0 = {oneMt*p[0].x + t*p[1].x,
|
||||||
|
oneMt*p[0].y + t*p[1].y};
|
||||||
|
|
||||||
|
vec2 q1 = {oneMt*p[1].x + t*p[2].x,
|
||||||
|
oneMt*p[1].y + t*p[2].y};
|
||||||
|
|
||||||
|
vec2 s = {oneMt*q0.x + t*q1.x,
|
||||||
|
oneMt*q0.y + t*q1.y};
|
||||||
|
|
||||||
|
outLeft[0] = p[0];
|
||||||
|
outLeft[1] = q0;
|
||||||
|
outLeft[2] = s;
|
||||||
|
|
||||||
|
outRight[0] = s;
|
||||||
|
outRight[1] = q1;
|
||||||
|
outRight[2] = p[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 mg_cubic_get_point(vec2 p[4], f32 t)
|
||||||
|
{
|
||||||
|
vec2 r;
|
||||||
|
|
||||||
|
f32 oneMt = 1-t;
|
||||||
|
f32 oneMt2 = Square(oneMt);
|
||||||
|
f32 oneMt3 = oneMt2*oneMt;
|
||||||
|
f32 t2 = Square(t);
|
||||||
|
f32 t3 = t2*t;
|
||||||
|
|
||||||
|
r.x = oneMt3*p[0].x + 3*oneMt2*t*p[1].x + 3*oneMt*t2*p[2].x + t3*p[3].x;
|
||||||
|
r.y = oneMt3*p[0].y + 3*oneMt2*t*p[1].y + 3*oneMt*t2*p[2].y + t3*p[3].y;
|
||||||
|
|
||||||
|
return(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_cubic_split(vec2 p[4], f32 t, vec2 outLeft[4], vec2 outRight[4])
|
||||||
|
{
|
||||||
|
//NOTE(martin): split bezier curve p at parameter t, using De Casteljau's algorithm
|
||||||
|
// the q_n are the points along the hull's segments at parameter t
|
||||||
|
// the r_n are the points along the (q_n, q_n+1) segments at parameter t
|
||||||
|
// s is the split point.
|
||||||
|
|
||||||
|
vec2 q0 = {(1-t)*p[0].x + t*p[1].x,
|
||||||
|
(1-t)*p[0].y + t*p[1].y};
|
||||||
|
|
||||||
|
vec2 q1 = {(1-t)*p[1].x + t*p[2].x,
|
||||||
|
(1-t)*p[1].y + t*p[2].y};
|
||||||
|
|
||||||
|
vec2 q2 = {(1-t)*p[2].x + t*p[3].x,
|
||||||
|
(1-t)*p[2].y + t*p[3].y};
|
||||||
|
|
||||||
|
vec2 r0 = {(1-t)*q0.x + t*q1.x,
|
||||||
|
(1-t)*q0.y + t*q1.y};
|
||||||
|
|
||||||
|
vec2 r1 = {(1-t)*q1.x + t*q2.x,
|
||||||
|
(1-t)*q1.y + t*q2.y};
|
||||||
|
|
||||||
|
vec2 s = {(1-t)*r0.x + t*r1.x,
|
||||||
|
(1-t)*r0.y + t*r1.y};;
|
||||||
|
|
||||||
|
outLeft[0] = p[0];
|
||||||
|
outLeft[1] = q0;
|
||||||
|
outLeft[2] = r0;
|
||||||
|
outLeft[3] = s;
|
||||||
|
|
||||||
|
outRight[0] = s;
|
||||||
|
outRight[1] = r1;
|
||||||
|
outRight[2] = q2;
|
||||||
|
outRight[3] = p[3];
|
||||||
|
}
|
||||||
|
|
||||||
void mg_mtl_render_stroke_line(mg_mtl_encoding_context* context, vec2* p)
|
void mg_mtl_render_stroke_line(mg_mtl_encoding_context* context, vec2* p)
|
||||||
{
|
{
|
||||||
f32 width = context->primitive->attributes.width;
|
f32 width = context->primitive->attributes.width;
|
||||||
|
@ -770,9 +961,6 @@ void mg_mtl_render_batch(mg_mtl_canvas_backend* backend,
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_mtl_canvas_resize(mg_mtl_canvas_backend* backend, vec2 size)
|
void mg_mtl_canvas_resize(mg_mtl_canvas_backend* backend, vec2 size)
|
||||||
{
|
|
||||||
mg_mtl_surface* surface = (mg_mtl_surface*)mg_surface_data_from_handle(backend->surface);
|
|
||||||
if(surface)
|
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
@ -785,7 +973,7 @@ void mg_mtl_canvas_resize(mg_mtl_canvas_backend* backend, vec2 size)
|
||||||
int nTilesX = (int)(size.x + tileSize - 1)/tileSize;
|
int nTilesX = (int)(size.x + tileSize - 1)/tileSize;
|
||||||
int nTilesY = (int)(size.y + tileSize - 1)/tileSize;
|
int nTilesY = (int)(size.y + tileSize - 1)/tileSize;
|
||||||
MTLResourceOptions bufferOptions = MTLResourceStorageModePrivate;
|
MTLResourceOptions bufferOptions = MTLResourceStorageModePrivate;
|
||||||
backend->screenTilesBuffer = [surface->device newBufferWithLength: nTilesX*nTilesY*sizeof(int)
|
backend->screenTilesBuffer = [backend->surface->device newBufferWithLength: nTilesX*nTilesY*sizeof(int)
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
if(backend->outTexture)
|
if(backend->outTexture)
|
||||||
|
@ -801,12 +989,11 @@ void mg_mtl_canvas_resize(mg_mtl_canvas_backend* backend, vec2 size)
|
||||||
texDesc.width = size.x;
|
texDesc.width = size.x;
|
||||||
texDesc.height = size.y;
|
texDesc.height = size.y;
|
||||||
|
|
||||||
backend->outTexture = [surface->device newTextureWithDescriptor:texDesc];
|
backend->outTexture = [backend->surface->device newTextureWithDescriptor:texDesc];
|
||||||
|
|
||||||
backend->frameSize = size;
|
backend->frameSize = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void mg_mtl_canvas_render(mg_canvas_backend* interface,
|
void mg_mtl_canvas_render(mg_canvas_backend* interface,
|
||||||
mg_color clearColor,
|
mg_color clearColor,
|
||||||
|
@ -829,10 +1016,10 @@ void mg_mtl_canvas_render(mg_canvas_backend* interface,
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//NOTE: prepare rendering
|
//NOTE: prepare rendering
|
||||||
mg_mtl_surface* surface = (mg_mtl_surface*)mg_surface_data_from_handle(backend->surface);
|
mg_mtl_surface* surface = backend->surface;
|
||||||
ASSERT(surface && surface->interface.api == MG_METAL);
|
|
||||||
|
mp_rect frame = surface->interface.getFrame((mg_surface_data*)surface);
|
||||||
|
|
||||||
mp_rect frame = mg_surface_get_frame(backend->surface);
|
|
||||||
f32 scale = surface->mtlLayer.contentsScale;
|
f32 scale = surface->mtlLayer.contentsScale;
|
||||||
vec2 viewportSize = {frame.w * scale, frame.h * scale};
|
vec2 viewportSize = {frame.w * scale, frame.h * scale};
|
||||||
int tileSize = MG_MTL_TILE_SIZE;
|
int tileSize = MG_MTL_TILE_SIZE;
|
||||||
|
@ -1068,12 +1255,10 @@ mg_image_data* mg_mtl_canvas_image_create(mg_canvas_backend* interface, vec2 siz
|
||||||
{
|
{
|
||||||
mg_mtl_image_data* image = 0;
|
mg_mtl_image_data* image = 0;
|
||||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||||
mg_mtl_surface* surface = (mg_mtl_surface*)mg_surface_data_from_handle(backend->surface);
|
mg_mtl_surface* surface = backend->surface;
|
||||||
|
|
||||||
if(surface && surface->interface.api == MG_METAL)
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
@autoreleasepool{
|
|
||||||
|
|
||||||
image = malloc_type(mg_mtl_image_data);
|
image = malloc_type(mg_mtl_image_data);
|
||||||
if(image)
|
if(image)
|
||||||
{
|
{
|
||||||
|
@ -1098,7 +1283,6 @@ mg_image_data* mg_mtl_canvas_image_create(mg_canvas_backend* interface, vec2 siz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return((mg_image_data*)image);
|
return((mg_image_data*)image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,15 +1313,10 @@ const u32 MG_MTL_PATH_BUFFER_SIZE = (4<<20)*sizeof(mg_mtl_path),
|
||||||
MG_MTL_TILE_QUEUE_BUFFER_SIZE = (4<<20)*sizeof(mg_mtl_tile_queue),
|
MG_MTL_TILE_QUEUE_BUFFER_SIZE = (4<<20)*sizeof(mg_mtl_tile_queue),
|
||||||
MG_MTL_TILE_OP_BUFFER_SIZE = (4<<20)*sizeof(mg_mtl_tile_op);
|
MG_MTL_TILE_OP_BUFFER_SIZE = (4<<20)*sizeof(mg_mtl_tile_op);
|
||||||
|
|
||||||
mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
mg_canvas_backend* mtl_canvas_backend_create(mg_mtl_surface* surface)
|
||||||
{
|
{
|
||||||
mg_mtl_canvas_backend* backend = 0;
|
mg_mtl_canvas_backend* backend = 0;
|
||||||
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->api == MG_METAL)
|
|
||||||
{
|
|
||||||
mg_mtl_surface* metalSurface = (mg_mtl_surface*)surfaceData;
|
|
||||||
|
|
||||||
backend = malloc_type(mg_mtl_canvas_backend);
|
backend = malloc_type(mg_mtl_canvas_backend);
|
||||||
memset(backend, 0, sizeof(mg_mtl_canvas_backend));
|
memset(backend, 0, sizeof(mg_mtl_canvas_backend));
|
||||||
|
|
||||||
|
@ -1156,7 +1335,7 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
||||||
str8 shaderPath = mp_app_get_resource_path(mem_scratch(), "mtl_renderer.metallib");
|
str8 shaderPath = mp_app_get_resource_path(mem_scratch(), "mtl_renderer.metallib");
|
||||||
NSString* metalFileName = [[NSString alloc] initWithBytes: shaderPath.ptr length:shaderPath.len encoding: NSUTF8StringEncoding];
|
NSString* metalFileName = [[NSString alloc] initWithBytes: shaderPath.ptr length:shaderPath.len encoding: NSUTF8StringEncoding];
|
||||||
NSError* err = 0;
|
NSError* err = 0;
|
||||||
id<MTLLibrary> library = [metalSurface->device newLibraryWithFile: metalFileName error:&err];
|
id<MTLLibrary> library = [surface->device newLibraryWithFile: metalFileName error:&err];
|
||||||
if(err != nil)
|
if(err != nil)
|
||||||
{
|
{
|
||||||
const char* errStr = [[err localizedDescription] UTF8String];
|
const char* errStr = [[err localizedDescription] UTF8String];
|
||||||
|
@ -1174,26 +1353,26 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
||||||
//NOTE: create pipelines
|
//NOTE: create pipelines
|
||||||
NSError* error = NULL;
|
NSError* error = NULL;
|
||||||
|
|
||||||
backend->pathPipeline = [metalSurface->device newComputePipelineStateWithFunction: pathFunction
|
backend->pathPipeline = [surface->device newComputePipelineStateWithFunction: pathFunction
|
||||||
error:&error];
|
error:&error];
|
||||||
|
|
||||||
backend->segmentPipeline = [metalSurface->device newComputePipelineStateWithFunction: segmentFunction
|
backend->segmentPipeline = [surface->device newComputePipelineStateWithFunction: segmentFunction
|
||||||
error:&error];
|
error:&error];
|
||||||
|
|
||||||
backend->backpropPipeline = [metalSurface->device newComputePipelineStateWithFunction: backpropFunction
|
backend->backpropPipeline = [surface->device newComputePipelineStateWithFunction: backpropFunction
|
||||||
error:&error];
|
error:&error];
|
||||||
|
|
||||||
backend->mergePipeline = [metalSurface->device newComputePipelineStateWithFunction: mergeFunction
|
backend->mergePipeline = [surface->device newComputePipelineStateWithFunction: mergeFunction
|
||||||
error:&error];
|
error:&error];
|
||||||
|
|
||||||
backend->rasterPipeline = [metalSurface->device newComputePipelineStateWithFunction: rasterFunction
|
backend->rasterPipeline = [surface->device newComputePipelineStateWithFunction: rasterFunction
|
||||||
error:&error];
|
error:&error];
|
||||||
|
|
||||||
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||||
pipelineStateDescriptor.label = @"blit pipeline";
|
pipelineStateDescriptor.label = @"blit pipeline";
|
||||||
pipelineStateDescriptor.vertexFunction = vertexFunction;
|
pipelineStateDescriptor.vertexFunction = vertexFunction;
|
||||||
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
|
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
|
||||||
pipelineStateDescriptor.colorAttachments[0].pixelFormat = metalSurface->mtlLayer.pixelFormat;
|
pipelineStateDescriptor.colorAttachments[0].pixelFormat = surface->mtlLayer.pixelFormat;
|
||||||
pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES;
|
pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES;
|
||||||
pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||||
pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
|
pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||||
|
@ -1202,11 +1381,11 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
||||||
pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||||
pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||||
|
|
||||||
backend->blitPipeline = [metalSurface->device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err];
|
backend->blitPipeline = [surface->device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err];
|
||||||
|
|
||||||
//NOTE: create textures
|
//NOTE: create textures
|
||||||
mp_rect frame = mg_surface_get_frame(surface);
|
mp_rect frame = surface->interface.getFrame((mg_surface_data*)surface);
|
||||||
f32 scale = metalSurface->mtlLayer.contentsScale;
|
f32 scale = surface->mtlLayer.contentsScale;
|
||||||
|
|
||||||
backend->frameSize = (vec2){frame.w*scale, frame.h*scale};
|
backend->frameSize = (vec2){frame.w*scale, frame.h*scale};
|
||||||
|
|
||||||
|
@ -1218,7 +1397,7 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
||||||
texDesc.width = backend->frameSize.x;
|
texDesc.width = backend->frameSize.x;
|
||||||
texDesc.height = backend->frameSize.y;
|
texDesc.height = backend->frameSize.y;
|
||||||
|
|
||||||
backend->outTexture = [metalSurface->device newTextureWithDescriptor:texDesc];
|
backend->outTexture = [surface->device newTextureWithDescriptor:texDesc];
|
||||||
|
|
||||||
//NOTE: create buffers
|
//NOTE: create buffers
|
||||||
|
|
||||||
|
@ -1230,52 +1409,70 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
||||||
|
|
||||||
for(int i=0; i<MG_MTL_INPUT_BUFFERS_COUNT; i++)
|
for(int i=0; i<MG_MTL_INPUT_BUFFERS_COUNT; i++)
|
||||||
{
|
{
|
||||||
backend->pathBuffer[i] = [metalSurface->device newBufferWithLength: MG_MTL_PATH_BUFFER_SIZE
|
backend->pathBuffer[i] = [surface->device newBufferWithLength: MG_MTL_PATH_BUFFER_SIZE
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
backend->elementBuffer[i] = [metalSurface->device newBufferWithLength: MG_MTL_ELEMENT_BUFFER_SIZE
|
backend->elementBuffer[i] = [surface->device newBufferWithLength: MG_MTL_ELEMENT_BUFFER_SIZE
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferOptions = MTLResourceStorageModePrivate;
|
bufferOptions = MTLResourceStorageModePrivate;
|
||||||
backend->segmentBuffer = [metalSurface->device newBufferWithLength: MG_MTL_SEGMENT_BUFFER_SIZE
|
backend->segmentBuffer = [surface->device newBufferWithLength: MG_MTL_SEGMENT_BUFFER_SIZE
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
backend->segmentCountBuffer = [metalSurface->device newBufferWithLength: sizeof(int)
|
backend->segmentCountBuffer = [surface->device newBufferWithLength: sizeof(int)
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
|
backend->pathQueueBuffer = [surface->device newBufferWithLength: MG_MTL_PATH_QUEUE_BUFFER_SIZE
|
||||||
backend->pathQueueBuffer = [metalSurface->device newBufferWithLength: MG_MTL_PATH_QUEUE_BUFFER_SIZE
|
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
backend->tileQueueBuffer = [metalSurface->device newBufferWithLength: MG_MTL_TILE_QUEUE_BUFFER_SIZE
|
backend->tileQueueBuffer = [surface->device newBufferWithLength: MG_MTL_TILE_QUEUE_BUFFER_SIZE
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
backend->tileQueueCountBuffer = [metalSurface->device newBufferWithLength: sizeof(int)
|
backend->tileQueueCountBuffer = [surface->device newBufferWithLength: sizeof(int)
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
backend->tileOpBuffer = [metalSurface->device newBufferWithLength: MG_MTL_TILE_OP_BUFFER_SIZE
|
backend->tileOpBuffer = [surface->device newBufferWithLength: MG_MTL_TILE_OP_BUFFER_SIZE
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
backend->tileOpCountBuffer = [metalSurface->device newBufferWithLength: sizeof(int)
|
backend->tileOpCountBuffer = [surface->device newBufferWithLength: sizeof(int)
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
int tileSize = MG_MTL_TILE_SIZE;
|
int tileSize = MG_MTL_TILE_SIZE;
|
||||||
int nTilesX = (int)(frame.w * scale + tileSize - 1)/tileSize;
|
int nTilesX = (int)(frame.w * scale + tileSize - 1)/tileSize;
|
||||||
int nTilesY = (int)(frame.h * scale + tileSize - 1)/tileSize;
|
int nTilesY = (int)(frame.h * scale + tileSize - 1)/tileSize;
|
||||||
backend->screenTilesBuffer = [metalSurface->device newBufferWithLength: nTilesX*nTilesY*sizeof(int)
|
backend->screenTilesBuffer = [surface->device newBufferWithLength: nTilesX*nTilesY*sizeof(int)
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
bufferOptions = MTLResourceStorageModeShared;
|
bufferOptions = MTLResourceStorageModeShared;
|
||||||
for(int i=0; i<MG_MTL_INPUT_BUFFERS_COUNT; i++)
|
for(int i=0; i<MG_MTL_INPUT_BUFFERS_COUNT; i++)
|
||||||
{
|
{
|
||||||
backend->logBuffer[i] = [metalSurface->device newBufferWithLength: 1<<20
|
backend->logBuffer[i] = [surface->device newBufferWithLength: 1<<20
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
|
|
||||||
backend->logOffsetBuffer[i] = [metalSurface->device newBufferWithLength: sizeof(int)
|
backend->logOffsetBuffer[i] = [surface->device newBufferWithLength: sizeof(int)
|
||||||
options: bufferOptions];
|
options: bufferOptions];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return((mg_canvas_backend*)backend);
|
return((mg_canvas_backend*)backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mg_surface_data* mtl_canvas_surface_create_for_window(mp_window window)
|
||||||
|
{
|
||||||
|
mg_mtl_surface* surface = (mg_mtl_surface*)mg_mtl_surface_create_for_window(window);
|
||||||
|
|
||||||
|
if(surface)
|
||||||
|
{
|
||||||
|
surface->interface.backend = mtl_canvas_backend_create(surface);
|
||||||
|
if(surface->interface.backend)
|
||||||
|
{
|
||||||
|
surface->interface.api = MG_CANVAS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
surface->interface.destroy((mg_surface_data*)surface);
|
||||||
|
surface = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return((mg_surface_data*)surface);
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
// OS identification
|
// OS identification
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
#define PLATFORM_WIN64 1
|
#define PLATFORM_WINDOWS 1
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#error "Unsupported OS (32bit only version of Windows)"
|
#error "Unsupported OS (32bit only version of Windows)"
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include<stdio.h>
|
#include<stdio.h>
|
||||||
#include"platform_log.c"
|
#include"platform_log.c"
|
||||||
|
|
||||||
#if PLATFORM_WIN32 || PLATFORM_WIN64
|
#if PLATFORM_WINDOWS
|
||||||
#include<io.h>
|
#include<io.h>
|
||||||
#define isatty _isatty
|
#define isatty _isatty
|
||||||
#define fileno _fileno
|
#define fileno _fileno
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
2
src/ui.c
2
src/ui.c
|
@ -2293,7 +2293,7 @@ typedef struct ui_edit_command
|
||||||
|
|
||||||
} ui_edit_command;
|
} ui_edit_command;
|
||||||
|
|
||||||
#if PLATFORM_WIN64
|
#if PLATFORM_WINDOWS
|
||||||
#define OS_COPY_PASTE_MOD MP_KEYMOD_CTRL
|
#define OS_COPY_PASTE_MOD MP_KEYMOD_CTRL
|
||||||
#elif PLATFORM_MACOS
|
#elif PLATFORM_MACOS
|
||||||
#define OS_COPY_PASTE_MOD MP_KEYMOD_CMD
|
#define OS_COPY_PASTE_MOD MP_KEYMOD_CMD
|
||||||
|
|
Loading…
Reference in New Issue