[surface] graphics surface sharing API + osx implementation
This commit is contained in:
parent
28f5af32fa
commit
43d413dbbc
|
@ -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
|
|
@ -0,0 +1,238 @@
|
||||||
|
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<string.h>
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
|
||||||
|
#include<math.h>
|
||||||
|
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<stdio.h>
|
||||||
|
#include<unistd.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
|
@ -114,6 +114,12 @@ bool mg_egl_surface_get_hidden(mg_surface_data* interface)
|
||||||
return(mp_layer_get_hidden(&surface->layer));
|
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_surface_data* mg_egl_surface_create_for_window(mp_window window)
|
||||||
{
|
{
|
||||||
mg_egl_surface* surface = 0;
|
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.setFrame = mg_egl_surface_set_frame;
|
||||||
surface->interface.getHidden = mg_egl_surface_get_hidden;
|
surface->interface.getHidden = mg_egl_surface_get_hidden;
|
||||||
surface->interface.setHidden = mg_egl_surface_set_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);
|
mp_layer_init_for_window(&surface->layer, windowData);
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ typedef enum mg_handle_kind
|
||||||
MG_HANDLE_CANVAS,
|
MG_HANDLE_CANVAS,
|
||||||
MG_HANDLE_FONT,
|
MG_HANDLE_FONT,
|
||||||
MG_HANDLE_IMAGE,
|
MG_HANDLE_IMAGE,
|
||||||
|
MG_HANDLE_SURFACE_SERVER,
|
||||||
} mg_handle_kind;
|
} mg_handle_kind;
|
||||||
|
|
||||||
typedef struct mg_handle_slot
|
typedef struct mg_handle_slot
|
||||||
|
@ -556,6 +557,17 @@ bool mg_surface_get_hidden(mg_surface surface)
|
||||||
return(res);
|
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
|
//NOTE(martin): graphics canvas internal
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -21,7 +21,8 @@ typedef enum {
|
||||||
MG_BACKEND_NONE,
|
MG_BACKEND_NONE,
|
||||||
MG_BACKEND_METAL,
|
MG_BACKEND_METAL,
|
||||||
MG_BACKEND_GL,
|
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
|
//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
|
// 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 bool mg_surface_get_hidden(mg_surface surface);
|
||||||
MP_API void mg_surface_set_hidden(mg_surface surface, bool hidden);
|
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
|
//NOTE(martin): graphics canvas structs
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -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 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 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_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
|
typedef struct mg_surface_data
|
||||||
{
|
{
|
||||||
|
@ -43,11 +44,12 @@ typedef struct mg_surface_data
|
||||||
mg_surface_set_frame_proc setFrame;
|
mg_surface_set_frame_proc setFrame;
|
||||||
mg_surface_get_hidden_proc getHidden;
|
mg_surface_get_hidden_proc getHidden;
|
||||||
mg_surface_set_hidden_proc setHidden;
|
mg_surface_set_hidden_proc setHidden;
|
||||||
|
mg_surface_native_layer_proc nativeLayer;
|
||||||
} mg_surface_data;
|
} mg_surface_data;
|
||||||
|
|
||||||
mg_surface mg_surface_alloc_handle(mg_surface_data* surface);
|
mg_surface mg_surface_alloc_handle(mg_surface_data* surface);
|
||||||
mg_surface_data* mg_surface_data_from_handle(mg_surface handle);
|
mg_surface_data* mg_surface_data_from_handle(mg_surface handle);
|
||||||
|
void* mg_surface_native_layer(mg_surface surface);
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// canvas backend interface
|
// canvas backend interface
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include"egl_surface.c"
|
#include"egl_surface.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include"osx_surface_sharing.m"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
*
|
*
|
||||||
* @file: graphics.m
|
* @file: mtl_surface.m
|
||||||
* @author: Martin Fouilleul
|
* @author: Martin Fouilleul
|
||||||
* @date: 12/07/2020
|
* @date: 12/07/2023
|
||||||
* @revision:
|
* @revision:
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
@ -162,6 +162,12 @@ bool mg_mtl_surface_get_hidden(mg_surface_data* interface)
|
||||||
return(mp_layer_get_hidden(&surface->layer));
|
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
|
//TODO fix that according to real scaling, depending on the monitor settings
|
||||||
static const f32 MG_MTL_SURFACE_CONTENTS_SCALING = 2;
|
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.setFrame = mg_mtl_surface_set_frame;
|
||||||
surface->interface.getHidden = mg_mtl_surface_get_hidden;
|
surface->interface.getHidden = mg_mtl_surface_get_hidden;
|
||||||
surface->interface.setHidden = mg_mtl_surface_set_hidden;
|
surface->interface.setHidden = mg_mtl_surface_set_hidden;
|
||||||
|
surface->interface.nativeLayer = mg_mtl_surface_native_layer;
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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];
|
||||||
|
}
|
||||||
|
}
|
|
@ -189,6 +189,12 @@ bool mg_wgl_surface_get_hidden(mg_surface_data* interface)
|
||||||
return(mp_layer_get_hidden(&surface->layer));
|
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* mg_wgl_get_proc(const char* name)
|
||||||
{
|
{
|
||||||
void* p = wglGetProcAddress(name);
|
void* p = wglGetProcAddress(name);
|
||||||
|
|
Loading…
Reference in New Issue