From 43d413dbbcd4536ccdd4088bd1062f6f9bdc204c Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Wed, 1 Mar 2023 16:15:36 +0100 Subject: [PATCH] [surface] graphics surface sharing API + osx implementation --- examples/surface_sharing/build.sh | 12 ++ examples/surface_sharing/main.c | 238 ++++++++++++++++++++++++++++ src/egl_surface.c | 7 + src/graphics.c | 12 ++ src/graphics.h | 19 ++- src/graphics_internal.h | 4 +- src/milepost.m | 2 + src/mtl_surface.m | 11 +- src/osx_surface_client.m | 160 ------------------- src/osx_surface_sharing.m | 250 ++++++++++++++++++++++++++++++ src/wgl_surface.c | 6 + 11 files changed, 557 insertions(+), 164 deletions(-) create mode 100755 examples/surface_sharing/build.sh create mode 100644 examples/surface_sharing/main.c delete mode 100644 src/osx_surface_client.m create mode 100644 src/osx_surface_sharing.m diff --git a/examples/surface_sharing/build.sh b/examples/surface_sharing/build.sh new file mode 100755 index 0000000..efd3018 --- /dev/null +++ b/examples/surface_sharing/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +BINDIR=../../bin +RESDIR=../../resources +SRCDIR=../../src +EXTDIR=../../ext + +INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR" +LIBS="-L$BINDIR -lmilepost" +FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG" + +clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_surface_sharing main.c diff --git a/examples/surface_sharing/main.c b/examples/surface_sharing/main.c new file mode 100644 index 0000000..ad87f50 --- /dev/null +++ b/examples/surface_sharing/main.c @@ -0,0 +1,238 @@ + +#include +#include + +#define _USE_MATH_DEFINES //NOTE: necessary for MSVC +#include + +#include +#include +#include + +#define MG_INCLUDE_GL_API 1 +#include"milepost.h" + +#define LOG_SUBSYSTEM "Main" + +unsigned int program; + +const char* vshaderSource = + //"#version 320 es\n" + "attribute vec4 vPosition;\n" + "uniform mat4 transform;\n" + "void main()\n" + "{\n" + " gl_Position = transform*vPosition;\n" + "}\n"; + +const char* fshaderSource = + //"#version 320 es\n" + "precision mediump float;\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + "}\n"; + +void compile_shader(GLuint shader, const char* source) +{ + glShaderSource(shader, 1, &source, 0); + glCompileShader(shader); + + int err = glGetError(); + if(err) + { + printf("gl error: %i\n", err); + } + + int status = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if(!status) + { + char buffer[256]; + int size = 0; + glGetShaderInfoLog(shader, 256, &size, buffer); + printf("shader error: %.*s\n", size, buffer); + } +} + +int child_main() +{ + mp_init(); + + mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; + mp_window window = mp_window_create(rect, "test", 0); + + //NOTE: create surface + mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_GLES); + mg_surface_prepare(surface); + + //NOTE: init shader and gl state + mg_surface_prepare(surface); + + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + GLuint vertexBuffer; + glGenBuffers(1, &vertexBuffer); + + GLfloat vertices[] = { + -0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; + + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + + unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); + unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); + program = glCreateProgram(); + + compile_shader(vshader, vshaderSource); + compile_shader(fshader, fshaderSource); + + glAttachShader(program, vshader); + glAttachShader(program, fshader); + glLinkProgram(program); + + int status = 0; + glGetProgramiv(program, GL_LINK_STATUS, &status); + if(!status) + { + char buffer[256]; + int size = 0; + glGetProgramInfoLog(program, 256, &size, buffer); + printf("link error: %.*s\n", size, buffer); + } + + glUseProgram(program); + + //NOTE: create surface server and start sharing surface + mg_surface_server server = mg_surface_server_create(); + mg_surface_connection_id connectionID = mg_surface_server_start(server, surface); + + //NOTE: send context id to parent + write(3, &connectionID, sizeof(connectionID)); + + //NOTE: render loop + while(!mp_should_quit()) + { + mp_pump_events(0); + mp_event event = {0}; + while(mp_next_event(&event)) + { + switch(event.type) + { + case MP_EVENT_WINDOW_CLOSE: + { + mp_request_quit(); + } break; + + default: + break; + } + } + + mg_surface_prepare(surface); + + glClearColor(0.3, 0.3, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + static float alpha = 0; + //f32 aspect = frameSize.x/frameSize.y; + f32 aspect = 800/(f32)600; + + GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0, + -sinf(alpha)/aspect, cosf(alpha), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + alpha += 2*M_PI/120; + + glUniformMatrix4fv(0, 1, false, matrix); + + + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(0); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + mg_surface_present(surface); + } + + mp_terminate(); + + return(0); +} + +int main(int argc, char** argv) +{ + LogLevel(LOG_LEVEL_DEBUG); + + if(argc > 1) + { + if(!strcmp(argv[1], "--child")) + { + return(child_main()); + } + else + { + return(-1); + } + } + mp_init(); + + //NOTE: create main window + mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; + mp_window window = mp_window_create(rect, "test", 0); + + //NOTE: create surface client + mg_surface surface = mg_surface_client_create_for_window(window); + + + //TODO setup descriptors + int fileDesc[2]; + pipe(fileDesc); + + pid_t pid = fork(); + if(!pid) + { + dup2(fileDesc[1], 3); + char* argv[] = {"bin/example_surface_sharing", "--child", 0}; + char* envp[] = {0}; + execve("./bin/example_surface_sharing", argv, envp); + assert(0); + } + + //NOTE: read the connection id + mg_surface_connection_id connectionID = 0; + read(fileDesc[0], &connectionID, sizeof(connectionID)); + printf("received child connection id %llu\n", connectionID); + + //NOTE: connect the client + mg_surface_client_connect(surface, connectionID); + + //NOTE: show the window + mp_window_bring_to_front(window); + + while(!mp_should_quit()) + { + mp_pump_events(0); + mp_event event = {0}; + while(mp_next_event(&event)) + { + switch(event.type) + { + case MP_EVENT_WINDOW_CLOSE: + { + mp_request_quit(); + } break; + + default: + break; + } + } + } + mp_terminate(); + return(0); +} diff --git a/src/egl_surface.c b/src/egl_surface.c index 33c220c..a3021f3 100644 --- a/src/egl_surface.c +++ b/src/egl_surface.c @@ -114,6 +114,12 @@ bool mg_egl_surface_get_hidden(mg_surface_data* interface) return(mp_layer_get_hidden(&surface->layer)); } +void* mg_egl_surface_native_layer(mg_surface_data* interface) +{ + mg_egl_surface* surface = (mg_egl_surface*)interface; + return(mp_layer_native_surface(&surface->layer)); +} + mg_surface_data* mg_egl_surface_create_for_window(mp_window window) { mg_egl_surface* surface = 0; @@ -133,6 +139,7 @@ mg_surface_data* mg_egl_surface_create_for_window(mp_window window) 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.nativeLayer = mg_egl_surface_native_layer; mp_layer_init_for_window(&surface->layer, windowData); diff --git a/src/graphics.c b/src/graphics.c index b0bac69..39cd4fc 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -154,6 +154,7 @@ typedef enum mg_handle_kind MG_HANDLE_CANVAS, MG_HANDLE_FONT, MG_HANDLE_IMAGE, + MG_HANDLE_SURFACE_SERVER, } mg_handle_kind; typedef struct mg_handle_slot @@ -556,6 +557,17 @@ bool mg_surface_get_hidden(mg_surface surface) 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) + { + res = surfaceData->nativeLayer(surfaceData); + } + return(res); +} + //------------------------------------------------------------------------------------------ //NOTE(martin): graphics canvas internal //------------------------------------------------------------------------------------------ diff --git a/src/graphics.h b/src/graphics.h index 00fc5fe..822da6e 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -21,7 +21,8 @@ typedef enum { MG_BACKEND_NONE, MG_BACKEND_METAL, MG_BACKEND_GL, - MG_BACKEND_GLES } mg_backend_id; + MG_BACKEND_GLES, + MG_BACKEND_REMOTE } mg_backend_id; //NOTE: these macros are used to select which backend to include when building milepost // they can be overridden by passing them to the compiler command line @@ -101,6 +102,22 @@ MP_API void mg_surface_set_frame(mg_surface surface, mp_rect frame); MP_API bool mg_surface_get_hidden(mg_surface surface); MP_API void mg_surface_set_hidden(mg_surface surface, bool hidden); +//------------------------------------------------------------------------------------------ +//NOTE(martin): surface server/client +//------------------------------------------------------------------------------------------ + +typedef struct mg_surface_server { u64 h; } mg_surface_server; +typedef u64 mg_surface_connection_id; + +MP_API mg_surface_server mg_surface_server_create(void); +MP_API void mg_surface_server_destroy(mg_surface_server server); +MP_API mg_surface_connection_id mg_surface_server_start(mg_surface_server server, mg_surface surface); +MP_API void mg_surface_server_stop(mg_surface_server server); + +MP_API mg_surface mg_surface_client_create_for_window(mp_window window); +MP_API void mg_surface_client_connect(mg_surface surface, mg_surface_connection_id id); +MP_API void mg_surface_client_disconnect(mg_surface surface); + //------------------------------------------------------------------------------------------ //NOTE(martin): graphics canvas structs //------------------------------------------------------------------------------------------ diff --git a/src/graphics_internal.h b/src/graphics_internal.h index 395e280..641b514 100644 --- a/src/graphics_internal.h +++ b/src/graphics_internal.h @@ -29,6 +29,7 @@ typedef mp_rect (*mg_surface_get_frame_proc)(mg_surface_data* surface); typedef void (*mg_surface_set_frame_proc)(mg_surface_data* surface, mp_rect frame); typedef bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface); typedef void (*mg_surface_set_hidden_proc)(mg_surface_data* surface, bool hidden); +typedef void* (*mg_surface_native_layer_proc)(mg_surface_data* surface); typedef struct mg_surface_data { @@ -43,11 +44,12 @@ typedef struct mg_surface_data mg_surface_set_frame_proc setFrame; mg_surface_get_hidden_proc getHidden; mg_surface_set_hidden_proc setHidden; - + mg_surface_native_layer_proc nativeLayer; } mg_surface_data; mg_surface mg_surface_alloc_handle(mg_surface_data* surface); mg_surface_data* mg_surface_data_from_handle(mg_surface handle); +void* mg_surface_native_layer(mg_surface surface); //--------------------------------------------------------------- // canvas backend interface diff --git a/src/milepost.m b/src/milepost.m index 3c41b2b..6130a67 100644 --- a/src/milepost.m +++ b/src/milepost.m @@ -20,6 +20,8 @@ #include"egl_surface.c" #endif +#include"osx_surface_sharing.m" + /* #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" diff --git a/src/mtl_surface.m b/src/mtl_surface.m index c155081..8a9ea72 100644 --- a/src/mtl_surface.m +++ b/src/mtl_surface.m @@ -1,8 +1,8 @@ /************************************************************//** * -* @file: graphics.m +* @file: mtl_surface.m * @author: Martin Fouilleul -* @date: 12/07/2020 +* @date: 12/07/2023 * @revision: * *****************************************************************/ @@ -162,6 +162,12 @@ bool mg_mtl_surface_get_hidden(mg_surface_data* interface) return(mp_layer_get_hidden(&surface->layer)); } +void* mg_mtl_surface_native_layer(mg_surface_data* interface) +{ + mg_mtl_surface* surface = (mg_mtl_surface*)interface; + return((void*)surface->mtlLayer); +} + //TODO fix that according to real scaling, depending on the monitor settings static const f32 MG_MTL_SURFACE_CONTENTS_SCALING = 2; @@ -184,6 +190,7 @@ mg_surface_data* mg_mtl_surface_create_for_window(mp_window window) surface->interface.setFrame = mg_mtl_surface_set_frame; surface->interface.getHidden = mg_mtl_surface_get_hidden; surface->interface.setHidden = mg_mtl_surface_set_hidden; + surface->interface.nativeLayer = mg_mtl_surface_native_layer; @autoreleasepool { diff --git a/src/osx_surface_client.m b/src/osx_surface_client.m deleted file mode 100644 index c97fa37..0000000 --- a/src/osx_surface_client.m +++ /dev/null @@ -1,160 +0,0 @@ -/************************************************************//** -* -* @file: osx_surface_client.cpp -* @author: Martin Fouilleul -* @date: 19/08/2022 -* @revision: -* -*****************************************************************/ - -#include"graphics_internal.h" - -//------------------------------------------------------------------------------------------------ -// private interfaces that need to be declared explicitly... -typedef uint32_t CGSConnectionID; -CGSConnectionID CGSMainConnectionID(void); - -typedef uint32_t CAContextID; - -@interface CAContext : NSObject -{ -} -+ (id)contextWithCGSConnection:(CAContextID)contextId options:(NSDictionary*)optionsDict; -@property(readonly) CAContextID contextId; -@property(retain) CALayer *layer; -@end - -@interface CALayerHost : CALayer -{ -} -@property CAContextID contextId; -@end -//------------------------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------------------------ -// Surface server -//------------------------------------------------------------------------------------------------ - -typedef struct mg_gles_surface_server -{ - mg_surface_server_info interface; - CAContext* context; -} mg_gles_surface_server; - -void mg_gles_surface_server_destroy(mg_surface_server_info* interface) -{ - mg_gles_surface_server* server = (mg_gles_surface_server*)interface; - @autoreleasepool - { - [server->context release]; - } -} - -mg_surface_server_id mg_gles_surface_server_get_id(mg_surface_server_info* interface) -{ - mg_gles_surface_server* server = (mg_gles_surface_server*)interface; - - @autoreleasepool - { - CAContextID contextID = [server->context contextId]; - return((void*)(uintptr_t)contextID); - } -} - -mg_surface_server mg_gles_surface_create_server(mg_surface_info* interface) -{@autoreleasepool{ - - mg_gles_surface* surface = (mg_gles_surface*)interface; - - mg_gles_surface_server* server = malloc_type(mg_gles_surface_server); - server->interface.destroy = mg_gles_surface_server_destroy; - server->interface.getID = mg_gles_surface_server_get_id; - - NSDictionary* dict = [[NSDictionary alloc] init]; - CGSConnectionID connectionID = CGSMainConnectionID(); - server->context = [CAContext contextWithCGSConnection: connectionID options: dict]; - [server->context retain]; - [server->context setLayer: surface->layer]; - - mg_surface_server handle = mg_surface_server_alloc_handle((mg_surface_server_info*)server); - return(handle); -}} - - -mg_surface_server mg_gles_surface_server_create_native(void* p) -{@autoreleasepool{ - - mg_gles_surface_server* server = malloc_type(mg_gles_surface_server); - server->interface.destroy = mg_gles_surface_server_destroy; - server->interface.getID = mg_gles_surface_server_get_id; - - NSDictionary* dict = [[NSDictionary alloc] init]; - CGSConnectionID connectionID = CGSMainConnectionID(); - server->context = [CAContext contextWithCGSConnection: connectionID options: dict]; - [server->context retain]; - [server->context setLayer: (CALayer*)p]; - - mg_surface_server handle = mg_surface_server_alloc_handle((mg_surface_server_info*)server); - return(handle); -}} - -//------------------------------------------------------------------------------------------------ -// Surface client -//------------------------------------------------------------------------------------------------ -typedef struct mg_osx_surface_client -{ - mg_surface_client_info interface; - CALayerHost* layerHost; - -} mg_osx_surface_client; - -void mg_osx_surface_client_destroy(mg_surface_client_info* interface) -{ - mg_osx_surface_client* client = (mg_osx_surface_client*)interface; - @autoreleasepool - { - [client->layerHost release]; - } -} - -void mg_osx_surface_client_attach(mg_surface_client_info* interface) -{ - mg_osx_surface_client* client = (mg_osx_surface_client*)interface; - - mp_view_data* viewData = mp_view_ptr_from_handle(interface->attachment); - [viewData->nsView setWantsLayer:YES]; - - CGRect bounds = [viewData->nsView bounds]; - CALayer* layer = [viewData->nsView layer]; - [layer addSublayer:client->layerHost]; - - [client->layerHost setPosition:CGPointMake(bounds.size.width/2, bounds.size.height/2)]; -} - -void mg_osx_surface_client_detach(mg_surface_client_info* interface) -{ - mg_osx_surface_client* client = (mg_osx_surface_client*)interface; - - mp_view_data* viewData = mp_view_ptr_from_handle(interface->attachment); - [client->layerHost removeFromSuperlayer]; -} - -mg_surface_client mg_osx_surface_client_create(mg_surface_server_id ID) -{ - mg_osx_surface_client* client = malloc_type(mg_osx_surface_client); - - client->interface.destroy = mg_osx_surface_client_destroy; - client->interface.attach = mg_osx_surface_client_attach; - client->interface.detach = mg_osx_surface_client_detach; - - @autoreleasepool - { - CAContextID contextID = (CAContextID)((uintptr_t)ID); - - client->layerHost = [[CALayerHost alloc] init]; - [client->layerHost retain]; - [client->layerHost setContextId: contextID]; - } - mg_surface_client handle = mg_surface_client_alloc_handle((mg_surface_client_info*)client); - return(handle); -} diff --git a/src/osx_surface_sharing.m b/src/osx_surface_sharing.m new file mode 100644 index 0000000..719af80 --- /dev/null +++ b/src/osx_surface_sharing.m @@ -0,0 +1,250 @@ +/************************************************************//** +* +* @file: osx_surface_sharing.m +* @author: Martin Fouilleul +* @date: 19/08/2022 +* @revision: +* +*****************************************************************/ + +#include"graphics_internal.h" + +//------------------------------------------------------------------------------------------------ +//NOTE: these private interfaces need to be declared explicitly... +//------------------------------------------------------------------------------------------------ +typedef uint32_t CGSConnectionID; +CGSConnectionID CGSMainConnectionID(void); + +typedef uint32_t CAContextID; + +@interface CAContext : NSObject +{ +} ++ (id)contextWithCGSConnection:(CAContextID)contextId options:(NSDictionary*)optionsDict; +@property(readonly) CAContextID contextId; +@property(retain) CALayer *layer; +@end + +@interface CALayerHost : CALayer +{ +} +@property CAContextID contextId; +@end + + +//------------------------------------------------------------------------------------------------ +// Surface server +//------------------------------------------------------------------------------------------------ + +typedef struct mg_surface_server_data +{ + CAContext* context; +} mg_surface_server_data; + +mg_surface_server_data* mg_surface_server_data_from_handle(mg_surface_server handle) +{ + mg_surface_server_data* server = (mg_surface_server_data*)mg_data_from_handle(MG_HANDLE_SURFACE_SERVER, handle.h); + return(server); +} + +MP_API mg_surface_server mg_surface_server_create(void) +{ + mg_surface_server_data* server = malloc_type(mg_surface_server_data); + + @autoreleasepool + { + NSDictionary* dict = [[NSDictionary alloc] init]; + CGSConnectionID connectionID = CGSMainConnectionID(); + server->context = [CAContext contextWithCGSConnection: connectionID options: dict]; + [server->context retain]; + } + mg_surface_server handle = (mg_surface_server){mg_handle_alloc(MG_HANDLE_SURFACE_SERVER, (void*)server)}; + return(handle); +} + +MP_API void mg_surface_server_destroy(mg_surface_server handle) +{ + mg_surface_server_data* server = mg_surface_server_data_from_handle(handle); + if(server) + { + @autoreleasepool + { + [server->context release]; + } + free(server); + mg_handle_recycle(handle.h); + } +} + +MP_API mg_surface_connection_id mg_surface_server_start(mg_surface_server handle, mg_surface surface) +{ + mg_surface_connection_id res = 0; + + mg_surface_server_data* server = mg_surface_server_data_from_handle(handle); + if(server) + { + @autoreleasepool + { + CALayer* layer = mg_surface_native_layer(surface); + + [server->context setLayer: layer]; + CAContextID contextID = [server->context contextId]; + res = (mg_surface_connection_id)contextID; + } + } + return(res); +} + +MP_API void mg_surface_server_stop(mg_surface_server handle) +{ + mg_surface_server_data* server = mg_surface_server_data_from_handle(handle); + if(server) + { + @autoreleasepool + { + [server->context setLayer: nil]; + } + } +} + +//------------------------------------------------------------------------------------------------ +// Surface client +//------------------------------------------------------------------------------------------------ + +typedef struct mg_osx_surface_client +{ + mg_surface_data interface; + mp_layer layer; + CALayerHost* layerHost; +} mg_osx_surface_client; + +void mg_osx_surface_client_prepare(mg_surface_data* interface) +{} + +void mg_osx_surface_client_present(mg_surface_data* interface) +{} + +void mg_osx_surface_client_swap_interval(mg_surface_data* interface, int swap) +{ + //TODO +} + +vec2 mg_osx_surface_client_contents_scaling(mg_surface_data* interface) +{ + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + return(mp_layer_contents_scaling(&surface->layer)); +} + +mp_rect mg_osx_surface_client_get_frame(mg_surface_data* interface) +{ + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + return(mp_layer_get_frame(&surface->layer)); +} + +void mg_osx_surface_client_set_frame(mg_surface_data* interface, mp_rect frame) +{ + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + mp_layer_set_frame(&surface->layer, frame); +} + +void mg_osx_surface_client_set_hidden(mg_surface_data* interface, bool hidden) +{ + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + mp_layer_set_hidden(&surface->layer, hidden); +} + +bool mg_osx_surface_client_get_hidden(mg_surface_data* interface) +{ + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + return(mp_layer_get_hidden(&surface->layer)); +} + +void* mg_osx_surface_client_native_layer(mg_surface_data* interface) +{ + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + return(mp_layer_native_surface(&surface->layer)); +} + +void mg_osx_surface_client_destroy(mg_surface_data* interface) +{ + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + @autoreleasepool + { + [surface->layerHost release]; + } + free(surface); +} + +mg_surface_data* mg_osx_surface_client_create_for_window(mp_window window) +{ + mg_osx_surface_client* surface = 0; + + mp_window_data* windowData = mp_window_ptr_from_handle(window); + if(windowData) + { + surface = malloc_type(mg_osx_surface_client); + if(surface) + { + mp_layer_init_for_window(&surface->layer, windowData); + + surface->interface.backend = MG_BACKEND_REMOTE; + surface->interface.destroy = mg_osx_surface_client_destroy; + surface->interface.prepare = mg_osx_surface_client_prepare; + surface->interface.present = mg_osx_surface_client_present; + surface->interface.swapInterval = mg_osx_surface_client_swap_interval; + surface->interface.contentsScaling = mg_osx_surface_client_contents_scaling; + surface->interface.getFrame = mg_osx_surface_client_get_frame; + surface->interface.setFrame = mg_osx_surface_client_set_frame; + surface->interface.getHidden = mg_osx_surface_client_get_hidden; + surface->interface.setHidden = mg_osx_surface_client_set_hidden; + surface->interface.nativeLayer = mg_osx_surface_client_native_layer; + + @autoreleasepool + { + surface->layerHost = [[CALayerHost alloc] init]; + [surface->layerHost retain]; + + CALayer* caLayer = mp_layer_native_surface(&surface->layer); + [caLayer addSublayer:surface->layerHost]; + } + } + } + return((mg_surface_data*)surface); +} + +mg_surface mg_surface_client_create_for_window(mp_window window) +{ + if(!__mgData.init) + { + mg_init(); + } + mg_surface surfaceHandle = {0}; + mg_surface_data* surface = mg_osx_surface_client_create_for_window(window); + if(surface) + { + surfaceHandle = mg_surface_handle_alloc(surface); + } + return(surfaceHandle); +} + +MP_API void mg_surface_client_connect(mg_surface handle, mg_surface_connection_id ID) +{ + mg_surface_data* interface = mg_surface_data_from_handle(handle); + if(interface && interface->backend == MG_BACKEND_REMOTE) + { + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + + CAContextID contextID = (CAContextID)((uintptr_t)ID); + [surface->layerHost setContextId: contextID]; + } +} + +MP_API void mg_surface_client_disconnect(mg_surface handle) +{ + mg_surface_data* interface = mg_surface_data_from_handle(handle); + if(interface && interface->backend == MG_BACKEND_REMOTE) + { + mg_osx_surface_client* surface = (mg_osx_surface_client*)interface; + [surface->layerHost setContextId: 0]; + } +} diff --git a/src/wgl_surface.c b/src/wgl_surface.c index 6060f70..eea9875 100644 --- a/src/wgl_surface.c +++ b/src/wgl_surface.c @@ -189,6 +189,12 @@ bool mg_wgl_surface_get_hidden(mg_surface_data* interface) return(mp_layer_get_hidden(&surface->layer)); } +void* mg_wgl_surface_native_layer(mg_surface_data* interface) +{ + mg_wgl_surface* surface = (mg_wgl_surface*)interface; + return(mg_layer_native_surface(&surface->layer)); +} + void* mg_wgl_get_proc(const char* name) { void* p = wglGetProcAddress(name);