[surface/canvas cleanup]
- Make build-time and runtime backend selection a bit easier - Reorganized backend-specific files with slightly more coherent naming scheme
This commit is contained in:
parent
f54f639db5
commit
80ea8db687
|
@ -6,5 +6,5 @@ set glsl_shaders=src\glsl_shaders\common.glsl src\glsl_shaders\blit_vertex.glsl
|
|||
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
|
||||
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
|
||||
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
|
||||
lib bin/milepost.obj /OUT:bin/milepost.lib
|
||||
|
|
164
build.sh
164
build.sh
|
@ -1,82 +1,82 @@
|
|||
#!/bin/bash
|
||||
|
||||
DEBUG_FLAGS="-g -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
#DEBUG_FLAGS="-O3"
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# set target
|
||||
#--------------------------------------------------------------
|
||||
|
||||
target="$1"
|
||||
if [ -z $target ] ; then
|
||||
target='lib'
|
||||
fi
|
||||
|
||||
shaderFlagParam="$2"
|
||||
#--------------------------------------------------------------
|
||||
# Detect OS and set environment variables accordingly
|
||||
#--------------------------------------------------------------
|
||||
OS=$(uname -s)
|
||||
|
||||
if [ $OS = "Darwin" ] ; then
|
||||
#echo "Target '$target' for macOS"
|
||||
CC=clang
|
||||
CXX=clang++
|
||||
DYLIB_SUFFIX='dylib'
|
||||
SYS_LIBS=''
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DMG_IMPLEMENTS_BACKEND_METAL -DMG_IMPLEMENTS_BACKEND_GLES -maes"
|
||||
CFLAGS="-std=c11"
|
||||
|
||||
elif [ $OS = "Linux" ] ; then
|
||||
echo "Error: Linux is not supported yet"
|
||||
exit -1
|
||||
else
|
||||
echo "Error: Unsupported OS $OS"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Set paths
|
||||
#--------------------------------------------------------------
|
||||
BINDIR="./bin"
|
||||
SRCDIR="./src"
|
||||
EXTDIR="./ext"
|
||||
RESDIR="./resources"
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$EXTDIR/angle_headers"
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Build
|
||||
#--------------------------------------------------------------
|
||||
|
||||
if [ ! \( -e bin \) ] ; then
|
||||
mkdir ./bin
|
||||
fi
|
||||
|
||||
if [ $target = 'lib' ] ; then
|
||||
|
||||
# compile metal shader
|
||||
xcrun -sdk macosx metal $shaderFlagParam -c -o $BINDIR/metal_shader.air $SRCDIR/metal_shader.metal
|
||||
xcrun -sdk macosx metallib -o $RESDIR/metal_shader.metallib $BINDIR/metal_shader.air
|
||||
|
||||
# compile milepost. We use one compilation unit for all C code, and one compilation
|
||||
# unit for all ObjectiveC code
|
||||
$CC $DEBUG_FLAGS -c -o $BINDIR/milepost_c.o $CFLAGS $FLAGS $INCLUDES $SRCDIR/milepost.c
|
||||
$CC $DEBUG_FLAGS -c -o $BINDIR/milepost_objc.o $FLAGS $INCLUDES $SRCDIR/milepost.m
|
||||
|
||||
# build the static library
|
||||
libtool -static -o $BINDIR/libmilepost.a $BINDIR/milepost_c.o $BINDIR/milepost_objc.o
|
||||
|
||||
else
|
||||
# additional targets
|
||||
if [ $target = 'test' ] ; then
|
||||
pushd examples/test_app
|
||||
./build.sh
|
||||
popd
|
||||
|
||||
elif [ $target = 'clean' ] ; then
|
||||
rm -r ./bin
|
||||
else
|
||||
echo "unrecognized target $target"
|
||||
exit -1
|
||||
fi
|
||||
fi
|
||||
#!/bin/bash
|
||||
|
||||
DEBUG_FLAGS="-g -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||
#DEBUG_FLAGS="-O3"
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# set target
|
||||
#--------------------------------------------------------------
|
||||
|
||||
target="$1"
|
||||
if [ -z $target ] ; then
|
||||
target='lib'
|
||||
fi
|
||||
|
||||
shaderFlagParam="$2"
|
||||
#--------------------------------------------------------------
|
||||
# Detect OS and set environment variables accordingly
|
||||
#--------------------------------------------------------------
|
||||
OS=$(uname -s)
|
||||
|
||||
if [ $OS = "Darwin" ] ; then
|
||||
#echo "Target '$target' for macOS"
|
||||
CC=clang
|
||||
CXX=clang++
|
||||
DYLIB_SUFFIX='dylib'
|
||||
SYS_LIBS=''
|
||||
FLAGS="-mmacos-version-min=10.15.4 -maes"
|
||||
CFLAGS="-std=c11"
|
||||
|
||||
elif [ $OS = "Linux" ] ; then
|
||||
echo "Error: Linux is not supported yet"
|
||||
exit -1
|
||||
else
|
||||
echo "Error: Unsupported OS $OS"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Set paths
|
||||
#--------------------------------------------------------------
|
||||
BINDIR="./bin"
|
||||
SRCDIR="./src"
|
||||
EXTDIR="./ext"
|
||||
RESDIR="./resources"
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$EXTDIR/angle_headers"
|
||||
|
||||
#--------------------------------------------------------------
|
||||
# Build
|
||||
#--------------------------------------------------------------
|
||||
|
||||
if [ ! \( -e bin \) ] ; then
|
||||
mkdir ./bin
|
||||
fi
|
||||
|
||||
if [ $target = 'lib' ] ; then
|
||||
|
||||
# compile metal shader
|
||||
xcrun -sdk macosx metal $shaderFlagParam -c -o $BINDIR/metal_shader.air $SRCDIR/metal_shader.metal
|
||||
xcrun -sdk macosx metallib -o $RESDIR/metal_shader.metallib $BINDIR/metal_shader.air
|
||||
|
||||
# compile milepost. We use one compilation unit for all C code, and one compilation
|
||||
# unit for all ObjectiveC code
|
||||
$CC $DEBUG_FLAGS -c -o $BINDIR/milepost_c.o $CFLAGS $FLAGS $INCLUDES $SRCDIR/milepost.c
|
||||
$CC $DEBUG_FLAGS -c -o $BINDIR/milepost_objc.o $FLAGS $INCLUDES $SRCDIR/milepost.m
|
||||
|
||||
# build the static library
|
||||
libtool -static -o $BINDIR/libmilepost.a $BINDIR/milepost_c.o $BINDIR/milepost_objc.o
|
||||
|
||||
else
|
||||
# additional targets
|
||||
if [ $target = 'test' ] ; then
|
||||
pushd examples/test_app
|
||||
./build.sh
|
||||
popd
|
||||
|
||||
elif [ $target = 'clean' ] ; then
|
||||
rm -r ./bin
|
||||
else
|
||||
echo "unrecognized target $target"
|
||||
exit -1
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
|
||||
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GLES /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib /LIBPATH:../../bin libEGL.dll.lib libGLESv2.dll.lib user32.lib opengl32.lib gdi32.lib /out:../../bin/example_canvas.exe
|
||||
|
||||
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/example_canvas.exe
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
BINDIR=../../bin
|
||||
RESDIR=../../resources
|
||||
SRCDIR=../../src
|
||||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip -DMG_IMPLEMENTS_BACKEND_METAL"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_canvas main.c
|
||||
#!/bin/bash
|
||||
|
||||
BINDIR=../../bin
|
||||
RESDIR=../../resources
|
||||
SRCDIR=../../src
|
||||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_canvas main.c
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*****************************************************************/
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
#include<errno.h>
|
||||
|
||||
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
|
||||
#include<math.h>
|
||||
|
@ -16,6 +17,7 @@
|
|||
|
||||
#define LOG_SUBSYSTEM "Main"
|
||||
|
||||
|
||||
mg_font create_font()
|
||||
{
|
||||
//NOTE(martin): create font
|
||||
|
@ -25,7 +27,7 @@ mg_font create_font()
|
|||
FILE* fontFile = fopen(fontPathCString, "r");
|
||||
if(!fontFile)
|
||||
{
|
||||
LOG_ERROR("Could not load font file '%s'\n", fontPathCString);
|
||||
LOG_ERROR("Could not load font file '%s': %s\n", fontPathCString, strerror(errno));
|
||||
return(mg_font_nil());
|
||||
}
|
||||
unsigned char* fontData = 0;
|
||||
|
@ -53,22 +55,26 @@ int main()
|
|||
LogLevel(LOG_LEVEL_DEBUG);
|
||||
|
||||
mp_init();
|
||||
mp_clock_init();
|
||||
mp_clock_init(); //TODO put that in mp_init()?
|
||||
|
||||
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
|
||||
mp_window window = mp_window_create(rect, "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);
|
||||
|
||||
//NOTE: create surface
|
||||
#if defined(OS_MACOS)
|
||||
mg_surface surface = mg_metal_surface_create_for_window(window);
|
||||
#elif defined(OS_WIN64)
|
||||
mg_surface surface = mg_gl_surface_create_for_window(window);
|
||||
#else
|
||||
#error "unsupported OS"
|
||||
#endif
|
||||
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_DEFAULT);
|
||||
mg_surface_swap_interval(surface, 0);
|
||||
|
||||
//TODO: create canvas
|
||||
mg_canvas canvas = mg_canvas_create(surface);
|
||||
|
||||
if(mg_canvas_is_nil(canvas))
|
||||
{
|
||||
printf("Error: couldn't create canvas\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
mg_font font = create_font();
|
||||
|
||||
// start app
|
||||
|
@ -76,7 +82,8 @@ int main()
|
|||
mp_window_focus(window);
|
||||
|
||||
f32 x = 400, y = 300;
|
||||
f32 dx = 5, dy = 5;
|
||||
f32 speed = 0;
|
||||
f32 dx = speed, dy = speed;
|
||||
f64 frameTime = 0;
|
||||
|
||||
while(!mp_should_quit())
|
||||
|
@ -94,37 +101,39 @@ int main()
|
|||
mp_request_quit();
|
||||
} break;
|
||||
|
||||
case MP_EVENT_WINDOW_RESIZE:
|
||||
{
|
||||
printf("resized, rect = {%f, %f, %f, %f}\n",
|
||||
event.frame.rect.x,
|
||||
event.frame.rect.y,
|
||||
event.frame.rect.w,
|
||||
event.frame.rect.h);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_KEYBOARD_KEY:
|
||||
{
|
||||
if(event.key.action == MP_KEY_PRESS || event.key.action == MP_KEY_REPEAT)
|
||||
{
|
||||
/*
|
||||
if(event.key.code == MP_KEY_LEFT)
|
||||
{
|
||||
dx-=5.1;
|
||||
if(x - 200 > 0)
|
||||
{
|
||||
x-=5;
|
||||
}
|
||||
}
|
||||
else if(event.key.code == MP_KEY_RIGHT)
|
||||
{
|
||||
dx+=5.1;
|
||||
if(x + 200 < contentRect.w)
|
||||
{
|
||||
x+=5;
|
||||
}
|
||||
}
|
||||
else if(event.key.code == MP_KEY_UP)
|
||||
{
|
||||
dy+=5.1;
|
||||
if(y + 200 < contentRect.h)
|
||||
{
|
||||
y+=5;
|
||||
}
|
||||
}
|
||||
else if(event.key.code == MP_KEY_DOWN)
|
||||
{
|
||||
dy-=5.1;
|
||||
if(y - 200 > 0)
|
||||
{
|
||||
y-=5;
|
||||
}
|
||||
}
|
||||
*/
|
||||
//*/
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -135,19 +144,23 @@ int main()
|
|||
|
||||
if(x-200 < 0)
|
||||
{
|
||||
dx = 5;
|
||||
x = 200;
|
||||
dx = speed;
|
||||
}
|
||||
if(x+200 > 800)
|
||||
if(x+200 > contentRect.w)
|
||||
{
|
||||
dx = -5;
|
||||
x = contentRect.w - 200;
|
||||
dx = -speed;
|
||||
}
|
||||
if(y-200 < 0)
|
||||
{
|
||||
dy = 5;
|
||||
y = 200;
|
||||
dy = speed;
|
||||
}
|
||||
if(y+200 > 550)
|
||||
if(y+200 > contentRect.h)
|
||||
{
|
||||
dy = -5;
|
||||
y = contentRect.h - 200;
|
||||
dy = -speed;
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
|
@ -166,7 +179,6 @@ int main()
|
|||
f32 frown = frameTime > 0.033 ? 100 : 0;
|
||||
|
||||
mg_set_color_rgba(0, 0, 0, 1);
|
||||
|
||||
mg_set_width(20);
|
||||
mg_move_to(x-100, y-100);
|
||||
mg_cubic_to(x-50, y-150+frown, x+50, y-150+frown, x+100, y-100);
|
||||
|
@ -198,9 +210,13 @@ int main()
|
|||
|
||||
mem_arena_clear(mem_scratch());
|
||||
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
|
||||
|
||||
}
|
||||
|
||||
mg_font_destroy(font);
|
||||
mg_canvas_destroy(canvas);
|
||||
mg_surface_destroy(surface);
|
||||
mp_window_destroy(window);
|
||||
|
||||
mp_terminate();
|
||||
|
||||
return(0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext
|
||||
|
||||
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/perf_text.exe
|
||||
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/perf_text.exe
|
||||
|
|
|
@ -63,10 +63,8 @@ static const char* TEST_STRING =
|
|||
mg_font create_font()
|
||||
{
|
||||
//NOTE(martin): create font
|
||||
/* str8 fontPath = mp_app_get_resource_path(mem_scratch(), "../resources/OpenSansLatinSubset.ttf");
|
||||
str8 fontPath = mp_app_get_resource_path(mem_scratch(), "../resources/OpenSansLatinSubset.ttf");
|
||||
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath);
|
||||
*/
|
||||
char* fontPathCString = "resources/OpenSansLatinSubset.ttf";
|
||||
|
||||
FILE* fontFile = fopen(fontPathCString, "r");
|
||||
if(!fontFile)
|
||||
|
@ -107,13 +105,7 @@ int main()
|
|||
|
||||
//NOTE: create surface, canvas and font
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
mg_surface surface = mg_metal_surface_create_for_window(window);
|
||||
#elif defined(OS_WIN64)
|
||||
mg_surface surface = mg_gl_surface_create_for_window(window);
|
||||
#else
|
||||
#error "unsupported OS"
|
||||
#endif
|
||||
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_DEFAULT);
|
||||
mg_surface_swap_interval(surface, 0);
|
||||
|
||||
mg_canvas canvas = mg_canvas_create(surface);
|
||||
|
@ -300,6 +292,11 @@ int main()
|
|||
mem_arena_clear(mem_scratch());
|
||||
}
|
||||
|
||||
|
||||
mg_font_destroy(font);
|
||||
mg_canvas_destroy(canvas);
|
||||
mg_surface_destroy(surface);
|
||||
mp_window_destroy(window);
|
||||
mp_terminate();
|
||||
|
||||
return(0);
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
|
||||
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/example_canvas.exe
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
BINDIR=../../bin
|
||||
RESDIR=../../resources
|
||||
SRCDIR=../../src
|
||||
|
||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip"
|
||||
|
||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_canvas main.c
|
|
@ -1,247 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: main.cpp
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 30/07/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
#include<errno.h>
|
||||
|
||||
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
|
||||
#include<math.h>
|
||||
|
||||
#include"milepost.h"
|
||||
|
||||
#define LOG_SUBSYSTEM "Main"
|
||||
|
||||
|
||||
mg_font create_font()
|
||||
{
|
||||
//NOTE(martin): create font
|
||||
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)
|
||||
{
|
||||
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);
|
||||
u32 fontDataSize = ftell(fontFile);
|
||||
rewind(fontFile);
|
||||
fontData = (unsigned char*)malloc(fontDataSize);
|
||||
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_LATIN_EXTENDED_A,
|
||||
UNICODE_RANGE_LATIN_EXTENDED_B,
|
||||
UNICODE_RANGE_SPECIALS};
|
||||
|
||||
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
|
||||
free(fontData);
|
||||
|
||||
return(font);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
LogLevel(LOG_LEVEL_DEBUG);
|
||||
|
||||
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 contentRect = mp_window_get_content_rect(window);
|
||||
|
||||
//NOTE: create surface
|
||||
#if defined(OS_MACOS)
|
||||
mg_surface surface = mg_metal_surface_create_for_window(window);
|
||||
#elif defined(OS_WIN64)
|
||||
mg_surface surface = mg_gl_surface_create_for_window(window);
|
||||
#else
|
||||
#error "unsupported OS"
|
||||
#endif
|
||||
|
||||
mg_surface_swap_interval(surface, 0);
|
||||
|
||||
//TODO: create canvas
|
||||
mg_canvas canvas = mg_canvas_create(surface);
|
||||
|
||||
if(mg_canvas_is_nil(canvas))
|
||||
{
|
||||
printf("Error: couldn't create canvas\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
mg_font font = create_font();
|
||||
|
||||
// start app
|
||||
mp_window_bring_to_front(window);
|
||||
mp_window_focus(window);
|
||||
|
||||
f32 x = 400, y = 300;
|
||||
f32 speed = 0;
|
||||
f32 dx = speed, dy = speed;
|
||||
f64 frameTime = 0;
|
||||
|
||||
while(!mp_should_quit())
|
||||
{
|
||||
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
||||
|
||||
mp_pump_events(0);
|
||||
mp_event event = {0};
|
||||
while(mp_next_event(&event))
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case MP_EVENT_WINDOW_CLOSE:
|
||||
{
|
||||
mp_request_quit();
|
||||
} break;
|
||||
|
||||
case MP_EVENT_WINDOW_RESIZE:
|
||||
{
|
||||
printf("resized, rect = {%f, %f, %f, %f}\n",
|
||||
event.frame.rect.x,
|
||||
event.frame.rect.y,
|
||||
event.frame.rect.w,
|
||||
event.frame.rect.h);
|
||||
} break;
|
||||
|
||||
case MP_EVENT_KEYBOARD_KEY:
|
||||
{
|
||||
if(event.key.action == MP_KEY_PRESS || event.key.action == MP_KEY_REPEAT)
|
||||
{
|
||||
//*
|
||||
if(event.key.code == MP_KEY_LEFT)
|
||||
{
|
||||
if(x - 200 > 0)
|
||||
{
|
||||
x-=5;
|
||||
}
|
||||
}
|
||||
else if(event.key.code == MP_KEY_RIGHT)
|
||||
{
|
||||
if(x + 200 < contentRect.w)
|
||||
{
|
||||
x+=5;
|
||||
}
|
||||
}
|
||||
else if(event.key.code == MP_KEY_UP)
|
||||
{
|
||||
if(y + 200 < contentRect.h)
|
||||
{
|
||||
y+=5;
|
||||
}
|
||||
}
|
||||
else if(event.key.code == MP_KEY_DOWN)
|
||||
{
|
||||
if(y - 200 > 0)
|
||||
{
|
||||
y-=5;
|
||||
}
|
||||
}
|
||||
//*/
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(x-200 < 0)
|
||||
{
|
||||
x = 200;
|
||||
dx = speed;
|
||||
}
|
||||
if(x+200 > contentRect.w)
|
||||
{
|
||||
x = contentRect.w - 200;
|
||||
dx = -speed;
|
||||
}
|
||||
if(y-200 < 0)
|
||||
{
|
||||
y = 200;
|
||||
dy = speed;
|
||||
}
|
||||
if(y+200 > contentRect.h)
|
||||
{
|
||||
y = contentRect.h - 200;
|
||||
dy = -speed;
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
// background
|
||||
mg_set_color_rgba(0, 1, 1, 1);
|
||||
mg_clear();
|
||||
|
||||
// mg_clip_push(100, 100, contentRect.w - 200, contentRect.h - 200);
|
||||
// head
|
||||
mg_set_color_rgba(1, 1, 0, 1);
|
||||
mg_circle_fill(x, y, 200);
|
||||
/*
|
||||
mg_clip_pop();
|
||||
mg_set_width(2);
|
||||
mg_set_color_rgba(1, 0, 0, 1);
|
||||
mg_rectangle_stroke(100, 100, contentRect.w - 200, contentRect.h - 200);
|
||||
*/
|
||||
// smile
|
||||
f32 frown = frameTime > 0.033 ? 100 : 0;
|
||||
|
||||
mg_set_color_rgba(0, 0, 0, 1);
|
||||
|
||||
mg_set_width(20);
|
||||
mg_move_to(x-100, y-100);
|
||||
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);
|
||||
mg_ellipse_fill(x+70, y+50, 30, 50);
|
||||
|
||||
// text
|
||||
mg_set_color_rgba(0, 0, 1, 1);
|
||||
mg_set_font(font);
|
||||
mg_set_font_size(12);
|
||||
mg_move_to(50, 50);
|
||||
|
||||
str8 text = str8_pushf(mem_scratch(),
|
||||
"Milepost vector graphics test program (frame time = %fs, fps = %f)...",
|
||||
frameTime,
|
||||
1./frameTime);
|
||||
mg_text_outlines(text);
|
||||
mg_fill();
|
||||
|
||||
printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
|
||||
frameTime,
|
||||
1./frameTime);
|
||||
|
||||
mg_flush();
|
||||
mg_surface_present(surface);
|
||||
|
||||
mem_arena_clear(mem_scratch());
|
||||
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
|
||||
}
|
||||
|
||||
mg_font_destroy(font);
|
||||
mg_canvas_destroy(canvas);
|
||||
mg_surface_destroy(surface);
|
||||
mp_window_destroy(window);
|
||||
|
||||
mp_terminate();
|
||||
|
||||
return(0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -38,17 +38,6 @@ typedef struct mg_gl_canvas_backend
|
|||
|
||||
} mg_gl_canvas_backend;
|
||||
|
||||
mg_gl_surface* mg_gl_canvas_get_surface(mg_gl_canvas_backend* canvas)
|
||||
{
|
||||
mg_gl_surface* res = 0;
|
||||
mg_surface_data* data = mg_surface_data_from_handle(canvas->surface);
|
||||
if(data && data->backend == MG_BACKEND_GL)
|
||||
{
|
||||
res = (mg_gl_surface*)data;
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
//NOTE: debugger
|
||||
typedef struct debug_vertex
|
||||
{
|
||||
|
@ -140,11 +129,6 @@ void mg_gl_send_buffers(mg_gl_canvas_backend* backend, int shapeCount, int verte
|
|||
void mg_gl_canvas_begin(mg_canvas_backend* interface)
|
||||
{
|
||||
mg_gl_canvas_backend* backend = (mg_gl_canvas_backend*)interface;
|
||||
mg_gl_surface* surface = mg_gl_canvas_get_surface(backend);
|
||||
if(!surface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
@ -157,11 +141,6 @@ void mg_gl_canvas_end(mg_canvas_backend* interface)
|
|||
void mg_gl_canvas_clear(mg_canvas_backend* interface, mg_color clearColor)
|
||||
{
|
||||
mg_gl_canvas_backend* backend = (mg_gl_canvas_backend*)interface;
|
||||
mg_gl_surface* surface = mg_gl_canvas_get_surface(backend);
|
||||
if(!surface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
@ -170,11 +149,6 @@ void mg_gl_canvas_clear(mg_canvas_backend* interface, mg_color clearColor)
|
|||
void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 vertexCount, u32 indexCount)
|
||||
{
|
||||
mg_gl_canvas_backend* backend = (mg_gl_canvas_backend*)interface;
|
||||
mg_gl_surface* surface = mg_gl_canvas_get_surface(backend);
|
||||
if(!surface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*NOTE: if we want debug_vertex while debugging, the following ensures the struct def doesn't get stripped away
|
||||
debug_vertex vertex;
|
||||
|
@ -390,8 +364,6 @@ mg_canvas_backend* mg_gl_canvas_create(mg_surface surface)
|
|||
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_GL)
|
||||
{
|
||||
mg_gl_surface* glSurface = (mg_gl_surface*)surfaceData;
|
||||
|
||||
backend = malloc_type(mg_gl_canvas_backend);
|
||||
memset(backend, 0, sizeof(mg_gl_canvas_backend));
|
||||
backend->surface = surface;
|
||||
|
|
107
src/graphics.c
107
src/graphics.c
|
@ -290,6 +290,89 @@ mg_font_data* mg_font_data_from_handle(mg_font font)
|
|||
// surface API
|
||||
//---------------------------------------------------------------
|
||||
|
||||
#if MG_COMPILE_BACKEND_GL
|
||||
#if defined(OS_WIN64)
|
||||
#include"wgl_surface.h"
|
||||
#define gl_surface_create_for_window mg_wgl_surface_create_for_window
|
||||
#elif defined(OS_MACOS)
|
||||
/*
|
||||
#include"nsgl_surface.h"
|
||||
#define gl_surface_create_for_window nsgl_surface_create_for_window
|
||||
*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_BACKEND_METAL
|
||||
#include"mtl_surface.h"
|
||||
#endif
|
||||
|
||||
bool mg_is_surface_backend_available(mg_backend_id backend)
|
||||
{
|
||||
bool result = false;
|
||||
switch(backend)
|
||||
{
|
||||
#if MG_COMPILE_BACKEND_METAL
|
||||
case MG_BACKEND_METAL:
|
||||
#endif
|
||||
#if MG_COMPILE_BACKEND_GL
|
||||
case MG_BACKEND_GL:
|
||||
#endif
|
||||
#if MG_COMPILE_BACKEND_GLES
|
||||
case MG_BACKEND_GLES:
|
||||
#endif
|
||||
result = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
bool mg_is_canvas_backend_available(mg_backend_id backend)
|
||||
{
|
||||
bool result = false;
|
||||
switch(backend)
|
||||
{
|
||||
#if MG_COMPILE_BACKEND_METAL
|
||||
case MG_BACKEND_METAL:
|
||||
#endif
|
||||
#if MG_COMPILE_BACKEND_GL && defined(OS_WIN64)
|
||||
case MG_BACKEND_GL:
|
||||
#endif
|
||||
result = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend)
|
||||
{
|
||||
mg_surface surface = mg_surface_nil();
|
||||
|
||||
switch(backend)
|
||||
{
|
||||
#if MG_COMPILE_BACKEND_GL
|
||||
case MG_BACKEND_GL:
|
||||
surface = gl_surface_create_for_window(window);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_BACKEND_METAL
|
||||
case MG_METAL_BACKEND:
|
||||
surface = mg_mtl_surface_create_for_window(window);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
void mg_surface_destroy(mg_surface handle)
|
||||
{
|
||||
DEBUG_ASSERT(__mgData.init);
|
||||
|
@ -2563,19 +2646,14 @@ mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text)
|
|||
//NOTE(martin): graphics canvas API
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef MG_IMPLEMENTS_BACKEND_METAL
|
||||
mg_canvas_backend* mg_metal_canvas_create(mg_surface surface);
|
||||
#ifdef MG_COMPILE_BACKEND_METAL
|
||||
mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface);
|
||||
#endif
|
||||
|
||||
#ifdef MG_IMPLEMENTS_BACKEND_GLES
|
||||
mg_canvas_backend* mg_gles_canvas_create(mg_surface surface);
|
||||
#endif
|
||||
|
||||
#ifdef MG_IMPLEMENTS_BACKEND_GL
|
||||
#ifdef MG_COMPILE_BACKEND_GL
|
||||
mg_canvas_backend* mg_gl_canvas_create(mg_surface surface);
|
||||
#endif
|
||||
|
||||
|
||||
mg_canvas mg_canvas_create(mg_surface surface)
|
||||
{
|
||||
mg_canvas canvas = mg_canvas_nil();
|
||||
|
@ -2585,20 +2663,13 @@ mg_canvas mg_canvas_create(mg_surface surface)
|
|||
mg_canvas_backend* backend = 0;
|
||||
switch(surfaceData->backend)
|
||||
{
|
||||
#ifdef MG_IMPLEMENTS_BACKEND_METAL
|
||||
#ifdef MG_COMPILE_BACKEND_METAL
|
||||
case MG_BACKEND_METAL:
|
||||
backend = mg_metal_canvas_create(surface);
|
||||
backend = mg_mtl_canvas_create(surface);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifdef MG_IMPLEMENTS_BACKEND_GLES
|
||||
case MG_BACKEND_GLES:
|
||||
backend = mg_gles_canvas_create(surface);
|
||||
break;
|
||||
#endif
|
||||
*/
|
||||
#ifdef MG_IMPLEMENTS_BACKEND_GL
|
||||
#ifdef MG_COMPILE_BACKEND_GL
|
||||
case MG_BACKEND_GL:
|
||||
backend = mg_gl_canvas_create(surface);
|
||||
break;
|
||||
|
|
|
@ -9,6 +9,72 @@
|
|||
#ifndef __GRAPHICS_H_
|
||||
#define __GRAPHICS_H_
|
||||
|
||||
#include"typedefs.h"
|
||||
#include"platform.h"
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): backends selection
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
typedef enum {
|
||||
MG_BACKEND_NONE,
|
||||
MG_BACKEND_METAL,
|
||||
MG_BACKEND_GL,
|
||||
MG_BACKEND_GLES } mg_backend_id;
|
||||
|
||||
//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
|
||||
#if defined(OS_MACOS)
|
||||
#ifndef MG_COMPILE_BACKEND_METAL
|
||||
#define MG_COMPILE_BACKEND_METAL 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_COMPILE_BACKEND_GL
|
||||
#define MG_COMPILE_BACKEND_GL 1
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_BACKEND_METAL
|
||||
#define MG_BACKEND_DEFAULT MG_BACKEND_METAL
|
||||
#elif MG_COMPILE_BACKEND_GL
|
||||
#define MG_BACKEND_DEFAULT MG_BACKEND_GL
|
||||
#else
|
||||
#define MG_BACKEND_DEFAULT MG_BACKEND_NONE
|
||||
#endif
|
||||
|
||||
#elif defined(OS_WIN64)
|
||||
#ifndef MG_COMPILE_BACKEND_GL
|
||||
#define MG_COMPILE_BACKEND_GL 1
|
||||
#endif
|
||||
|
||||
#if MG_COMPILE_BACKEND_GL
|
||||
#define MG_BACKEND_DEFAULT MG_BACKEND_GL
|
||||
#else
|
||||
#define MG_BACKEND_DEFAULT MG_BACKEND_NONE
|
||||
#endif
|
||||
|
||||
#elif defined(OS_LINUX)
|
||||
#ifndef MG_COMPILE_BACKEND_GL
|
||||
#define MG_COMPILE_BACKEND_GL 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//NOTE: these macros are used to select backend-specific APIs to include when using milepost
|
||||
#ifdef MG_EXPOSE_SURFACE_METAL
|
||||
#include"mtl_surface.h"
|
||||
#endif
|
||||
|
||||
#ifdef MG_EXPOSE_SURFACE_WGL
|
||||
#include"wgl_surface.h"
|
||||
#endif
|
||||
|
||||
//TODO: expose nsgl surface when supported, expose egl surface, etc...
|
||||
|
||||
//TODO: add MG_INCLUDE_OPENGL/GLES/etc, once we know how we make different gl versions co-exist
|
||||
|
||||
bool mg_is_surface_backend_available(mg_backend_id id);
|
||||
bool mg_is_canvas_backend_available(mg_backend_id id);
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//NOTE(martin): graphics surface
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
@ -17,6 +83,7 @@ typedef struct mg_surface { u64 h; } mg_surface;
|
|||
mg_surface mg_surface_nil();
|
||||
bool mg_surface_is_nil(mg_surface surface);
|
||||
|
||||
mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend);
|
||||
void mg_surface_destroy(mg_surface surface);
|
||||
void mg_surface_prepare(mg_surface surface);
|
||||
void mg_surface_present(mg_surface surface);
|
||||
|
|
|
@ -15,13 +15,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum { MG_BACKEND_DUMMY,
|
||||
MG_BACKEND_METAL,
|
||||
MG_BACKEND_GL,
|
||||
MG_BACKEND_GLES,
|
||||
//...
|
||||
} mg_backend_id;
|
||||
|
||||
typedef struct mg_surface_data mg_surface_data;
|
||||
|
||||
typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface);
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: metal_surface.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 25/12/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __METAL_SURFACE_H_
|
||||
#define __METAL_SURFACE_H_
|
||||
|
||||
#include"graphics.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import<Metal/Metal.h>
|
||||
#endif
|
||||
|
||||
mg_surface mg_metal_surface_create_for_window(mp_window window);
|
||||
|
||||
void* mg_metal_surface_render_encoder(mg_surface surface);
|
||||
void* mg_metal_surface_compute_encoder(mg_surface surface);
|
||||
void* mg_metal_surface_layer(mg_surface surface);
|
||||
void* mg_metal_surface_drawable(mg_surface surface);
|
||||
void* mg_metal_surface_command_buffer(mg_surface surface);
|
||||
|
||||
#endif //__METAL_SURFACE_H_
|
|
@ -48,23 +48,21 @@
|
|||
#endif
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// application layer
|
||||
// app/graphics layer
|
||||
//---------------------------------------------------------------
|
||||
|
||||
#if defined(OS_WIN64)
|
||||
#include"win32_app.c"
|
||||
#include"win32_gl_surface.c"
|
||||
#include"gl_canvas.c"
|
||||
// #include"win32_gles_surface.c"
|
||||
// #include"gles_canvas.c"
|
||||
#include"graphics.c"
|
||||
|
||||
#if MG_COMPILE_BACKEND_GL
|
||||
#include"wgl_surface.c"
|
||||
#include"gl_canvas.c"
|
||||
#endif
|
||||
|
||||
#elif defined(OS_MACOS)
|
||||
//NOTE: macos application layer is defined in milepost.m
|
||||
//NOTE: macos application layer and graphics backends are defined in milepost.m
|
||||
#include"graphics.c"
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// graphics/ui layer
|
||||
//---------------------------------------------------------------
|
||||
#include"graphics.c"
|
||||
//#include"ui.c"
|
||||
|
|
|
@ -33,34 +33,17 @@
|
|||
*/
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// application layer
|
||||
// application/graphics layer
|
||||
//----------------------------------------------------------------
|
||||
#include"mp_app.h"
|
||||
|
||||
#if defined(OS_WIN64) || defined(OS_WIN32)
|
||||
|
||||
#if MG_IMPLEMENTS_BACKEND_GLES
|
||||
#include"win32_gles_surface.h"
|
||||
#endif
|
||||
|
||||
#if MG_IMPLEMENTS_BACKEND_GL
|
||||
#define WIN32_GL_LOADER_API
|
||||
#include"win32_gl_loader.h"
|
||||
#undef WIN32_GL_LOADER_API
|
||||
|
||||
#include"win32_gl_surface.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MG_IMPLEMENTS_BACKEND_METAL
|
||||
#include"metal_surface.h"
|
||||
#endif
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// graphics/ui layer
|
||||
//----------------------------------------------------------------
|
||||
#include"graphics.h"
|
||||
|
||||
#if defined(OS_WIN64)
|
||||
#define WIN32_GL_LOADER_API
|
||||
#include"wgl_loader.h"
|
||||
#undef WIN32_GL_LOADER_API
|
||||
#endif
|
||||
|
||||
//#include"ui.h"
|
||||
|
||||
#endif //__MILEPOST_H_
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: milepost.m
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 13/02/2021
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include"osx_app.m"
|
||||
#include"metal_surface.m"
|
||||
#include"metal_canvas.m"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include"osx_gles_surface.m"
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
//#include"osx_surface_client.m"
|
||||
/************************************************************//**
|
||||
*
|
||||
* @file: milepost.m
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 13/02/2021
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include"osx_app.m"
|
||||
#include"graphics.h"
|
||||
|
||||
#if MG_COMPILE_BACKEND_METAL
|
||||
#include"mtl_surface.m"
|
||||
#include"mtl_canvas.m"
|
||||
#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"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: metal_canvas.m
|
||||
* @file: mtl_canvas.m
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 12/07/2020
|
||||
* @revision: 24/01/2023
|
||||
|
@ -14,13 +14,13 @@
|
|||
#include"macro_helpers.h"
|
||||
#include"osx_app.h"
|
||||
|
||||
#include"metal_shader.h"
|
||||
#include"mtl_shader.h"
|
||||
|
||||
#define LOG_SUBSYSTEM "Graphics"
|
||||
|
||||
static const int MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH = 4<<20;
|
||||
static const int MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH = 4<<20;
|
||||
|
||||
typedef struct mg_metal_canvas_backend
|
||||
typedef struct mg_mtl_canvas_backend
|
||||
{
|
||||
mg_canvas_backend interface;
|
||||
mg_surface surface;
|
||||
|
@ -47,36 +47,36 @@ typedef struct mg_metal_canvas_backend
|
|||
id<MTLBuffer> triangleArray;
|
||||
id<MTLBuffer> boxArray;
|
||||
|
||||
} mg_metal_canvas_backend;
|
||||
} mg_mtl_canvas_backend;
|
||||
|
||||
mg_metal_surface* mg_metal_canvas_get_surface(mg_metal_canvas_backend* canvas)
|
||||
mg_mtl_surface* mg_mtl_canvas_get_surface(mg_mtl_canvas_backend* canvas)
|
||||
{
|
||||
mg_metal_surface* res = 0;
|
||||
mg_mtl_surface* res = 0;
|
||||
mg_surface_data* data = mg_surface_data_from_handle(canvas->surface);
|
||||
if(data && data->backend == MG_BACKEND_METAL)
|
||||
{
|
||||
res = (mg_metal_surface*)data;
|
||||
res = (mg_mtl_surface*)data;
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
void mg_metal_canvas_begin(mg_canvas_backend* interface)
|
||||
void mg_mtl_canvas_begin(mg_canvas_backend* interface)
|
||||
{}
|
||||
|
||||
void mg_metal_canvas_end(mg_canvas_backend* interface)
|
||||
void mg_mtl_canvas_end(mg_canvas_backend* interface)
|
||||
{}
|
||||
|
||||
void mg_metal_canvas_clear(mg_canvas_backend* interface, mg_color clearColor)
|
||||
void mg_mtl_canvas_clear(mg_canvas_backend* interface, mg_color clearColor)
|
||||
{
|
||||
//TODO
|
||||
mg_metal_canvas_backend* backend = (mg_metal_canvas_backend*)interface;
|
||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||
backend->clearColor = clearColor;
|
||||
}
|
||||
|
||||
void mg_metal_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u32 indexCount, u32 shapeCount)
|
||||
void mg_mtl_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u32 indexCount, u32 shapeCount)
|
||||
{
|
||||
mg_metal_canvas_backend* backend = (mg_metal_canvas_backend*)interface;
|
||||
mg_metal_surface* surface = mg_metal_canvas_get_surface(backend);
|
||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||
mg_mtl_surface* surface = mg_mtl_canvas_get_surface(backend);
|
||||
if(!surface)
|
||||
{
|
||||
return;
|
||||
|
@ -86,7 +86,7 @@ void mg_metal_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u
|
|||
{
|
||||
if(surface->commandBuffer == nil || surface->commandBuffer == nil)
|
||||
{
|
||||
mg_metal_surface_acquire_drawable_and_command_buffer(surface);
|
||||
mg_mtl_surface_acquire_drawable_and_command_buffer(surface);
|
||||
}
|
||||
|
||||
ASSERT(indexCount * sizeof(i32) < [backend->indexBuffer length]);
|
||||
|
@ -205,10 +205,10 @@ void mg_metal_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u
|
|||
}
|
||||
|
||||
/*
|
||||
void mg_metal_canvas_viewport(mg_canvas_backend* interface, mp_rect viewPort)
|
||||
void mg_mtl_canvas_viewport(mg_canvas_backend* interface, mp_rect viewPort)
|
||||
{
|
||||
mg_metal_canvas_backend* backend = (mg_metal_canvas_backend*)interface;
|
||||
mg_metal_surface* surface = mg_metal_canvas_get_surface(backend);
|
||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||
mg_mtl_surface* surface = mg_mtl_canvas_get_surface(backend);
|
||||
if(!surface)
|
||||
{
|
||||
return;
|
||||
|
@ -236,15 +236,15 @@ void mg_metal_canvas_viewport(mg_canvas_backend* interface, mp_rect viewPort)
|
|||
}
|
||||
*/
|
||||
|
||||
void mg_metal_canvas_update_vertex_layout(mg_metal_canvas_backend* backend)
|
||||
void mg_mtl_canvas_update_vertex_layout(mg_mtl_canvas_backend* backend)
|
||||
{
|
||||
char* vertexBase = (char*)[backend->vertexBuffer contents];
|
||||
char* shapeBase = (char*)[backend->shapeBuffer contents];
|
||||
char* indexBase = (char*)[backend->indexBuffer contents];
|
||||
|
||||
backend->interface.vertexLayout = (mg_vertex_layout){
|
||||
.maxVertexCount = MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH,
|
||||
.maxIndexCount = MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH,
|
||||
.maxVertexCount = MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH,
|
||||
.maxIndexCount = MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH,
|
||||
.cubicBuffer = vertexBase + offsetof(mg_vertex, cubic),
|
||||
.cubicStride = sizeof(mg_vertex),
|
||||
.posBuffer = vertexBase + offsetof(mg_vertex, pos),
|
||||
|
@ -263,9 +263,9 @@ void mg_metal_canvas_update_vertex_layout(mg_metal_canvas_backend* backend)
|
|||
.indexStride = sizeof(int)};
|
||||
}
|
||||
|
||||
void mg_metal_canvas_destroy(mg_canvas_backend* interface)
|
||||
void mg_mtl_canvas_destroy(mg_canvas_backend* interface)
|
||||
{
|
||||
mg_metal_canvas_backend* backend = (mg_metal_canvas_backend*)interface;
|
||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -280,9 +280,9 @@ void mg_metal_canvas_destroy(mg_canvas_backend* interface)
|
|||
}
|
||||
}
|
||||
|
||||
void mg_metal_canvas_atlas_upload(mg_canvas_backend* interface, mp_rect rect, u8* bytes)
|
||||
void mg_mtl_canvas_atlas_upload(mg_canvas_backend* interface, mp_rect rect, u8* bytes)
|
||||
{@autoreleasepool{
|
||||
mg_metal_canvas_backend* backend = (mg_metal_canvas_backend*)interface;
|
||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||
|
||||
MTLRegion region = MTLRegionMake2D(rect.x, rect.y, rect.w, rect.h);
|
||||
[backend->atlasTexture replaceRegion:region
|
||||
|
@ -291,25 +291,25 @@ void mg_metal_canvas_atlas_upload(mg_canvas_backend* interface, mp_rect rect, u8
|
|||
bytesPerRow: 4 * rect.w];
|
||||
}}
|
||||
|
||||
mg_canvas_backend* mg_metal_canvas_create(mg_surface surface)
|
||||
mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
||||
{
|
||||
mg_metal_canvas_backend* backend = 0;
|
||||
mg_mtl_canvas_backend* backend = 0;
|
||||
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_METAL)
|
||||
{
|
||||
mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData;
|
||||
mg_mtl_surface* metalSurface = (mg_mtl_surface*)surfaceData;
|
||||
|
||||
backend = malloc_type(mg_metal_canvas_backend);
|
||||
backend = malloc_type(mg_mtl_canvas_backend);
|
||||
backend->surface = surface;
|
||||
|
||||
//NOTE(martin): setup interface functions
|
||||
backend->interface.destroy = mg_metal_canvas_destroy;
|
||||
backend->interface.begin = mg_metal_canvas_begin;
|
||||
backend->interface.end = mg_metal_canvas_end;
|
||||
backend->interface.clear = mg_metal_canvas_clear;
|
||||
backend->interface.drawBatch = mg_metal_canvas_draw_batch;
|
||||
backend->interface.atlasUpload = mg_metal_canvas_atlas_upload;
|
||||
backend->interface.destroy = mg_mtl_canvas_destroy;
|
||||
backend->interface.begin = mg_mtl_canvas_begin;
|
||||
backend->interface.end = mg_mtl_canvas_end;
|
||||
backend->interface.clear = mg_mtl_canvas_clear;
|
||||
backend->interface.drawBatch = mg_mtl_canvas_draw_batch;
|
||||
backend->interface.atlasUpload = mg_mtl_canvas_atlas_upload;
|
||||
|
||||
mp_rect frame = mg_surface_get_frame(surface);
|
||||
backend->viewPort = (mp_rect){0, 0, frame.w, frame.h};
|
||||
|
@ -352,22 +352,22 @@ mg_canvas_backend* mg_metal_canvas_create(mg_surface surface)
|
|||
MTLResourceOptions bufferOptions = MTLResourceCPUCacheModeWriteCombined
|
||||
| MTLResourceStorageModeShared;
|
||||
|
||||
backend->indexBuffer = [metalSurface->device newBufferWithLength: MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(int)
|
||||
backend->indexBuffer = [metalSurface->device newBufferWithLength: MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(int)
|
||||
options: bufferOptions];
|
||||
|
||||
backend->vertexBuffer = [metalSurface->device newBufferWithLength: MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(mg_vertex)
|
||||
backend->vertexBuffer = [metalSurface->device newBufferWithLength: MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(mg_vertex)
|
||||
options: bufferOptions];
|
||||
|
||||
backend->shapeBuffer = [metalSurface->device newBufferWithLength: MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(mg_shape)
|
||||
backend->shapeBuffer = [metalSurface->device newBufferWithLength: MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(mg_shape)
|
||||
options: bufferOptions];
|
||||
|
||||
backend->tilesArray = [metalSurface->device newBufferWithLength: RENDERER_TILE_BUFFER_SIZE*sizeof(int)*RENDERER_MAX_TILES
|
||||
options: MTLResourceStorageModePrivate];
|
||||
|
||||
backend->triangleArray = [metalSurface->device newBufferWithLength: MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(mg_triangle_data)
|
||||
backend->triangleArray = [metalSurface->device newBufferWithLength: MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(mg_triangle_data)
|
||||
options: MTLResourceStorageModePrivate];
|
||||
|
||||
backend->boxArray = [metalSurface->device newBufferWithLength: MG_METAL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(vector_float4)
|
||||
backend->boxArray = [metalSurface->device newBufferWithLength: MG_MTL_CANVAS_DEFAULT_BUFFER_LENGTH*sizeof(vector_float4)
|
||||
options: MTLResourceStorageModePrivate];
|
||||
|
||||
//TODO(martin): retain ?
|
||||
|
@ -387,7 +387,7 @@ mg_canvas_backend* mg_metal_canvas_create(mg_surface surface)
|
|||
//-----------------------------------------------------------
|
||||
|
||||
//TODO(martin): filepath magic to find metallib path when not in the working directory
|
||||
str8 shaderPath = mp_app_get_resource_path(mem_scratch(), "../resources/metal_shader.metallib");
|
||||
str8 shaderPath = mp_app_get_resource_path(mem_scratch(), "../resources/mtl_shader.metallib");
|
||||
NSString* metalFileName = [[NSString alloc] initWithBytes: shaderPath.ptr length:shaderPath.len encoding: NSUTF8StringEncoding];
|
||||
NSError* err = 0;
|
||||
id<MTLLibrary> library = [metalSurface->device newLibraryWithFile: metalFileName error:&err];
|
||||
|
@ -460,7 +460,7 @@ mg_canvas_backend* mg_metal_canvas_create(mg_surface surface)
|
|||
}
|
||||
}
|
||||
|
||||
mg_metal_canvas_update_vertex_layout(backend);
|
||||
mg_mtl_canvas_update_vertex_layout(backend);
|
||||
}
|
||||
|
||||
return((mg_canvas_backend*)backend);
|
|
@ -1,13 +1,13 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: metal_shader.h
|
||||
* @file: mtl_shader.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 01/08/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __METAL_RENDERER_H_
|
||||
#define __METAL_RENDERER_H_
|
||||
#ifndef __MTL_RENDERER_H_
|
||||
#define __MTL_RENDERER_H_
|
||||
|
||||
#include<simd/simd.h>
|
||||
|
||||
|
@ -50,4 +50,4 @@ typedef struct mg_triangle_data
|
|||
|
||||
} mg_triangle_data;
|
||||
|
||||
#endif //__METAL_RENDERER_H_
|
||||
#endif //__MTL_RENDERER_H_
|
|
@ -2,7 +2,7 @@
|
|||
#include<metal_stdlib>
|
||||
#include<simd/simd.h>
|
||||
|
||||
#include"metal_shader.h"
|
||||
#include"mtl_shader.h"
|
||||
|
||||
using namespace metal;
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: mtl_surface.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 25/12/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __MTL_SURFACE_H_
|
||||
#define __MTL_SURFACE_H_
|
||||
|
||||
#include"graphics.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import<Mtl/Metal.h>
|
||||
#endif
|
||||
|
||||
mg_surface mg_mtl_surface_create_for_window(mp_window window);
|
||||
|
||||
void* mg_mtl_surface_render_encoder(mg_surface surface);
|
||||
void* mg_mtl_surface_compute_encoder(mg_surface surface);
|
||||
void* mg_mtl_surface_layer(mg_surface surface);
|
||||
void* mg_mtl_surface_drawable(mg_surface surface);
|
||||
void* mg_mtl_surface_command_buffer(mg_surface surface);
|
||||
|
||||
#endif //__MTL_SURFACE_H_
|
|
@ -17,16 +17,16 @@
|
|||
|
||||
#define LOG_SUBSYSTEM "Graphics"
|
||||
|
||||
static const u32 MP_METAL_MAX_DRAWABLES_IN_FLIGHT = 3;
|
||||
static const u32 MP_MTL_MAX_DRAWABLES_IN_FLIGHT = 3;
|
||||
|
||||
typedef struct mg_metal_surface
|
||||
typedef struct mg_mtl_surface
|
||||
{
|
||||
mg_surface_data interface;
|
||||
|
||||
// permanent metal resources
|
||||
// permanent mtl resources
|
||||
NSView* view;
|
||||
id<MTLDevice> device;
|
||||
CAMetalLayer* metalLayer;
|
||||
CAMetalLayer* mtlLayer;
|
||||
id<MTLCommandQueue> commandQueue;
|
||||
|
||||
// transient metal resources
|
||||
|
@ -35,21 +35,21 @@ typedef struct mg_metal_surface
|
|||
|
||||
dispatch_semaphore_t drawableSemaphore;
|
||||
|
||||
} mg_metal_surface;
|
||||
} mg_mtl_surface;
|
||||
|
||||
void mg_metal_surface_destroy(mg_surface_data* interface)
|
||||
void mg_mtl_surface_destroy(mg_surface_data* interface)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
[surface->commandQueue release];
|
||||
[surface->metalLayer release];
|
||||
[surface->mtlLayer release];
|
||||
[surface->device release];
|
||||
}
|
||||
}
|
||||
|
||||
void mg_metal_surface_acquire_drawable_and_command_buffer(mg_metal_surface* surface)
|
||||
void mg_mtl_surface_acquire_drawable_and_command_buffer(mg_mtl_surface* surface)
|
||||
{@autoreleasepool{
|
||||
/*WARN(martin): this is super important
|
||||
When the app is put in the background, it seems that if there are buffers in flight, the drawables to
|
||||
|
@ -76,7 +76,7 @@ void mg_metal_surface_acquire_drawable_and_command_buffer(mg_metal_surface* surf
|
|||
*/
|
||||
dispatch_semaphore_wait(surface->drawableSemaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
surface->drawable = [surface->metalLayer nextDrawable];
|
||||
surface->drawable = [surface->mtlLayer nextDrawable];
|
||||
ASSERT(surface->drawable != nil);
|
||||
|
||||
//TODO: make this a weak reference if we use ARC
|
||||
|
@ -92,10 +92,10 @@ void mg_metal_surface_acquire_drawable_and_command_buffer(mg_metal_surface* surf
|
|||
[surface->drawable retain];
|
||||
}}
|
||||
|
||||
void mg_metal_surface_prepare(mg_surface_data* interface)
|
||||
void mg_mtl_surface_prepare(mg_surface_data* interface)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_metal_surface_acquire_drawable_and_command_buffer(surface);
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
mg_mtl_surface_acquire_drawable_and_command_buffer(surface);
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -109,9 +109,9 @@ void mg_metal_surface_prepare(mg_surface_data* interface)
|
|||
}
|
||||
}
|
||||
|
||||
void mg_metal_surface_present(mg_surface_data* interface)
|
||||
void mg_mtl_surface_present(mg_surface_data* interface)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
@autoreleasepool
|
||||
{
|
||||
//NOTE(martin): present drawable and commit command buffer
|
||||
|
@ -127,32 +127,32 @@ void mg_metal_surface_present(mg_surface_data* interface)
|
|||
}
|
||||
}
|
||||
|
||||
void mg_metal_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
void mg_mtl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//TODO
|
||||
////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
void mg_metal_surface_set_frame(mg_surface_data* interface, mp_rect frame)
|
||||
void mg_mtl_surface_set_frame(mg_surface_data* interface, mp_rect frame)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}};
|
||||
[surface->view setFrame: cgFrame];
|
||||
f32 scale = surface->metalLayer.contentsScale;
|
||||
f32 scale = surface->mtlLayer.contentsScale;
|
||||
CGSize drawableSize = (CGSize){.width = frame.w * scale, .height = frame.h * scale};
|
||||
surface->metalLayer.drawableSize = drawableSize;
|
||||
surface->mtlLayer.drawableSize = drawableSize;
|
||||
}
|
||||
}
|
||||
|
||||
mp_rect mg_metal_surface_get_frame(mg_surface_data* interface)
|
||||
mp_rect mg_mtl_surface_get_frame(mg_surface_data* interface)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -161,31 +161,31 @@ mp_rect mg_metal_surface_get_frame(mg_surface_data* interface)
|
|||
}
|
||||
}
|
||||
|
||||
void mg_metal_surface_set_hidden(mg_surface_data* interface, bool hidden)
|
||||
void mg_mtl_surface_set_hidden(mg_surface_data* interface, bool hidden)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
@autoreleasepool
|
||||
{
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
[surface->metalLayer setHidden:hidden];
|
||||
[surface->mtlLayer setHidden:hidden];
|
||||
[CATransaction commit];
|
||||
}
|
||||
}
|
||||
|
||||
bool mg_metal_surface_get_hidden(mg_surface_data* interface)
|
||||
bool mg_mtl_surface_get_hidden(mg_surface_data* interface)
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)interface;
|
||||
@autoreleasepool
|
||||
{
|
||||
return([surface->metalLayer isHidden]);
|
||||
return([surface->mtlLayer isHidden]);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO fix that according to real scaling, depending on the monitor settings
|
||||
static const f32 MG_METAL_SURFACE_CONTENTS_SCALING = 2;
|
||||
static const f32 MG_MTL_SURFACE_CONTENTS_SCALING = 2;
|
||||
|
||||
mg_surface mg_metal_surface_create_for_window(mp_window window)
|
||||
mg_surface mg_mtl_surface_create_for_window(mp_window window)
|
||||
{
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(!windowData)
|
||||
|
@ -194,18 +194,18 @@ mg_surface mg_metal_surface_create_for_window(mp_window window)
|
|||
}
|
||||
else
|
||||
{
|
||||
mg_metal_surface* surface = (mg_metal_surface*)malloc(sizeof(mg_metal_surface));
|
||||
mg_mtl_surface* surface = (mg_mtl_surface*)malloc(sizeof(mg_mtl_surface));
|
||||
|
||||
//NOTE(martin): setup interface functions
|
||||
surface->interface.backend = MG_BACKEND_METAL;
|
||||
surface->interface.destroy = mg_metal_surface_destroy;
|
||||
surface->interface.prepare = mg_metal_surface_prepare;
|
||||
surface->interface.present = mg_metal_surface_present;
|
||||
surface->interface.swapInterval = mg_metal_surface_swap_interval;
|
||||
surface->interface.getFrame = mg_metal_surface_get_frame;
|
||||
surface->interface.setFrame = mg_metal_surface_set_frame;
|
||||
surface->interface.getHidden = mg_metal_surface_get_hidden;
|
||||
surface->interface.setHidden = mg_metal_surface_set_hidden;
|
||||
surface->interface.backend = MG_BACKEND_MTL;
|
||||
surface->interface.destroy = mg_mtl_surface_destroy;
|
||||
surface->interface.prepare = mg_mtl_surface_prepare;
|
||||
surface->interface.present = mg_mtl_surface_present;
|
||||
surface->interface.swapInterval = mg_mtl_surface_swap_interval;
|
||||
surface->interface.getFrame = mg_mtl_surface_get_frame;
|
||||
surface->interface.setFrame = mg_mtl_surface_set_frame;
|
||||
surface->interface.getHidden = mg_mtl_surface_get_hidden;
|
||||
surface->interface.setHidden = mg_mtl_surface_set_hidden;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
|
@ -215,37 +215,37 @@ mg_surface mg_metal_surface_create_for_window(mp_window window)
|
|||
|
||||
[[windowData->osx.nsWindow contentView] addSubview: surface->view];
|
||||
|
||||
surface->drawableSemaphore = dispatch_semaphore_create(MP_METAL_MAX_DRAWABLES_IN_FLIGHT);
|
||||
surface->drawableSemaphore = dispatch_semaphore_create(MP_MTL_MAX_DRAWABLES_IN_FLIGHT);
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//NOTE(martin): create a metal device and a metal layer and
|
||||
//NOTE(martin): create a mtl device and a mtl layer and
|
||||
//-----------------------------------------------------------
|
||||
surface->device = MTLCreateSystemDefaultDevice();
|
||||
[surface->device retain];
|
||||
surface->metalLayer = [CAMetalLayer layer];
|
||||
[surface->metalLayer retain];
|
||||
[surface->metalLayer setOpaque:NO];
|
||||
surface->mtlLayer = [CAMtlLayer layer];
|
||||
[surface->mtlLayer retain];
|
||||
[surface->mtlLayer setOpaque:NO];
|
||||
|
||||
surface->metalLayer.device = surface->device;
|
||||
surface->mtlLayer.device = surface->device;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//NOTE(martin): set the size and scaling
|
||||
//-----------------------------------------------------------
|
||||
CGSize size = surface->view.bounds.size;
|
||||
size.width *= MG_METAL_SURFACE_CONTENTS_SCALING;
|
||||
size.height *= MG_METAL_SURFACE_CONTENTS_SCALING;
|
||||
surface->metalLayer.drawableSize = size;
|
||||
surface->metalLayer.contentsScale = MG_METAL_SURFACE_CONTENTS_SCALING;
|
||||
size.width *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||
size.height *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||
surface->mtlLayer.drawableSize = size;
|
||||
surface->mtlLayer.contentsScale = MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||
|
||||
surface->metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
|
||||
surface->view.wantsLayer = YES;
|
||||
surface->view.layer = surface->metalLayer;
|
||||
surface->view.layer = surface->mtlLayer;
|
||||
|
||||
//NOTE(martin): handling resizing
|
||||
surface->view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
|
||||
surface->metalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
|
||||
surface->metalLayer.needsDisplayOnBoundsChange = YES;
|
||||
surface->mtlLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
|
||||
surface->mtlLayer.needsDisplayOnBoundsChange = YES;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//NOTE(martin): create a command queue
|
||||
|
@ -263,13 +263,13 @@ mg_surface mg_metal_surface_create_for_window(mp_window window)
|
|||
}
|
||||
}
|
||||
|
||||
void* mg_metal_surface_layer(mg_surface surface)
|
||||
void* mg_mtl_surface_layer(mg_surface surface)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_METAL)
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_MTL)
|
||||
{
|
||||
mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData;
|
||||
return(metalSurface->metalLayer);
|
||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
||||
return(mtlSurface->mtlLayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -277,13 +277,13 @@ void* mg_metal_surface_layer(mg_surface surface)
|
|||
}
|
||||
}
|
||||
|
||||
void* mg_metal_surface_drawable(mg_surface surface)
|
||||
void* mg_mtl_surface_drawable(mg_surface surface)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_METAL)
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_MTL)
|
||||
{
|
||||
mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData;
|
||||
return(metalSurface->drawable);
|
||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
||||
return(mtlSurface->drawable);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -291,13 +291,13 @@ void* mg_metal_surface_drawable(mg_surface surface)
|
|||
}
|
||||
}
|
||||
|
||||
void* mg_metal_surface_command_buffer(mg_surface surface)
|
||||
void* mg_mtl_surface_command_buffer(mg_surface surface)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_METAL)
|
||||
if(surfaceData && surfaceData->backend == MG_BACKEND_MTL)
|
||||
{
|
||||
mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData;
|
||||
return(metalSurface->commandBuffer);
|
||||
mg_mtl_surface* mtlSurface = (mg_mtl_surface*)surfaceData;
|
||||
return(mtlSurface->commandBuffer);
|
||||
}
|
||||
else
|
||||
{
|
|
@ -1,32 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: osx_gles_surface.cpp
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 18/08/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
//#include<Cocoa/Cocoa.h>
|
||||
//#include <Foundation/Foundation.h>
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
#include<GLES3/gl3.h>
|
||||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#include<EGL/egl.h>
|
||||
#include<EGL/eglext.h>
|
||||
|
||||
#include"graphics_internal.h"
|
||||
|
||||
typedef struct mg_gles_surface
|
||||
{
|
||||
mg_surface_data interface;
|
||||
|
||||
NSView* view;
|
||||
CALayer* layer;
|
||||
EGLDisplay eglDisplay;
|
||||
EGLConfig eglConfig;
|
||||
EGLContext eglContext;
|
||||
EGLSurface eglSurface;
|
||||
EGLint numConfigs;
|
||||
|
||||
} mg_gles_surface;
|
|
@ -1,184 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: osx_gles_surface.cpp
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 18/08/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
//#include<Cocoa/Cocoa.h>
|
||||
//#include <Foundation/Foundation.h>
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
#include<GLES3/gl3.h>
|
||||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#include<EGL/egl.h>
|
||||
#include<EGL/eglext.h>
|
||||
|
||||
#include"graphics_internal.h"
|
||||
#include"osx_gles_surface.h"
|
||||
|
||||
|
||||
void mg_gles_surface_destroy(mg_surface_data* interface)
|
||||
{
|
||||
//////////////////////////////////////////////////
|
||||
//TODO
|
||||
//////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
void mg_gles_surface_prepare(mg_surface_data* interface)
|
||||
{
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
||||
}
|
||||
|
||||
void mg_gles_surface_present(mg_surface_data* interface)
|
||||
{
|
||||
|
||||
//TODO: eglSwapBuffers seem to never block in macOS (ie eglSwapInterval doesn't seem to have any effect)
|
||||
// We need to use a CVDisplayLink to time this if we want surface present to block
|
||||
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
|
||||
}
|
||||
|
||||
void mg_gles_surface_set_frame(mg_surface_data* interface, mp_rect frame)
|
||||
{
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
f32 scale = surface->layer.contentsScale;
|
||||
CGRect bounds = (CGRect){{frame.x * scale, frame.y * scale}, {.width = frame.w*scale, .height = frame.h*scale}};
|
||||
[surface->layer setBounds: bounds];
|
||||
}
|
||||
|
||||
mp_rect mg_gles_surface_get_frame(mg_surface_data* interface)
|
||||
{
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
f32 scale = surface->layer.contentsScale;
|
||||
CGRect bounds = [surface->layer bounds];
|
||||
mp_rect rect = {bounds.origin.x / scale, bounds.origin.y / scale, bounds.size.width / scale, bounds.size.height / scale};
|
||||
return(rect);
|
||||
}
|
||||
|
||||
|
||||
void mg_gles_surface_set_hidden(mg_surface_data* interface, bool hidden)
|
||||
{
|
||||
//TODO: doesn't make sense for an offscreen surface?
|
||||
}
|
||||
|
||||
bool mg_gles_surface_get_hidden(mg_surface_data* interface)
|
||||
{
|
||||
//TODO: doesn't make sense for an offscreen surface?
|
||||
return(false);
|
||||
}
|
||||
|
||||
vec2 mg_gles_surface_get_size(mg_surface_data* interface)
|
||||
{
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
CGRect bounds = [surface->layer bounds];
|
||||
f32 scale = surface->layer.contentsScale;
|
||||
vec2 res = {bounds.size.width/scale, bounds.size.height/scale};
|
||||
return(res);
|
||||
}
|
||||
|
||||
mg_surface mg_gles_surface_create_with_view(u32 width, u32 height, NSView* view)
|
||||
{
|
||||
mg_gles_surface* surface = malloc_type(mg_gles_surface);
|
||||
memset(surface, 0, sizeof(mg_gles_surface));
|
||||
|
||||
surface->interface.backend = MG_BACKEND_GLES;
|
||||
surface->interface.destroy = mg_gles_surface_destroy;
|
||||
surface->interface.prepare = mg_gles_surface_prepare;
|
||||
surface->interface.present = mg_gles_surface_present;
|
||||
surface->interface.getFrame = mg_gles_surface_get_frame;
|
||||
surface->interface.setFrame = mg_gles_surface_set_frame;
|
||||
surface->interface.getHidden = mg_gles_surface_get_hidden;
|
||||
surface->interface.setHidden = mg_gles_surface_set_hidden;
|
||||
|
||||
surface->view = view;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
surface->layer = [[CALayer alloc] init];
|
||||
[surface->layer retain];
|
||||
[surface->layer setBounds:CGRectMake(0, 0, width, height)];
|
||||
|
||||
if(surface->view)
|
||||
{
|
||||
[surface->view setWantsLayer: YES];
|
||||
surface->view.layer = surface->layer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EGLAttrib displayAttribs[] = {
|
||||
//NOTE: we need to explicitly set EGL_PLATFORM_ANGLE_TYPE_ANGLE to EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, because
|
||||
// EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE defaults to using CGL, and eglSetSwapInterval is broken for this backend
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
|
||||
EGL_NONE};
|
||||
|
||||
surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs);
|
||||
eglInitialize(surface->eglDisplay, NULL, NULL);
|
||||
|
||||
EGLint const configAttributes[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_SAMPLE_BUFFERS, 0,
|
||||
EGL_SAMPLES, EGL_DONT_CARE,
|
||||
EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
|
||||
EGL_NONE };
|
||||
|
||||
eglChooseConfig(surface->eglDisplay, configAttributes, &surface->eglConfig, 1, &surface->numConfigs);
|
||||
|
||||
EGLint const surfaceAttributes[] = {EGL_NONE};
|
||||
surface->eglSurface = eglCreateWindowSurface(surface->eglDisplay, surface->eglConfig, surface->layer, surfaceAttributes);
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
EGLint contextAttributes[] = {
|
||||
EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
|
||||
EGL_CONTEXT_MINOR_VERSION_KHR, 0, //NOTE: Angle can't create a GLES 3.1 context on macOS
|
||||
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE,
|
||||
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE,
|
||||
EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE,
|
||||
EGL_NONE};
|
||||
|
||||
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
|
||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
||||
|
||||
eglSwapInterval(surface->eglDisplay, 1);
|
||||
|
||||
mg_surface handle = mg_surface_alloc_handle((mg_surface_data*)surface);
|
||||
return(handle);
|
||||
}
|
||||
|
||||
mg_surface mg_gles_surface_create_offscreen(u32 width, u32 height)
|
||||
{
|
||||
return(mg_gles_surface_create_with_view(width, height, 0));
|
||||
}
|
||||
|
||||
mg_surface mg_gles_surface_create_for_window(mp_window window)
|
||||
{
|
||||
mg_surface res = mg_surface_nil();
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
|
||||
NSView* view = [[NSView alloc] initWithFrame: frame];
|
||||
|
||||
res = mg_gles_surface_create_with_view(frame.size.width, frame.size.height, view);
|
||||
|
||||
if(!mg_surface_is_nil(res))
|
||||
{
|
||||
[[windowData->osx.nsWindow contentView] addSubview: view];
|
||||
}
|
||||
}
|
||||
}
|
||||
return(res);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: win32_gl_loader.h
|
||||
* @file: wgl_loader.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 01/08/2022
|
||||
* @revision:
|
||||
|
@ -56,7 +56,7 @@
|
|||
GL_PROC(GLUNMAPBUFFER, glUnmapBuffer)
|
||||
|
||||
|
||||
#ifdef WIN32_GL_LOADER_API
|
||||
#ifdef WGL_LOADER_API
|
||||
//NOTE: pointer declarations
|
||||
#define GL_PROC(type, name) extern _cat3_(PFN, type, PROC) name;
|
||||
GL_PROC_LIST
|
||||
|
@ -64,7 +64,7 @@
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32_GL_LOADER_IMPL
|
||||
#ifdef WGL_LOADER_IMPL
|
||||
#define GL_PROC(type, name) _cat3_(PFN, type, PROC) name = 0;
|
||||
GL_PROC_LIST
|
||||
#undef GL_PROC
|
|
@ -1,18 +1,18 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: win32_gl_surface.c
|
||||
* @file: wgl_surface.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 01/08/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#define WIN32_GL_LOADER_IMPL
|
||||
#include"win32_gl_loader.h"
|
||||
#define WGL_LOADER_IMPL
|
||||
#include"wgl_loader.h"
|
||||
#include"win32_app.h"
|
||||
|
||||
#include"graphics_internal.h"
|
||||
|
||||
typedef struct mg_gl_surface
|
||||
typedef struct mg_wgl_surface
|
||||
{
|
||||
mg_surface_data interface;
|
||||
|
||||
|
@ -21,11 +21,11 @@ typedef struct mg_gl_surface
|
|||
HGLRC glContext;
|
||||
vec2 contentsScaling;
|
||||
|
||||
} mg_gl_surface;
|
||||
} mg_wgl_surface;
|
||||
|
||||
void mg_gl_surface_destroy(mg_surface_data* interface)
|
||||
void mg_wgl_surface_destroy(mg_surface_data* interface)
|
||||
{
|
||||
mg_gl_surface* surface = (mg_gl_surface*)interface;
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
|
||||
if(surface->glContext == wglGetCurrentContext())
|
||||
{
|
||||
|
@ -35,34 +35,34 @@ void mg_gl_surface_destroy(mg_surface_data* interface)
|
|||
free(surface);
|
||||
}
|
||||
|
||||
void mg_gl_surface_prepare(mg_surface_data* interface)
|
||||
void mg_wgl_surface_prepare(mg_surface_data* interface)
|
||||
{
|
||||
mg_gl_surface* surface = (mg_gl_surface*)interface;
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
|
||||
wglMakeCurrent(surface->hDC, surface->glContext);
|
||||
}
|
||||
|
||||
void mg_gl_surface_present(mg_surface_data* interface)
|
||||
void mg_wgl_surface_present(mg_surface_data* interface)
|
||||
{
|
||||
mg_gl_surface* surface = (mg_gl_surface*)interface;
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
SwapBuffers(surface->hDC);
|
||||
}
|
||||
|
||||
void mg_gl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
void mg_wgl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
{
|
||||
mg_gl_surface* surface = (mg_gl_surface*)interface;
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
wglSwapIntervalEXT(swap);
|
||||
}
|
||||
|
||||
vec2 mg_gl_contents_scaling(mg_surface_data* interface)
|
||||
vec2 mg_wgl_contents_scaling(mg_surface_data* interface)
|
||||
{
|
||||
mg_gl_surface* surface = (mg_gl_surface*)interface;
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
return(surface->contentsScaling);
|
||||
}
|
||||
|
||||
mp_rect mg_gl_surface_get_frame(mg_surface_data* interface)
|
||||
mp_rect mg_wgl_surface_get_frame(mg_surface_data* interface)
|
||||
{
|
||||
mg_gl_surface* surface = (mg_gl_surface*)interface;
|
||||
mg_wgl_surface* surface = (mg_wgl_surface*)interface;
|
||||
RECT rect = {0};
|
||||
GetClientRect(surface->hWnd, &rect);
|
||||
|
||||
|
@ -75,7 +75,7 @@ mp_rect mg_gl_surface_get_frame(mg_surface_data* interface)
|
|||
return(res);
|
||||
}
|
||||
|
||||
mg_surface mg_gl_surface_create_for_window(mp_window window)
|
||||
mg_surface mg_wgl_surface_create_for_window(mp_window window)
|
||||
{
|
||||
mg_surface surfaceHandle = mg_surface_nil();
|
||||
|
||||
|
@ -211,14 +211,14 @@ mg_surface mg_gl_surface_create_for_window(mp_window window)
|
|||
wglSwapIntervalEXT(1);
|
||||
|
||||
//TODO save important info in surface_data and return a handle
|
||||
mg_gl_surface* surface = malloc_type(mg_gl_surface);
|
||||
mg_wgl_surface* surface = malloc_type(mg_wgl_surface);
|
||||
surface->interface.backend = MG_BACKEND_GL;
|
||||
surface->interface.destroy = mg_gl_surface_destroy;
|
||||
surface->interface.prepare = mg_gl_surface_prepare;
|
||||
surface->interface.present = mg_gl_surface_present;
|
||||
surface->interface.swapInterval = mg_gl_surface_swap_interval;
|
||||
surface->interface.contentsScaling = mg_gl_contents_scaling;
|
||||
surface->interface.getFrame = mg_gl_surface_get_frame;
|
||||
surface->interface.destroy = mg_wgl_surface_destroy;
|
||||
surface->interface.prepare = mg_wgl_surface_prepare;
|
||||
surface->interface.present = mg_wgl_surface_present;
|
||||
surface->interface.swapInterval = mg_wgl_surface_swap_interval;
|
||||
surface->interface.contentsScaling = mg_wgl_contents_scaling;
|
||||
surface->interface.getFrame = mg_wgl_surface_get_frame;
|
||||
|
||||
//TODO: get/set frame/hidden
|
||||
surface->hWnd = windowData->win32.hWnd;
|
|
@ -1,16 +1,16 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: win32_gl_surface.c
|
||||
* @file: wgl_surface.c
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 28/01/2023
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __WIN32_GL_SURFACE_H_
|
||||
#define __WIN32_GL_SURFACE_H_
|
||||
#ifndef __WGL_SURFACE_H_
|
||||
#define __WGL_SURFACE_H_
|
||||
|
||||
#include"graphics.h"
|
||||
|
||||
mg_surface mg_gl_surface_create_for_window(mp_window window);
|
||||
mg_surface mg_wgl_surface_create_for_window(mp_window window);
|
||||
|
||||
#endif // __WIN32_GL_SURFACE_H_
|
|
@ -1,133 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: osx_gles_surface.cpp
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 18/08/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#include<GLES3/gl31.h>
|
||||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#include<EGL/egl.h>
|
||||
#include<EGL/eglext.h>
|
||||
|
||||
#include"graphics_internal.h"
|
||||
|
||||
typedef struct mg_gles_surface
|
||||
{
|
||||
mg_surface_data interface;
|
||||
|
||||
HWND hWnd;
|
||||
|
||||
EGLDisplay eglDisplay;
|
||||
EGLConfig eglConfig;
|
||||
EGLContext eglContext;
|
||||
EGLSurface eglSurface;
|
||||
|
||||
} mg_gles_surface;
|
||||
|
||||
void mg_gles_surface_destroy(mg_surface_data* interface)
|
||||
{
|
||||
//////////////////////////////////////////////////
|
||||
//TODO
|
||||
//////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
void mg_gles_surface_prepare(mg_surface_data* interface)
|
||||
{
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
||||
}
|
||||
|
||||
void mg_gles_surface_present(mg_surface_data* interface)
|
||||
{
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
|
||||
}
|
||||
|
||||
/*
|
||||
void mg_gles_surface_set_frame(mg_surface_data* interface, mp_rect frame);
|
||||
|
||||
void mg_gles_surface_set_hidden(mg_surface_data* interface, bool hidden);
|
||||
bool mg_gles_surface_get_hidden(mg_surface_data* interface);
|
||||
*/
|
||||
|
||||
mp_rect mg_gles_surface_get_frame(mg_surface_data* interface)
|
||||
{
|
||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||
RECT rect = {0};
|
||||
GetClientRect(surface->hWnd, &rect);
|
||||
|
||||
mp_rect res = {rect.left, rect.bottom, rect.right - rect.left, rect.bottom - rect.top};
|
||||
return(res);
|
||||
}
|
||||
|
||||
mg_surface mg_gles_surface_create_for_window(mp_window window)
|
||||
{
|
||||
mg_surface res = mg_surface_nil();
|
||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||
if(windowData)
|
||||
{
|
||||
mg_gles_surface* surface = malloc_type(mg_gles_surface);
|
||||
memset(surface, 0, sizeof(mg_gles_surface));
|
||||
|
||||
surface->interface.backend = MG_BACKEND_GLES;
|
||||
surface->interface.destroy = mg_gles_surface_destroy;
|
||||
surface->interface.prepare = mg_gles_surface_prepare;
|
||||
surface->interface.present = mg_gles_surface_present;
|
||||
surface->interface.getFrame = mg_gles_surface_get_frame;
|
||||
/*TODO
|
||||
surface->interface.setFrame = mg_gles_surface_set_frame;
|
||||
surface->interface.getHidden = mg_gles_surface_get_hidden;
|
||||
surface->interface.setHidden = mg_gles_surface_set_hidden;
|
||||
*/
|
||||
|
||||
surface->hWnd = windowData->win32.hWnd;
|
||||
|
||||
EGLAttrib displayAttribs[] = {
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
|
||||
EGL_NONE};
|
||||
|
||||
surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs);
|
||||
eglInitialize(surface->eglDisplay, NULL, NULL);
|
||||
|
||||
EGLint const configAttributes[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_SAMPLE_BUFFERS, 0,
|
||||
EGL_SAMPLES, EGL_DONT_CARE,
|
||||
EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
|
||||
EGL_NONE };
|
||||
|
||||
int numConfigs = 0;
|
||||
eglChooseConfig(surface->eglDisplay, configAttributes, &surface->eglConfig, 1, &numConfigs);
|
||||
|
||||
EGLint const surfaceAttributes[] = {EGL_NONE};
|
||||
surface->eglSurface = eglCreateWindowSurface(surface->eglDisplay, surface->eglConfig, surface->hWnd, surfaceAttributes);
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
EGLint contextAttributes[] = {
|
||||
EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
|
||||
EGL_CONTEXT_MINOR_VERSION_KHR, 1,
|
||||
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE,
|
||||
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE,
|
||||
EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE,
|
||||
EGL_NONE};
|
||||
|
||||
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
|
||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
||||
|
||||
//TODO: reactivate this when finished testing!
|
||||
// eglSwapInterval(surface->eglDisplay, 1);
|
||||
eglSwapInterval(surface->eglDisplay, 0);
|
||||
|
||||
res = mg_surface_alloc_handle((mg_surface_data*)surface);
|
||||
}
|
||||
return(res);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: win32_gles_surface.h
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 28/01/2023
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#ifndef __WIN32_GLES_SURFACE_H_
|
||||
#define __WIN32_GLES_SURFACE_H_
|
||||
|
||||
#include"graphics.h"
|
||||
#include"mp_app.h"
|
||||
|
||||
mg_surface mg_gles_surface_create_for_window(mp_window window);
|
||||
|
||||
#endif // __WIN32_GLES_SURFACE_H_
|
12
todo.txt
12
todo.txt
|
@ -5,6 +5,13 @@ Overview
|
|||
[.] Clean+Fixes of canvas code and examples
|
||||
|
||||
[>] Make backend selection easier
|
||||
[x] rename backend-specific files with api prefix (e.g. egl_, nsgl_, wgl_, mtl_, ...)
|
||||
[x] option macros to select surface/canvas backends to compile into milepost lib
|
||||
[/] option macros to select backend-specific APIs to include when building an app
|
||||
[x] surface/canvas functions that take a backend id
|
||||
[x] feature-detection functions to know what surface/canvas backends are available at run-time
|
||||
[>] drop the "mg_" prefix for internal functions (and declare them static)
|
||||
[>] write doc about these options
|
||||
|
||||
[ ] Image API and backend
|
||||
[ ] Build image atlas on top
|
||||
|
@ -17,6 +24,11 @@ Overview
|
|||
|
||||
[ ] Delegated drawing API+Impl
|
||||
|
||||
[ ] Make building apps simpler
|
||||
[ ] single include path
|
||||
[ ] script for embedding dependencies / create app bundle
|
||||
|
||||
|
||||
Clean+Fixes
|
||||
-----------
|
||||
|
||||
|
|
|
@ -94,3 +94,20 @@ Quick measurement on perf_text.exe
|
|||
-> May be worth it to try persistently mapped buffers later.
|
||||
|
||||
* Splitting vertex data and shape data (using glBufferData) --> ~10ms
|
||||
|
||||
|
||||
Backend Selection
|
||||
-----------------
|
||||
|
||||
* We need define macros to select which backends are compiled into milepost.lib
|
||||
-> define default backends and allow override with user compile defines
|
||||
|
||||
* We also need define macros to select which backend-specific functions and/or graphics APIs to include when building an app with milepost (e.g.\ include opengl headers or not, etc.).
|
||||
|
||||
* For now, we intend to statically link milepost.lib (or dynamically load to an embedded dll), so at application compile time the supported backends are known and calling a backend-specific function for a backend that has not been compiled in milepost results in a link error. (No need to defines for that)
|
||||
|
||||
* However, if we want to provide a nice abstraction for creation function, this means it is possible for user to pass a backend that does not exists in the lib (resulting in a runtime error). It would be nice to have some way to runtime check which backends are available. That can be a function compiled in the lib.
|
||||
|
||||
* We also might want to access backend-specific functions in the app, so we need to include those conditionally.
|
||||
|
||||
* We also might want to include graphics API, eg OpenGL, in a uniform way. -> See later how we manage GLES/GL co-existence
|
||||
|
|
Loading…
Reference in New Issue