splitting graphics_surface and graphics_common in order to isolate surface dispatch stuff from orca apps
This commit is contained in:
parent
346979a21a
commit
ca1caf8537
|
@ -1,6 +1,6 @@
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
*
|
*
|
||||||
* @file: graphics.c
|
* @file: graphics_common.c
|
||||||
* @author: Martin Fouilleul
|
* @author: Martin Fouilleul
|
||||||
* @date: 23/01/2023
|
* @date: 23/01/2023
|
||||||
* @revision:
|
* @revision:
|
||||||
|
@ -62,7 +62,6 @@ typedef struct mg_font_data
|
||||||
} mg_font_data;
|
} mg_font_data;
|
||||||
|
|
||||||
typedef struct mg_canvas_data mg_canvas_data;
|
typedef struct mg_canvas_data mg_canvas_data;
|
||||||
typedef struct mg_image_data mg_image_data;
|
|
||||||
|
|
||||||
typedef enum mg_handle_kind
|
typedef enum mg_handle_kind
|
||||||
{
|
{
|
||||||
|
@ -123,18 +122,10 @@ typedef struct mg_canvas_data
|
||||||
|
|
||||||
//NOTE: these are used at render time
|
//NOTE: these are used at render time
|
||||||
mg_color clearColor;
|
mg_color clearColor;
|
||||||
mp_rect clip;
|
|
||||||
mg_mat2x3 transform;
|
|
||||||
mg_image image;
|
|
||||||
mp_rect srcRegion;
|
|
||||||
|
|
||||||
vec4 shapeExtents;
|
vec4 shapeExtents;
|
||||||
vec4 shapeScreenExtents;
|
vec4 shapeScreenExtents;
|
||||||
u32 nextShapeIndex;
|
|
||||||
u32 vertexCount;
|
|
||||||
u32 indexCount;
|
|
||||||
|
|
||||||
int splitCount;
|
|
||||||
} mg_canvas_data;
|
} mg_canvas_data;
|
||||||
|
|
||||||
static mg_data __mgData = {0};
|
static mg_data __mgData = {0};
|
||||||
|
@ -221,347 +212,6 @@ void* mg_data_from_handle(mg_handle_kind kind, u64 h)
|
||||||
return(data);
|
return(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
// typed handles functions
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
mg_surface mg_surface_handle_alloc(mg_surface_data* surface)
|
|
||||||
{
|
|
||||||
mg_surface handle = {.h = mg_handle_alloc(MG_HANDLE_SURFACE, (void*)surface) };
|
|
||||||
return(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_surface_data* mg_surface_data_from_handle(mg_surface handle)
|
|
||||||
{
|
|
||||||
mg_surface_data* data = mg_data_from_handle(MG_HANDLE_SURFACE, handle.h);
|
|
||||||
return(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_canvas mg_canvas_handle_alloc(mg_canvas_data* canvas)
|
|
||||||
{
|
|
||||||
mg_canvas handle = {.h = mg_handle_alloc(MG_HANDLE_CANVAS, (void*)canvas) };
|
|
||||||
return(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_canvas_data* mg_canvas_data_from_handle(mg_canvas handle)
|
|
||||||
{
|
|
||||||
mg_canvas_data* data = mg_data_from_handle(MG_HANDLE_CANVAS, handle.h);
|
|
||||||
return(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_font mg_font_handle_alloc(mg_font_data* font)
|
|
||||||
{
|
|
||||||
mg_font handle = {.h = mg_handle_alloc(MG_HANDLE_FONT, (void*)font) };
|
|
||||||
return(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_font_data* mg_font_data_from_handle(mg_font handle)
|
|
||||||
{
|
|
||||||
mg_font_data* data = mg_data_from_handle(MG_HANDLE_FONT, handle.h);
|
|
||||||
return(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_image mg_image_handle_alloc(mg_image_data* image)
|
|
||||||
{
|
|
||||||
mg_image handle = {.h = mg_handle_alloc(MG_HANDLE_IMAGE, (void*)image) };
|
|
||||||
return(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_image_data* mg_image_data_from_handle(mg_image handle)
|
|
||||||
{
|
|
||||||
mg_image_data* data = mg_data_from_handle(MG_HANDLE_IMAGE, handle.h);
|
|
||||||
return(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
// surface API
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
|
|
||||||
#if MG_COMPILE_GL
|
|
||||||
#if PLATFORM_WINDOWS
|
|
||||||
#include"wgl_surface.h"
|
|
||||||
#define gl_surface_create_for_window mg_wgl_surface_create_for_window
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
|
||||||
#include"egl_surface.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_METAL
|
|
||||||
#include"mtl_surface.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
|
||||||
#if PLATFORM_MACOS
|
|
||||||
mg_surface_data* mtl_canvas_surface_create_for_window(mp_window window);
|
|
||||||
#elif PLATFORM_WINDOWS
|
|
||||||
//TODO
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool mg_is_surface_backend_available(mg_surface_api api)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
switch(api)
|
|
||||||
{
|
|
||||||
#if MG_COMPILE_METAL
|
|
||||||
case MG_METAL:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_GL
|
|
||||||
case MG_GL:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
|
||||||
case MG_GLES:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
|
||||||
case MG_CANVAS:
|
|
||||||
#endif
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_surface mg_surface_nil() { return((mg_surface){.h = 0}); }
|
|
||||||
bool mg_surface_is_nil(mg_surface surface) { return(surface.h == 0); }
|
|
||||||
|
|
||||||
mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api)
|
|
||||||
{
|
|
||||||
if(__mgData.init)
|
|
||||||
{
|
|
||||||
mg_init();
|
|
||||||
}
|
|
||||||
mg_surface surfaceHandle = mg_surface_nil();
|
|
||||||
mg_surface_data* surface = 0;
|
|
||||||
|
|
||||||
switch(api)
|
|
||||||
{
|
|
||||||
#if MG_COMPILE_GL
|
|
||||||
case MG_GL:
|
|
||||||
surface = gl_surface_create_for_window(window);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_GLES
|
|
||||||
case MG_GLES:
|
|
||||||
surface = mg_egl_surface_create_for_window(window);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_METAL
|
|
||||||
case MG_METAL:
|
|
||||||
surface = mg_mtl_surface_create_for_window(window);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_COMPILE_CANVAS
|
|
||||||
case MG_CANVAS:
|
|
||||||
|
|
||||||
#if PLATFORM_MACOS
|
|
||||||
surface = mtl_canvas_surface_create_for_window(window);
|
|
||||||
#elif PLATFORM_WINDOWS
|
|
||||||
surface = gl_canvas_surface_create_for_window(window);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(surface)
|
|
||||||
{
|
|
||||||
surfaceHandle = mg_surface_handle_alloc(surface);
|
|
||||||
}
|
|
||||||
return(surfaceHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api)
|
|
||||||
{
|
|
||||||
if(__mgData.init)
|
|
||||||
{
|
|
||||||
mg_init();
|
|
||||||
}
|
|
||||||
mg_surface surfaceHandle = mg_surface_nil();
|
|
||||||
mg_surface_data* surface = 0;
|
|
||||||
|
|
||||||
switch(api)
|
|
||||||
{
|
|
||||||
#if MG_COMPILE_GLES
|
|
||||||
case MG_GLES:
|
|
||||||
surface = mg_egl_surface_create_remote(width, height);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(surface)
|
|
||||||
{
|
|
||||||
surfaceHandle = mg_surface_handle_alloc(surface);
|
|
||||||
}
|
|
||||||
return(surfaceHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_surface mg_surface_create_host(mp_window window)
|
|
||||||
{
|
|
||||||
if(__mgData.init)
|
|
||||||
{
|
|
||||||
mg_init();
|
|
||||||
}
|
|
||||||
mg_surface handle = mg_surface_nil();
|
|
||||||
mg_surface_data* surface = 0;
|
|
||||||
#if PLATFORM_MACOS
|
|
||||||
surface = mg_osx_surface_create_host(window);
|
|
||||||
#elif PLATFORM_WINDOWS
|
|
||||||
surface = mg_win32_surface_create_host(window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(surface)
|
|
||||||
{
|
|
||||||
handle = mg_surface_handle_alloc(surface);
|
|
||||||
}
|
|
||||||
return(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_surface_destroy(mg_surface handle)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
|
||||||
if(surface)
|
|
||||||
{
|
|
||||||
if(surface->backend && surface->backend->destroy)
|
|
||||||
{
|
|
||||||
surface->backend->destroy(surface->backend);
|
|
||||||
}
|
|
||||||
surface->destroy(surface);
|
|
||||||
mg_handle_recycle(handle.h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_surface_prepare(mg_surface surface)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->prepare)
|
|
||||||
{
|
|
||||||
surfaceData->prepare(surfaceData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_surface_present(mg_surface surface)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->present)
|
|
||||||
{
|
|
||||||
surfaceData->present(surfaceData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_surface_swap_interval(mg_surface surface, int swap)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->swapInterval)
|
|
||||||
{
|
|
||||||
surfaceData->swapInterval(surfaceData, swap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 mg_surface_contents_scaling(mg_surface surface)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
vec2 scaling = {1, 1};
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->contentsScaling)
|
|
||||||
{
|
|
||||||
scaling = surfaceData->contentsScaling(surfaceData);
|
|
||||||
}
|
|
||||||
return(scaling);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mg_surface_set_frame(mg_surface surface, mp_rect frame)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->setFrame)
|
|
||||||
{
|
|
||||||
surfaceData->setFrame(surfaceData, frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_rect mg_surface_get_frame(mg_surface surface)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
mp_rect res = {0};
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->getFrame)
|
|
||||||
{
|
|
||||||
res = surfaceData->getFrame(surfaceData);
|
|
||||||
}
|
|
||||||
return(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_surface_set_hidden(mg_surface surface, bool hidden)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->setHidden)
|
|
||||||
{
|
|
||||||
surfaceData->setHidden(surfaceData, hidden);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mg_surface_get_hidden(mg_surface surface)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgData.init);
|
|
||||||
bool res = false;
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->getHidden)
|
|
||||||
{
|
|
||||||
res = surfaceData->getHidden(surfaceData);
|
|
||||||
}
|
|
||||||
return(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* mg_surface_native_layer(mg_surface surface)
|
|
||||||
{
|
|
||||||
void* res = 0;
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->nativeLayer)
|
|
||||||
{
|
|
||||||
res = surfaceData->nativeLayer(surfaceData);
|
|
||||||
}
|
|
||||||
return(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_surface_id mg_surface_remote_id(mg_surface handle)
|
|
||||||
{
|
|
||||||
mg_surface_id remoteId = 0;
|
|
||||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
|
||||||
if(surface && surface->remoteID)
|
|
||||||
{
|
|
||||||
remoteId = surface->remoteID(surface);
|
|
||||||
}
|
|
||||||
return(remoteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_surface_host_connect(mg_surface handle, mg_surface_id remoteID)
|
|
||||||
{
|
|
||||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
|
||||||
if(surface && surface->hostConnect)
|
|
||||||
{
|
|
||||||
surface->hostConnect(surface, remoteID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): graphics canvas internal
|
//NOTE(martin): graphics canvas internal
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
@ -740,6 +390,18 @@ void mg_path_push_element(mg_canvas_data* canvas, mg_path_elt elt)
|
||||||
mg_font mg_font_nil() { return((mg_font){.h = 0}); }
|
mg_font mg_font_nil() { return((mg_font){.h = 0}); }
|
||||||
bool mg_font_is_nil(mg_font font) { return(font.h == 0); }
|
bool mg_font_is_nil(mg_font font) { return(font.h == 0); }
|
||||||
|
|
||||||
|
mg_font mg_font_handle_alloc(mg_font_data* font)
|
||||||
|
{
|
||||||
|
mg_font handle = {.h = mg_handle_alloc(MG_HANDLE_FONT, (void*)font) };
|
||||||
|
return(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_font_data* mg_font_data_from_handle(mg_font handle)
|
||||||
|
{
|
||||||
|
mg_font_data* data = mg_data_from_handle(MG_HANDLE_FONT, handle.h);
|
||||||
|
return(data);
|
||||||
|
}
|
||||||
|
|
||||||
mg_font mg_font_create_from_memory(u32 size, byte* buffer, u32 rangeCount, unicode_range* ranges)
|
mg_font mg_font_create_from_memory(u32 size, byte* buffer, u32 rangeCount, unicode_range* ranges)
|
||||||
{
|
{
|
||||||
if(!__mgData.init)
|
if(!__mgData.init)
|
||||||
|
@ -1189,6 +851,18 @@ mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text)
|
||||||
mg_canvas mg_canvas_nil() { return((mg_canvas){.h = 0}); }
|
mg_canvas mg_canvas_nil() { return((mg_canvas){.h = 0}); }
|
||||||
bool mg_canvas_is_nil(mg_canvas canvas) { return(canvas.h == 0); }
|
bool mg_canvas_is_nil(mg_canvas canvas) { return(canvas.h == 0); }
|
||||||
|
|
||||||
|
mg_canvas mg_canvas_handle_alloc(mg_canvas_data* canvas)
|
||||||
|
{
|
||||||
|
mg_canvas handle = {.h = mg_handle_alloc(MG_HANDLE_CANVAS, (void*)canvas) };
|
||||||
|
return(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_canvas_data* mg_canvas_data_from_handle(mg_canvas handle)
|
||||||
|
{
|
||||||
|
mg_canvas_data* data = mg_data_from_handle(MG_HANDLE_CANVAS, handle.h);
|
||||||
|
return(data);
|
||||||
|
}
|
||||||
|
|
||||||
mg_canvas mg_canvas_create()
|
mg_canvas mg_canvas_create()
|
||||||
{
|
{
|
||||||
mg_canvas canvasHandle = mg_canvas_nil();
|
mg_canvas canvasHandle = mg_canvas_nil();
|
||||||
|
@ -1896,38 +1570,6 @@ void mg_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle)
|
||||||
mg_image mg_image_nil() { return((mg_image){.h = 0}); }
|
mg_image mg_image_nil() { return((mg_image){.h = 0}); }
|
||||||
bool mg_image_is_nil(mg_image image) { return(image.h == 0); }
|
bool mg_image_is_nil(mg_image image) { return(image.h == 0); }
|
||||||
|
|
||||||
vec2 mg_image_size(mg_image image)
|
|
||||||
{
|
|
||||||
vec2 res = {0};
|
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
|
||||||
if(canvas)
|
|
||||||
{
|
|
||||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
|
||||||
if(imageData)
|
|
||||||
{
|
|
||||||
res = imageData->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
|
|
||||||
{
|
|
||||||
mg_image image = mg_image_nil();
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
|
||||||
if(surfaceData && surfaceData->backend)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(surfaceData->api == MG_CANVAS);
|
|
||||||
|
|
||||||
mg_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (vec2){width, height});
|
|
||||||
if(imageData)
|
|
||||||
{
|
|
||||||
image = mg_image_handle_alloc(imageData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_image mg_image_create_from_rgba8(mg_surface surface, u32 width, u32 height, u8* pixels)
|
mg_image mg_image_create_from_rgba8(mg_surface surface, u32 width, u32 height, u8* pixels)
|
||||||
{
|
{
|
||||||
mg_image image = mg_image_create(surface, width, height);
|
mg_image image = mg_image_create(surface, width, height);
|
||||||
|
@ -1971,33 +1613,6 @@ mg_image mg_image_create_from_file(mg_surface surface, str8 path, bool flip)
|
||||||
return(image);
|
return(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_image_destroy(mg_image image)
|
|
||||||
{
|
|
||||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
|
||||||
if(imageData)
|
|
||||||
{
|
|
||||||
mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface);
|
|
||||||
if(surface && surface->backend)
|
|
||||||
{
|
|
||||||
surface->backend->imageDestroy(surface->backend, imageData);
|
|
||||||
mg_handle_recycle(image.h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
|
||||||
{
|
|
||||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
|
||||||
if(imageData)
|
|
||||||
{
|
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface);
|
|
||||||
if(surfaceData)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(surfaceData->backend);
|
|
||||||
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_image_draw_region(mg_image image, mp_rect srcRegion, mp_rect dstRegion)
|
void mg_image_draw_region(mg_image image, mp_rect srcRegion, mp_rect dstRegion)
|
||||||
{
|
{
|
|
@ -0,0 +1,392 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @file: graphics_surface.c
|
||||||
|
* @author: Martin Fouilleul
|
||||||
|
* @date: 25/04/2023
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
#include"graphics_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// typed handles functions
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
mg_surface mg_surface_handle_alloc(mg_surface_data* surface)
|
||||||
|
{
|
||||||
|
mg_surface handle = {.h = mg_handle_alloc(MG_HANDLE_SURFACE, (void*)surface) };
|
||||||
|
return(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_surface_data* mg_surface_data_from_handle(mg_surface handle)
|
||||||
|
{
|
||||||
|
mg_surface_data* data = mg_data_from_handle(MG_HANDLE_SURFACE, handle.h);
|
||||||
|
return(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_image mg_image_handle_alloc(mg_image_data* image)
|
||||||
|
{
|
||||||
|
mg_image handle = {.h = mg_handle_alloc(MG_HANDLE_IMAGE, (void*)image) };
|
||||||
|
return(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_image_data* mg_image_data_from_handle(mg_image handle)
|
||||||
|
{
|
||||||
|
mg_image_data* data = mg_data_from_handle(MG_HANDLE_IMAGE, handle.h);
|
||||||
|
return(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// surface API
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
#if MG_COMPILE_GL
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
#include"wgl_surface.h"
|
||||||
|
#define gl_surface_create_for_window mg_wgl_surface_create_for_window
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_GLES
|
||||||
|
#include"egl_surface.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_METAL
|
||||||
|
#include"mtl_surface.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_CANVAS
|
||||||
|
#if PLATFORM_MACOS
|
||||||
|
mg_surface_data* mtl_canvas_surface_create_for_window(mp_window window);
|
||||||
|
#elif PLATFORM_WINDOWS
|
||||||
|
//TODO
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool mg_is_surface_backend_available(mg_surface_api api)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
switch(api)
|
||||||
|
{
|
||||||
|
#if MG_COMPILE_METAL
|
||||||
|
case MG_METAL:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_GL
|
||||||
|
case MG_GL:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_GLES
|
||||||
|
case MG_GLES:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_CANVAS
|
||||||
|
case MG_CANVAS:
|
||||||
|
#endif
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_surface mg_surface_nil() { return((mg_surface){.h = 0}); }
|
||||||
|
bool mg_surface_is_nil(mg_surface surface) { return(surface.h == 0); }
|
||||||
|
|
||||||
|
mg_surface mg_surface_create_for_window(mp_window window, mg_surface_api api)
|
||||||
|
{
|
||||||
|
if(__mgData.init)
|
||||||
|
{
|
||||||
|
mg_init();
|
||||||
|
}
|
||||||
|
mg_surface surfaceHandle = mg_surface_nil();
|
||||||
|
mg_surface_data* surface = 0;
|
||||||
|
|
||||||
|
switch(api)
|
||||||
|
{
|
||||||
|
#if MG_COMPILE_GL
|
||||||
|
case MG_GL:
|
||||||
|
surface = gl_surface_create_for_window(window);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_GLES
|
||||||
|
case MG_GLES:
|
||||||
|
surface = mg_egl_surface_create_for_window(window);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_METAL
|
||||||
|
case MG_METAL:
|
||||||
|
surface = mg_mtl_surface_create_for_window(window);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_COMPILE_CANVAS
|
||||||
|
case MG_CANVAS:
|
||||||
|
|
||||||
|
#if PLATFORM_MACOS
|
||||||
|
surface = mtl_canvas_surface_create_for_window(window);
|
||||||
|
#elif PLATFORM_WINDOWS
|
||||||
|
surface = gl_canvas_surface_create_for_window(window);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(surface)
|
||||||
|
{
|
||||||
|
surfaceHandle = mg_surface_handle_alloc(surface);
|
||||||
|
}
|
||||||
|
return(surfaceHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_surface mg_surface_create_remote(u32 width, u32 height, mg_surface_api api)
|
||||||
|
{
|
||||||
|
if(__mgData.init)
|
||||||
|
{
|
||||||
|
mg_init();
|
||||||
|
}
|
||||||
|
mg_surface surfaceHandle = mg_surface_nil();
|
||||||
|
mg_surface_data* surface = 0;
|
||||||
|
|
||||||
|
switch(api)
|
||||||
|
{
|
||||||
|
#if MG_COMPILE_GLES
|
||||||
|
case MG_GLES:
|
||||||
|
surface = mg_egl_surface_create_remote(width, height);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(surface)
|
||||||
|
{
|
||||||
|
surfaceHandle = mg_surface_handle_alloc(surface);
|
||||||
|
}
|
||||||
|
return(surfaceHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_surface mg_surface_create_host(mp_window window)
|
||||||
|
{
|
||||||
|
if(__mgData.init)
|
||||||
|
{
|
||||||
|
mg_init();
|
||||||
|
}
|
||||||
|
mg_surface handle = mg_surface_nil();
|
||||||
|
mg_surface_data* surface = 0;
|
||||||
|
#if PLATFORM_MACOS
|
||||||
|
surface = mg_osx_surface_create_host(window);
|
||||||
|
#elif PLATFORM_WINDOWS
|
||||||
|
surface = mg_win32_surface_create_host(window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(surface)
|
||||||
|
{
|
||||||
|
handle = mg_surface_handle_alloc(surface);
|
||||||
|
}
|
||||||
|
return(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_surface_destroy(mg_surface handle)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||||
|
if(surface)
|
||||||
|
{
|
||||||
|
if(surface->backend && surface->backend->destroy)
|
||||||
|
{
|
||||||
|
surface->backend->destroy(surface->backend);
|
||||||
|
}
|
||||||
|
surface->destroy(surface);
|
||||||
|
mg_handle_recycle(handle.h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_surface_prepare(mg_surface surface)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->prepare)
|
||||||
|
{
|
||||||
|
surfaceData->prepare(surfaceData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_surface_present(mg_surface surface)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->present)
|
||||||
|
{
|
||||||
|
surfaceData->present(surfaceData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_surface_swap_interval(mg_surface surface, int swap)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->swapInterval)
|
||||||
|
{
|
||||||
|
surfaceData->swapInterval(surfaceData, swap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 mg_surface_contents_scaling(mg_surface surface)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
vec2 scaling = {1, 1};
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->contentsScaling)
|
||||||
|
{
|
||||||
|
scaling = surfaceData->contentsScaling(surfaceData);
|
||||||
|
}
|
||||||
|
return(scaling);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mg_surface_set_frame(mg_surface surface, mp_rect frame)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->setFrame)
|
||||||
|
{
|
||||||
|
surfaceData->setFrame(surfaceData, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_rect mg_surface_get_frame(mg_surface surface)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
mp_rect res = {0};
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->getFrame)
|
||||||
|
{
|
||||||
|
res = surfaceData->getFrame(surfaceData);
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_surface_set_hidden(mg_surface surface, bool hidden)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->setHidden)
|
||||||
|
{
|
||||||
|
surfaceData->setHidden(surfaceData, hidden);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_surface_get_hidden(mg_surface surface)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(__mgData.init);
|
||||||
|
bool res = false;
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->getHidden)
|
||||||
|
{
|
||||||
|
res = surfaceData->getHidden(surfaceData);
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mg_surface_native_layer(mg_surface surface)
|
||||||
|
{
|
||||||
|
void* res = 0;
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->nativeLayer)
|
||||||
|
{
|
||||||
|
res = surfaceData->nativeLayer(surfaceData);
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_surface_id mg_surface_remote_id(mg_surface handle)
|
||||||
|
{
|
||||||
|
mg_surface_id remoteId = 0;
|
||||||
|
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||||
|
if(surface && surface->remoteID)
|
||||||
|
{
|
||||||
|
remoteId = surface->remoteID(surface);
|
||||||
|
}
|
||||||
|
return(remoteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_surface_host_connect(mg_surface handle, mg_surface_id remoteID)
|
||||||
|
{
|
||||||
|
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||||
|
if(surface && surface->hostConnect)
|
||||||
|
{
|
||||||
|
surface->hostConnect(surface, remoteID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
//NOTE(martin): images
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
vec2 mg_image_size(mg_image image)
|
||||||
|
{
|
||||||
|
vec2 res = {0};
|
||||||
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
|
if(canvas)
|
||||||
|
{
|
||||||
|
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||||
|
if(imageData)
|
||||||
|
{
|
||||||
|
res = imageData->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
|
||||||
|
{
|
||||||
|
mg_image image = mg_image_nil();
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->backend)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(surfaceData->api == MG_CANVAS);
|
||||||
|
|
||||||
|
mg_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (vec2){width, height});
|
||||||
|
if(imageData)
|
||||||
|
{
|
||||||
|
image = mg_image_handle_alloc(imageData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_image_destroy(mg_image image)
|
||||||
|
{
|
||||||
|
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||||
|
if(imageData)
|
||||||
|
{
|
||||||
|
mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface);
|
||||||
|
if(surface && surface->backend)
|
||||||
|
{
|
||||||
|
surface->backend->imageDestroy(surface->backend, imageData);
|
||||||
|
mg_handle_recycle(image.h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
||||||
|
{
|
||||||
|
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||||
|
if(imageData)
|
||||||
|
{
|
||||||
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface);
|
||||||
|
if(surfaceData)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(surfaceData->backend);
|
||||||
|
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,7 +54,8 @@
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
#include"win32_app.c"
|
#include"win32_app.c"
|
||||||
#include"graphics.c"
|
#include"graphics_common.c"
|
||||||
|
#include"graphics_surface.c"
|
||||||
|
|
||||||
#if MG_COMPILE_GL || MG_COMPILE_GLES
|
#if MG_COMPILE_GL || MG_COMPILE_GLES
|
||||||
#include"gl_loader.c"
|
#include"gl_loader.c"
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
#include"osx_app.m"
|
#include"osx_app.m"
|
||||||
#include"graphics.c"
|
#include"graphics_common.c"
|
||||||
|
#include"graphics_surface.c"
|
||||||
|
|
||||||
#if MG_COMPILE_METAL
|
#if MG_COMPILE_METAL
|
||||||
#include"mtl_surface.m"
|
#include"mtl_surface.m"
|
||||||
|
|
|
@ -259,9 +259,6 @@ vec2 mg_quadratic_get_point(vec2 p[3], f32 t)
|
||||||
|
|
||||||
void mg_quadratic_split(vec2 p[3], f32 t, vec2 outLeft[3], vec2 outRight[3])
|
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
|
//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 q_n are the points along the hull's segments at parameter t
|
||||||
// s is the split point.
|
// s is the split point.
|
||||||
|
|
|
@ -7,6 +7,18 @@
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
mp_rect clip;
|
||||||
|
mg_mat2x3 transform;
|
||||||
|
mg_image image;
|
||||||
|
mp_rect srcRegion;
|
||||||
|
|
||||||
|
u32 nextShapeIndex;
|
||||||
|
u32 vertexCount;
|
||||||
|
u32 indexCount;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
void mg_reset_shape_index(mg_canvas_data* canvas)
|
void mg_reset_shape_index(mg_canvas_data* canvas)
|
||||||
{
|
{
|
||||||
canvas->nextShapeIndex = 0;
|
canvas->nextShapeIndex = 0;
|
||||||
|
|
Loading…
Reference in New Issue