[surface] extracted common layer functionality from osx surfaces. Use layer in platform-agnostic egl surface.
This commit is contained in:
parent
9ea9ea7636
commit
94373d12ae
|
@ -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,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#if MG_COMPILE_BACKEND_GLES
|
||||
#include"gl_loader.c"
|
||||
#include"osx_egl_surface.m"
|
||||
#include"egl_surface.c"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -23,6 +23,8 @@ typedef struct mg_mtl_surface
|
|||
{
|
||||
mg_surface_data interface;
|
||||
|
||||
mp_layer layer;
|
||||
|
||||
// permanent mtl resources
|
||||
id<MTLDevice> 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};
|
||||
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
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define NSObject void
|
||||
#define NSTimer void
|
||||
#define NSCursor void
|
||||
#define CALayer void
|
||||
#endif
|
||||
|
||||
#include<Carbon/Carbon.h>
|
||||
|
@ -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;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
//
|
||||
//*****************************************************************
|
||||
|
||||
#import <QuartzCore/QuartzCore.h> //CATransaction
|
||||
|
||||
#include<stdlib.h> // 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
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
@ -1,203 +0,0 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: osx_egl_surface.m
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 17/02/2023
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#define EGL_EGLEXT_PROTOTYPES
|
||||
#include<EGL/egl.h>
|
||||
#include<EGL/eglext.h>
|
||||
|
||||
#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);
|
||||
}
|
Loading…
Reference in New Issue