diff --git a/src/egl_surface.c b/src/egl_surface.c index ad94628..aeef560 100644 --- a/src/egl_surface.c +++ b/src/egl_surface.c @@ -1,6 +1,6 @@ /************************************************************//** * -* @file: win32_egl_surface.cpp +* @file: egl_surface.cpp * @author: Martin Fouilleul * @date: 17/02/2023 * @revision: @@ -121,8 +121,15 @@ mg_surface mg_egl_surface_create_for_window(mp_window window) mp_layer_init_for_window(&surface->layer, windowData); + #if OS_MACOS + //NOTE: using EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE on osx defaults to CGL backend, which doesn't handle SwapInterval correctly + #define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE + #else + #define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE + #endif + EGLAttrib displayAttribs[] = { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_ANGLE, MG_EGL_PLATFORM_ANGLE_TYPE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, EGL_NONE}; @@ -154,7 +161,7 @@ mg_surface mg_egl_surface_create_for_window(mp_window window) eglBindAPI(EGL_OPENGL_ES_API); EGLint contextAttributes[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, 3, - EGL_CONTEXT_MINOR_VERSION_KHR, 1, + EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE, EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE, EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE, diff --git a/src/milepost.m b/src/milepost.m index b42d45a..3c41b2b 100644 --- a/src/milepost.m +++ b/src/milepost.m @@ -17,7 +17,7 @@ #if MG_COMPILE_BACKEND_GLES #include"gl_loader.c" - #include"osx_egl_surface.m" + #include"egl_surface.c" #endif /* diff --git a/src/mtl_surface.m b/src/mtl_surface.m index e639578..63ef781 100644 --- a/src/mtl_surface.m +++ b/src/mtl_surface.m @@ -23,6 +23,8 @@ typedef struct mg_mtl_surface { mg_surface_data interface; + mp_layer layer; + // permanent mtl resources id device; CAMetalLayer* mtlLayer; @@ -47,6 +49,7 @@ void mg_mtl_surface_destroy(mg_surface_data* interface) [surface->mtlLayer release]; [surface->device release]; } + //NOTE: we don't use mp_layer_cleanup here, because the CAMetalLayer is taken care off by the surface itself } void mg_mtl_surface_acquire_drawable_and_command_buffer(mg_mtl_surface* surface) @@ -136,51 +139,38 @@ void mg_mtl_surface_swap_interval(mg_surface_data* interface, int swap) //////////////////////////////////////////////////////////////// } +vec2 mg_mtl_surface_contents_scaling(mg_surface_data* interface) +{ + mg_mtl_surface* surface = (mg_mtl_surface*)interface; + return(mp_layer_contents_scaling(&surface->layer)); +} + void mg_mtl_surface_set_frame(mg_surface_data* interface, mp_rect frame) { mg_mtl_surface* surface = (mg_mtl_surface*)interface; + mp_layer_set_frame(&surface->layer, frame); + vec2 scale = mp_layer_contents_scaling(&surface->layer); - @autoreleasepool - { - CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}}; - [surface->mtlLayer setFrame: cgFrame]; - - f32 scale = surface->mtlLayer.contentsScale; - CGSize drawableSize = (CGSize){.width = frame.w * scale, .height = frame.h * scale}; - surface->mtlLayer.drawableSize = drawableSize; - } + CGSize drawableSize = (CGSize){.width = frame.w * scale.x, .height = frame.h * scale.y}; + surface->mtlLayer.drawableSize = drawableSize; } mp_rect mg_mtl_surface_get_frame(mg_surface_data* interface) { mg_mtl_surface* surface = (mg_mtl_surface*)interface; - - @autoreleasepool - { - CGRect frame = surface->mtlLayer.frame; - return((mp_rect){frame.origin.x, frame.origin.y, frame.size.width, frame.size.height}); - } + return(mp_layer_get_frame(&surface->layer)); } void mg_mtl_surface_set_hidden(mg_surface_data* interface, bool hidden) { mg_mtl_surface* surface = (mg_mtl_surface*)interface; - @autoreleasepool - { - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - [surface->mtlLayer setHidden:hidden]; - [CATransaction commit]; - } + mp_layer_set_hidden(&surface->layer, hidden); } bool mg_mtl_surface_get_hidden(mg_surface_data* interface) { mg_mtl_surface* surface = (mg_mtl_surface*)interface; - @autoreleasepool - { - return([surface->mtlLayer isHidden]); - } + return(mp_layer_get_hidden(&surface->layer)); } //TODO fix that according to real scaling, depending on the monitor settings @@ -203,6 +193,7 @@ mg_surface mg_mtl_surface_create_for_window(mp_window window) surface->interface.prepare = mg_mtl_surface_prepare; surface->interface.present = mg_mtl_surface_present; surface->interface.swapInterval = mg_mtl_surface_swap_interval; + surface->interface.contentsScaling = mg_mtl_surface_contents_scaling; surface->interface.getFrame = mg_mtl_surface_get_frame; surface->interface.setFrame = mg_mtl_surface_set_frame; surface->interface.getHidden = mg_mtl_surface_get_hidden; @@ -220,9 +211,11 @@ mg_surface mg_mtl_surface_create_for_window(mp_window window) [surface->device retain]; surface->mtlLayer = [CAMetalLayer layer]; [surface->mtlLayer retain]; - [surface->mtlLayer setOpaque:NO]; surface->mtlLayer.device = surface->device; + [surface->mtlLayer setOpaque:NO]; + + surface->layer.caLayer = (CALayer*)surface->mtlLayer; //----------------------------------------------------------- //NOTE(martin): set the size and scaling diff --git a/src/osx_app.h b/src/osx_app.h index 5c08f1b..9fb49c0 100644 --- a/src/osx_app.h +++ b/src/osx_app.h @@ -20,6 +20,7 @@ #define NSObject void #define NSTimer void #define NSCursor void + #define CALayer void #endif #include @@ -32,6 +33,11 @@ typedef struct osx_window_data } osx_window_data; +typedef struct mp_layer +{ + CALayer* caLayer; +} mp_layer; + #define MP_PLATFORM_WINDOW_DATA osx_window_data osx; const u32 MP_APP_MAX_VIEWS = 128; diff --git a/src/osx_app.m b/src/osx_app.m index e7c7a66..4cfa62b 100644 --- a/src/osx_app.m +++ b/src/osx_app.m @@ -8,6 +8,8 @@ // //***************************************************************** +#import //CATransaction + #include // malloc/free #include"lists.h" @@ -1713,6 +1715,68 @@ void mp_window_set_content_size(mp_window window, int width, int height) } } +//-------------------------------------------------------------------- +// layers +//-------------------------------------------------------------------- + +void mp_layer_init_for_window(mp_layer* layer, mp_window_data* window) +{@autoreleasepool{ + layer->caLayer = [[CALayer alloc] init]; + [layer->caLayer retain]; + + NSRect frame = [[window->osx.nsWindow contentView] frame]; + CGSize size = frame.size; + layer->caLayer.frame = (CGRect){{0, 0}, size}; + + [window->osx.nsView.layer addSublayer: layer->caLayer]; +}} + +void mp_layer_cleanup(mp_layer* layer) +{@autoreleasepool{ + [layer->caLayer release]; +}} + +void* mp_layer_native_surface(mp_layer* layer) +{ + return((void*)layer->caLayer); +} + +vec2 mp_layer_contents_scaling(mp_layer* layer) +{@autoreleasepool{ + f32 contentsScale = [layer->caLayer contentsScale]; + vec2 res = {contentsScale, contentsScale}; + return(res); +}} + +mp_rect mp_layer_get_frame(mp_layer* layer) +{@autoreleasepool{ + CGRect frame = layer->caLayer.frame; + mp_rect res = {frame.origin.x, + frame.origin.y, + frame.size.width, + frame.size.height}; + return(res); +}} + +void mp_layer_set_frame(mp_layer* layer, mp_rect frame) +{@autoreleasepool{ + CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}}; + [layer->caLayer setFrame: cgFrame]; +}} + +void mp_layer_set_hidden(mp_layer* layer, bool hidden) +{@autoreleasepool{ + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + [layer->caLayer setHidden:hidden]; + [CATransaction commit]; +}} + +bool mp_layer_get_hidden(mp_layer* layer) +{@autoreleasepool{ + return([layer->caLayer isHidden]); +}} + //-------------------------------------------------------------------- // view management //-------------------------------------------------------------------- diff --git a/src/osx_egl_surface.m b/src/osx_egl_surface.m deleted file mode 100644 index faa4d30..0000000 --- a/src/osx_egl_surface.m +++ /dev/null @@ -1,203 +0,0 @@ -/************************************************************//** -* -* @file: osx_egl_surface.m -* @author: Martin Fouilleul -* @date: 17/02/2023 -* @revision: -* -*****************************************************************/ - -#define EGL_EGLEXT_PROTOTYPES -#include -#include - -#include"mp_app_internal.h" -#include"graphics_internal.h" -#include"gl_loader.h" - -typedef struct mg_egl_surface -{ - mg_surface_data interface; - - CALayer* layer; - - EGLDisplay eglDisplay; - EGLConfig eglConfig; - EGLContext eglContext; - EGLSurface eglSurface; - - mg_gl_api api; - -} mg_egl_surface; - -void mg_egl_surface_destroy(mg_surface_data* interface) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - - if(&surface->api == mg_gl_get_api()) - { - mg_gl_select_api(0); - } - if(eglGetCurrentContext() == surface->eglContext) - { - eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - } - eglDestroyContext(surface->eglDisplay, surface->eglContext); - eglDestroySurface(surface->eglDisplay, surface->eglSurface); - - @autoreleasepool - { - [surface->layer release]; - } - - free(surface); -} - -void mg_egl_surface_prepare(mg_surface_data* interface) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext); - mg_gl_select_api(&surface->api); -} - -void mg_egl_surface_present(mg_surface_data* interface) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - eglSwapBuffers(surface->eglDisplay, surface->eglSurface); -} - -void mg_egl_surface_swap_interval(mg_surface_data* interface, int swap) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - eglSwapInterval(surface->eglDisplay, 1); -} - -void mg_egl_surface_set_frame(mg_surface_data* interface, mp_rect frame) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - - @autoreleasepool - { - CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}}; - [surface->layer setFrame: cgFrame]; - } -} - -mp_rect mg_egl_surface_get_frame(mg_surface_data* interface) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - - @autoreleasepool - { - CGRect frame = surface->layer.frame; - return((mp_rect){frame.origin.x, frame.origin.y, frame.size.width, frame.size.height}); - } -} - -void mg_egl_surface_set_hidden(mg_surface_data* interface, bool hidden) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - @autoreleasepool - { - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - [surface->layer setHidden:hidden]; - [CATransaction commit]; - } -} - -bool mg_egl_surface_get_hidden(mg_surface_data* interface) -{ - mg_egl_surface* surface = (mg_egl_surface*)interface; - @autoreleasepool - { - return([surface->layer isHidden]); - } -} - -/* -mp_rect mg_egl_surface_get_frame(mg_surface_data* interface); -void mg_egl_surface_set_frame(mg_surface_data* interface, mp_rect frame); -void mg_egl_surface_set_hidden(mg_surface_data* interface, bool hidden); -bool mg_egl_surface_get_hidden(mg_surface_data* interface); -*/ - -mg_surface mg_egl_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_egl_surface* surface = malloc_type(mg_egl_surface); - memset(surface, 0, sizeof(mg_egl_surface)); - - surface->interface.backend = MG_BACKEND_GLES; - surface->interface.destroy = mg_egl_surface_destroy; - surface->interface.prepare = mg_egl_surface_prepare; - surface->interface.present = mg_egl_surface_present; - surface->interface.getFrame = mg_egl_surface_get_frame; - surface->interface.setFrame = mg_egl_surface_set_frame; - surface->interface.getHidden = mg_egl_surface_get_hidden; - surface->interface.setHidden = mg_egl_surface_set_hidden; - surface->interface.swapInterval = mg_egl_surface_swap_interval; - - @autoreleasepool - { - surface->layer = [[CALayer alloc] init]; - [surface->layer retain]; - - [windowData->osx.nsView.layer addSublayer: surface->layer]; - - NSRect frame = [[windowData->osx.nsWindow contentView] frame]; - CGSize size = frame.size; - surface->layer.frame = (CGRect){{0, 0}, size}; - } - - EGLAttrib displayAttribs[] = { - 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 }; - - int numConfigs = 0; - eglChooseConfig(surface->eglDisplay, configAttributes, &surface->eglConfig, 1, &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, - 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); - - mg_gl_load_gles32(&surface->api, (mg_gl_load_proc)eglGetProcAddress); - - eglSwapInterval(surface->eglDisplay, 1); - - res = mg_surface_alloc_handle((mg_surface_data*)surface); - } - return(res); -}