back osx surfaces by CALayer
This commit is contained in:
parent
2232b647ed
commit
4306d0a01c
|
@ -5,7 +5,12 @@ RESDIR=../../resources
|
||||||
SRCDIR=../../src
|
SRCDIR=../../src
|
||||||
|
|
||||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore -L$BINDIR -lEGL -lGLESv2"
|
||||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip"
|
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
|
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_canvas main.c
|
||||||
|
|
||||||
|
# change dynamic libraries install name
|
||||||
|
#TODO: this shouldn't be needed for apps using only metal backend...
|
||||||
|
install_name_tool -change "./libEGL.dylib" "@loader_path/libEGL.dylib" $BINDIR/example_canvas
|
||||||
|
install_name_tool -change "./libGLESv2.dylib" "@loader_path/libGLESv2.dylib" $BINDIR/example_canvas
|
||||||
|
|
|
@ -5,10 +5,16 @@ RESDIR=../../resources
|
||||||
SRCDIR=../../src
|
SRCDIR=../../src
|
||||||
|
|
||||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore -L$BINDIR -lEGL -lGLESv2"
|
||||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip"
|
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip"
|
||||||
|
|
||||||
xcrun -sdk macosx metal -c -o shader.air shader.metal
|
xcrun -sdk macosx metal -c -o shader.air shader.metal
|
||||||
xcrun -sdk macosx metallib -o shader.metallib shader.air
|
xcrun -sdk macosx metallib -o shader.metallib shader.air
|
||||||
|
cp shader.metallib $BINDIR/triangle_shader.metallib
|
||||||
|
|
||||||
clang -g $FLAGS $LIBS $INCLUDES -o test main.m
|
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_metal_triangle main.m
|
||||||
|
|
||||||
|
# change dynamic libraries install name
|
||||||
|
#TODO: this shouldn't be needed for apps using only metal backend...
|
||||||
|
install_name_tool -change "./libEGL.dylib" "@loader_path/libEGL.dylib" $BINDIR/example_metal_triangle
|
||||||
|
install_name_tool -change "./libGLESv2.dylib" "@loader_path/libGLESv2.dylib" $BINDIR/example_metal_triangle
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include<math.h>
|
#include<math.h>
|
||||||
|
|
||||||
#include"milepost.h"
|
#include"milepost.h"
|
||||||
#include"metal_surface.h"
|
#include"mtl_surface.h"
|
||||||
|
|
||||||
#define LOG_SUBSYSTEM "Main"
|
#define LOG_SUBSYSTEM "Main"
|
||||||
|
|
||||||
|
@ -36,13 +36,14 @@ int main()
|
||||||
mp_window window = mp_window_create(rect, "test", 0);
|
mp_window window = mp_window_create(rect, "test", 0);
|
||||||
|
|
||||||
//NOTE: create surface
|
//NOTE: create surface
|
||||||
mg_surface surface = mg_metal_surface_create_for_window(window);
|
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_METAL);
|
||||||
|
|
||||||
//NOTE(martin): load the library
|
//NOTE(martin): load the library
|
||||||
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
|
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
|
||||||
|
|
||||||
const char* shaderPath = "shader.metallib";
|
str8 shaderPath = mp_app_get_resource_path(mem_scratch(), "triangle_shader.metallib");
|
||||||
NSString* metalFileName = [[NSString alloc] initWithCString: shaderPath encoding: NSUTF8StringEncoding];
|
const char* shaderPathCString = str8_to_cstring(mem_scratch(), shaderPath);
|
||||||
|
NSString* metalFileName = [[NSString alloc] initWithCString: shaderPathCString encoding: NSUTF8StringEncoding];
|
||||||
NSError* err = 0;
|
NSError* err = 0;
|
||||||
id<MTLLibrary> library = [device newLibraryWithFile: metalFileName error:&err];
|
id<MTLLibrary> library = [device newLibraryWithFile: metalFileName error:&err];
|
||||||
if(err != nil)
|
if(err != nil)
|
||||||
|
@ -60,7 +61,7 @@ int main()
|
||||||
pipelineStateDescriptor.vertexFunction = vertexFunction;
|
pipelineStateDescriptor.vertexFunction = vertexFunction;
|
||||||
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
|
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
|
||||||
|
|
||||||
CAMetalLayer* layer = mg_metal_surface_layer(surface);
|
CAMetalLayer* layer = mg_mtl_surface_layer(surface);
|
||||||
pipelineStateDescriptor.colorAttachments[0].pixelFormat = layer.pixelFormat;
|
pipelineStateDescriptor.colorAttachments[0].pixelFormat = layer.pixelFormat;
|
||||||
|
|
||||||
id<MTLRenderPipelineState> pipelineState = [device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err];
|
id<MTLRenderPipelineState> pipelineState = [device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err];
|
||||||
|
@ -89,69 +90,6 @@ int main()
|
||||||
mp_request_quit();
|
mp_request_quit();
|
||||||
} break;
|
} 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_WINDOW_MOVE:
|
|
||||||
{
|
|
||||||
printf("moved, 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_MOUSE_MOVE:
|
|
||||||
{
|
|
||||||
printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n",
|
|
||||||
event.move.x,
|
|
||||||
event.move.y,
|
|
||||||
event.move.deltaX,
|
|
||||||
event.move.deltaY);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MP_EVENT_MOUSE_WHEEL:
|
|
||||||
{
|
|
||||||
printf("mouse wheel, delta = {%f, %f}\n",
|
|
||||||
event.move.deltaX,
|
|
||||||
event.move.deltaY);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MP_EVENT_MOUSE_ENTER:
|
|
||||||
{
|
|
||||||
printf("mouse enter\n");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MP_EVENT_MOUSE_LEAVE:
|
|
||||||
{
|
|
||||||
printf("mouse leave\n");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MP_EVENT_MOUSE_BUTTON:
|
|
||||||
{
|
|
||||||
printf("mouse button %i: %i\n",
|
|
||||||
event.key.code,
|
|
||||||
event.key.action == MP_KEY_PRESS ? 1 : 0);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MP_EVENT_KEYBOARD_KEY:
|
|
||||||
{
|
|
||||||
printf("key %i: %s\n",
|
|
||||||
event.key.code,
|
|
||||||
event.key.action == MP_KEY_PRESS ? "press" : (event.key.action == MP_KEY_RELEASE ? "release" : "repeat"));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MP_EVENT_KEYBOARD_CHAR:
|
|
||||||
{
|
|
||||||
printf("entered char %s\n", event.character.sequence);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -162,8 +100,8 @@ int main()
|
||||||
viewportSize.y = 600;
|
viewportSize.y = 600;
|
||||||
|
|
||||||
mg_surface_prepare(surface);
|
mg_surface_prepare(surface);
|
||||||
id<CAMetalDrawable> drawable = mg_metal_surface_drawable(surface);
|
id<CAMetalDrawable> drawable = mg_mtl_surface_drawable(surface);
|
||||||
id<MTLCommandBuffer> commandBuffer = mg_metal_surface_command_buffer(surface);
|
id<MTLCommandBuffer> commandBuffer = mg_mtl_surface_command_buffer(surface);
|
||||||
|
|
||||||
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
|
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
|
||||||
|
|
|
@ -30,22 +30,6 @@ typedef struct mg_egl_surface
|
||||||
|
|
||||||
} mg_egl_surface;
|
} mg_egl_surface;
|
||||||
|
|
||||||
#if OS_MACOS
|
|
||||||
#include"osx_app.h"
|
|
||||||
|
|
||||||
void* mg_egl_get_native_surface(mp_window_data* window)
|
|
||||||
{
|
|
||||||
return((void*)window->osx.nsView.layer);
|
|
||||||
}
|
|
||||||
#elif OS_WIN64
|
|
||||||
#include"win32_app.h"
|
|
||||||
|
|
||||||
void* mg_egl_get_native_surface(mp_window_data* window)
|
|
||||||
{
|
|
||||||
return((void*)window->win32.hWnd);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void mg_egl_surface_destroy(mg_surface_data* interface)
|
void mg_egl_surface_destroy(mg_surface_data* interface)
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
|
@ -73,11 +57,23 @@ void mg_egl_surface_set_hidden(mg_surface_data* interface, bool hidden);
|
||||||
bool mg_egl_surface_get_hidden(mg_surface_data* interface);
|
bool mg_egl_surface_get_hidden(mg_surface_data* interface);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if OS_MACOS
|
||||||
|
//NOTE: on macOS 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
|
||||||
|
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE
|
||||||
|
#elif OS_WIN64
|
||||||
|
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
||||||
|
#endif
|
||||||
|
|
||||||
mg_surface mg_egl_surface_create_for_window(mp_window window)
|
mg_surface mg_egl_surface_create_for_window(mp_window window)
|
||||||
{
|
{
|
||||||
mg_surface res = mg_surface_nil();
|
mg_surface res = mg_surface_nil();
|
||||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
|
||||||
if(windowData)
|
//TODO: just need to check that the handle is valid
|
||||||
|
// then get native pointer from window handle
|
||||||
|
void* nativeSurface = mg_egl_get_native_surface(window);
|
||||||
|
|
||||||
|
if(nativeSurface)
|
||||||
{
|
{
|
||||||
mg_egl_surface* surface = malloc_type(mg_egl_surface);
|
mg_egl_surface* surface = malloc_type(mg_egl_surface);
|
||||||
memset(surface, 0, sizeof(mg_egl_surface));
|
memset(surface, 0, sizeof(mg_egl_surface));
|
||||||
|
@ -93,22 +89,12 @@ mg_surface mg_egl_surface_create_for_window(mp_window window)
|
||||||
surface->interface.setHidden = mg_egl_surface_set_hidden;
|
surface->interface.setHidden = mg_egl_surface_set_hidden;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
surface->nativeSurface = mg_egl_get_native_surface(windowData);
|
surface->nativeSurface = nativeSurface;
|
||||||
|
|
||||||
|
EGLAttrib displayAttribs[] = {
|
||||||
#if OS_MACOS
|
EGL_PLATFORM_ANGLE_TYPE_ANGLE, MG_EGL_PLATFORM_ANGLE_TYPE,
|
||||||
//NOTE: we need to explicitly set EGL_PLATFORM_ANGLE_TYPE_ANGLE to EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, because
|
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
|
||||||
// EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE defaults to using CGL, and eglSetSwapInterval is broken for this backend
|
EGL_NONE};
|
||||||
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};
|
|
||||||
#else
|
|
||||||
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};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs);
|
surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs);
|
||||||
eglInitialize(surface->eglDisplay, NULL, NULL);
|
eglInitialize(surface->eglDisplay, NULL, NULL);
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// surface data
|
||||||
|
//---------------------------------------------------------------
|
||||||
typedef struct mg_surface_data mg_surface_data;
|
typedef struct mg_surface_data mg_surface_data;
|
||||||
|
|
||||||
typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface);
|
typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface);
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_GL
|
#if MG_COMPILE_BACKEND_GL
|
||||||
#include"wgl_surface.c"
|
= #include"wgl_surface.c"
|
||||||
#include"gl_canvas.c"
|
#include"gl_canvas.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_GLES
|
#if MG_COMPILE_BACKEND_GLES
|
||||||
#include"gl_loader.c"
|
#include"gl_loader.c"
|
||||||
#include"egl_surface.c"
|
#include"osx_egl_surface.m"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#ifndef __MP_APP_INTERNAL_H_
|
#ifndef __MP_APP_INTERNAL_H_
|
||||||
#define __MP_APP_INTERNAL_H_
|
#define __MP_APP_INTERNAL_H_
|
||||||
|
|
||||||
|
#include"mp_app.h"
|
||||||
|
|
||||||
#include"platform.h"
|
#include"platform.h"
|
||||||
#include"ringbuffer.h"
|
#include"ringbuffer.h"
|
||||||
|
|
||||||
|
@ -148,6 +150,4 @@ typedef struct mp_app
|
||||||
MP_PLATFORM_APP_DATA
|
MP_PLATFORM_APP_DATA
|
||||||
} mp_app;
|
} mp_app;
|
||||||
|
|
||||||
mp_window_data* mp_window_ptr_from_handle(mp_window handle);
|
|
||||||
|
|
||||||
#endif // __MP_APP_INTERNAL_H_
|
#endif // __MP_APP_INTERNAL_H_
|
||||||
|
|
|
@ -24,7 +24,6 @@ typedef struct mg_mtl_surface
|
||||||
mg_surface_data interface;
|
mg_surface_data interface;
|
||||||
|
|
||||||
// permanent mtl resources
|
// permanent mtl resources
|
||||||
NSView* view;
|
|
||||||
id<MTLDevice> device;
|
id<MTLDevice> device;
|
||||||
CAMetalLayer* mtlLayer;
|
CAMetalLayer* mtlLayer;
|
||||||
id<MTLCommandQueue> commandQueue;
|
id<MTLCommandQueue> commandQueue;
|
||||||
|
@ -44,6 +43,7 @@ void mg_mtl_surface_destroy(mg_surface_data* interface)
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
[surface->commandQueue release];
|
[surface->commandQueue release];
|
||||||
|
[surface->mtlLayer removeFromSuperlayer];
|
||||||
[surface->mtlLayer release];
|
[surface->mtlLayer release];
|
||||||
[surface->device release];
|
[surface->device release];
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,8 @@ void mg_mtl_surface_set_frame(mg_surface_data* interface, mp_rect frame)
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}};
|
CGRect cgFrame = {{frame.x, frame.y}, {frame.w, frame.h}};
|
||||||
[surface->view setFrame: cgFrame];
|
[surface->mtlLayer setFrame: cgFrame];
|
||||||
|
|
||||||
f32 scale = surface->mtlLayer.contentsScale;
|
f32 scale = surface->mtlLayer.contentsScale;
|
||||||
CGSize drawableSize = (CGSize){.width = frame.w * scale, .height = frame.h * scale};
|
CGSize drawableSize = (CGSize){.width = frame.w * scale, .height = frame.h * scale};
|
||||||
surface->mtlLayer.drawableSize = drawableSize;
|
surface->mtlLayer.drawableSize = drawableSize;
|
||||||
|
@ -156,7 +157,7 @@ mp_rect mg_mtl_surface_get_frame(mg_surface_data* interface)
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
CGRect frame = surface->view.frame;
|
CGRect frame = surface->mtlLayer.frame;
|
||||||
return((mp_rect){frame.origin.x, frame.origin.y, frame.size.width, frame.size.height});
|
return((mp_rect){frame.origin.x, frame.origin.y, frame.size.width, frame.size.height});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,17 +210,12 @@ mg_surface mg_mtl_surface_create_for_window(mp_window window)
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
|
|
||||||
surface->view = [[NSView alloc] initWithFrame: frame];
|
|
||||||
[surface->view setWantsLayer:YES];
|
|
||||||
|
|
||||||
[[windowData->osx.nsWindow contentView] addSubview: surface->view];
|
|
||||||
|
|
||||||
surface->drawableSemaphore = dispatch_semaphore_create(MP_MTL_MAX_DRAWABLES_IN_FLIGHT);
|
surface->drawableSemaphore = dispatch_semaphore_create(MP_MTL_MAX_DRAWABLES_IN_FLIGHT);
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
//NOTE(martin): create a mtl device and a mtl layer and
|
//NOTE(martin): create a mtl device and a mtl layer and
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
surface->device = MTLCreateSystemDefaultDevice();
|
surface->device = MTLCreateSystemDefaultDevice();
|
||||||
[surface->device retain];
|
[surface->device retain];
|
||||||
surface->mtlLayer = [CAMetalLayer layer];
|
surface->mtlLayer = [CAMetalLayer layer];
|
||||||
|
@ -231,7 +227,9 @@ mg_surface mg_mtl_surface_create_for_window(mp_window window)
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
//NOTE(martin): set the size and scaling
|
//NOTE(martin): set the size and scaling
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
CGSize size = surface->view.bounds.size;
|
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
|
||||||
|
CGSize size = frame.size;
|
||||||
|
surface->mtlLayer.frame = (CGRect){{0, 0}, size};
|
||||||
size.width *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
size.width *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||||
size.height *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
size.height *= MG_MTL_SURFACE_CONTENTS_SCALING;
|
||||||
surface->mtlLayer.drawableSize = size;
|
surface->mtlLayer.drawableSize = size;
|
||||||
|
@ -239,11 +237,9 @@ mg_surface mg_mtl_surface_create_for_window(mp_window window)
|
||||||
|
|
||||||
surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
|
|
||||||
surface->view.wantsLayer = YES;
|
[windowData->osx.nsView.layer addSublayer: surface->mtlLayer];
|
||||||
surface->view.layer = surface->mtlLayer;
|
|
||||||
|
|
||||||
//NOTE(martin): handling resizing
|
//NOTE(martin): handling resizing
|
||||||
surface->view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
|
|
||||||
surface->mtlLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
|
surface->mtlLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
|
||||||
surface->mtlLayer.needsDisplayOnBoundsChange = YES;
|
surface->mtlLayer.needsDisplayOnBoundsChange = YES;
|
||||||
|
|
||||||
|
|
|
@ -729,6 +729,7 @@ static void mp_update_key_mods(mp_key_mods mods)
|
||||||
window = mpWindow;
|
window = mpWindow;
|
||||||
mpWindow->osx.nsView = self;
|
mpWindow->osx.nsView = self;
|
||||||
[mpWindow->osx.nsView setWantsLayer:YES];
|
[mpWindow->osx.nsView setWantsLayer:YES];
|
||||||
|
mpWindow->osx.nsView.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
|
||||||
|
|
||||||
NSTrackingAreaOptions trackingOptions = NSTrackingMouseEnteredAndExited
|
NSTrackingAreaOptions trackingOptions = NSTrackingMouseEnteredAndExited
|
||||||
| NSTrackingMouseMoved
|
| NSTrackingMouseMoved
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @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;
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
[surface->layer release];
|
||||||
|
}
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
//TODO
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
|
@ -822,4 +822,15 @@ str8 mp_app_get_resource_path(mem_arena* arena, const char* name)
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void* mg_egl_get_native_surface(mp_window_data* window)
|
||||||
|
{
|
||||||
|
void* res = 0;
|
||||||
|
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||||
|
if(windowData)
|
||||||
|
{
|
||||||
|
res = (void*)windowData->win32.hWnd;
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
#undef LOG_SUBSYSTEM
|
#undef LOG_SUBSYSTEM
|
||||||
|
|
29
todo.txt
29
todo.txt
|
@ -1,17 +1,11 @@
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
[x] Pan/Zoom on text example
|
|
||||||
[.] Clean+Fixes of canvas code and examples
|
|
||||||
|
|
||||||
[.] Make backend selection easier
|
[.] 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
|
[.] option macros to select backend-specific APIs to include when building an app
|
||||||
(ie, include gl_api.h when using gl backend)
|
(ie, include gl_api.h when using gl backend)
|
||||||
[x] surface/canvas functions that take a backend id
|
[ ] error on bad option macro combinations
|
||||||
[x] feature-detection functions to know what surface/canvas backends are available at run-time
|
[ ] write doc about backend option macros
|
||||||
[>] write doc about these options
|
|
||||||
|
|
||||||
[>] Image API and backend
|
[>] Image API and backend
|
||||||
[ ] Build image atlas on top
|
[ ] Build image atlas on top
|
||||||
|
@ -24,25 +18,36 @@ Overview
|
||||||
[/] Keep dummy window/dummy context around for gl context creation, and don't reload wgl functions every time
|
[/] Keep dummy window/dummy context around for gl context creation, and don't reload wgl functions every time
|
||||||
|
|
||||||
[.] Reintroduce GLES surface
|
[.] Reintroduce GLES surface
|
||||||
[ ] See how we can isolate platform-specific stuff and just deal with egl there..
|
[?] See how we can isolate platform-specific stuff and just deal with egl there...
|
||||||
|
|
||||||
[>] Back surface by child windows and implement moving frame/hiding/overlay
|
[.] Back surface by child windows and implement moving frame/hiding/overlay
|
||||||
|
[x] osx gles surface
|
||||||
|
[ ] Sort out gles contents scaling for high dpi
|
||||||
|
[ ] win32 opengl surfaces
|
||||||
|
[ ] win32 gles surface
|
||||||
|
|
||||||
[>] Check that we can make GLES and GL surfaces co-exist in the app
|
[/] could have an internal, per-platform mp_layer struct that handles resizing/hiding etc...
|
||||||
|
-> avoid duplication of frame/hiding and duplication of egl code.
|
||||||
|
|
||||||
[?] Backport canvas to GLES
|
[ ] then check that we can make GLES and GL surfaces co-exist in the app
|
||||||
|
|
||||||
|
[!] Make linking with libEGL optional, even if EGL backend is compiled in milepost?
|
||||||
|
[!] Bundle examples with their own resources?? (e.g. avoiding clashes in metal libs files in bin directory)
|
||||||
[!] Fix canvas shader precision issue on OSX
|
[!] Fix canvas shader precision issue on OSX
|
||||||
[!] Fix canvas perf issue on OSX
|
[!] Fix canvas perf issue on OSX
|
||||||
[!] osx: Remove need to include objc defs from osx_app.h in egl impl. Also properly guard angle backend attribute (must be metal on osx and default on win32)
|
[!] osx: Remove need to include objc defs from osx_app.h in egl impl. Also properly guard angle backend attribute (must be metal on osx and default on win32)
|
||||||
|
|
||||||
[ ] Delegated drawing API+Impl
|
[ ] Delegated drawing API+Impl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[ ] Make building apps simpler
|
[ ] Make building apps simpler
|
||||||
[ ] single include path
|
[ ] single include path
|
||||||
[ ] script for embedding dependencies / create app bundle
|
[ ] script for embedding dependencies / create app bundle
|
||||||
|
|
||||||
|
|
||||||
|
[?] Backport canvas to GLES
|
||||||
|
|
||||||
Clean+Fixes
|
Clean+Fixes
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue