From ac00cc9def962d990755e85020cc7931ad37fc26 Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Thu, 2 Mar 2023 19:21:39 +0100 Subject: [PATCH] [wip, win32 surface sharing] simplifyin the surface sharing API --- examples/surface_sharing/main.c | 15 +-- src/egl_surface.c | 29 +++-- src/egl_surface.h | 2 +- src/graphics.c | 23 +++- src/graphics.h | 18 +-- src/graphics_internal.h | 12 +- src/mp_app_internal.h | 17 +++ src/win32_app.c | 36 ++++++ src/win32_surface_sharing.c | 211 +++++++++----------------------- 9 files changed, 166 insertions(+), 197 deletions(-) diff --git a/examples/surface_sharing/main.c b/examples/surface_sharing/main.c index 83e01eb..62e237c 100644 --- a/examples/surface_sharing/main.c +++ b/examples/surface_sharing/main.c @@ -100,12 +100,10 @@ int child_main(int writeFd) mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_window window = mp_window_create(rect, "test", 0); - //NOTE: create surface server - mg_surface_server server = mg_surface_server_create(); - mg_surface_connection_id connectionID = mg_surface_server_id(server); - //NOTE: create surface - mg_surface surface = mg_surface_create_for_sharing(server, MG_BACKEND_GLES); + mg_surface surface = mg_surface_create_remote(800, 600, MG_BACKEND_GLES); + mg_surface_id connectionID = mg_surface_remote_id(surface); + mg_surface_prepare(surface); //NOTE: init shader and gl state @@ -232,8 +230,7 @@ int main(int argc, char** argv) mp_window window = mp_window_create(rect, "test", 0); //NOTE: create surface client - mg_surface surface = mg_surface_client_create_for_window(window); - + mg_surface surface = mg_surface_create_host(window); //NOTE setup descriptors int fileDesc[2]; @@ -248,12 +245,12 @@ int main(int argc, char** argv) process_id child = spawn_child(args[0], args); //NOTE: read the connection id - mg_surface_connection_id connectionID = 0; + mg_surface_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); + mg_surface_host_connect(surface, connectionID); //NOTE: show the window mp_window_bring_to_front(window); diff --git a/src/egl_surface.c b/src/egl_surface.c index 173fe8e..c8c1935 100644 --- a/src/egl_surface.c +++ b/src/egl_surface.c @@ -120,6 +120,13 @@ void* mg_egl_surface_native_layer(mg_surface_data* interface) return(mp_layer_native_surface(&surface->layer)); } +mg_surface_id mg_egl_surface_remote_id(mg_surface_data* interface) +{ + mg_egl_surface* surface = (mg_egl_surface*)interface; + //////////WARN: not portable, just for testing + return((mg_surface_id)surface->layer.hWnd); +} + ////////////////////////// // PIGMODE ////////////////////////// @@ -127,6 +134,7 @@ void* mg_egl_surface_native_layer(mg_surface_data* interface) void mg_egl_surface_init_for_native(mg_egl_surface* surface, void* nativeSurface) { 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; @@ -137,6 +145,7 @@ void mg_egl_surface_init_for_native(mg_egl_surface* surface, void* nativeSurface surface->interface.getHidden = mg_egl_surface_get_hidden; surface->interface.setHidden = mg_egl_surface_set_hidden; surface->interface.nativeLayer = mg_egl_surface_native_layer; + surface->interface.remoteId = mg_egl_surface_remote_id; EGLAttrib displayAttribs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, MG_EGL_PLATFORM_ANGLE_TYPE, @@ -185,21 +194,19 @@ void mg_egl_surface_init_for_native(mg_egl_surface* surface, void* nativeSurface eglSwapInterval(surface->eglDisplay, 1); } -mg_surface_data* mg_egl_surface_create_for_sharing(mg_surface_server handle) +mg_surface_data* mg_egl_surface_create_for_sharing(u32 width, u32 height) { mg_egl_surface* surface = 0; - mg_surface_server_data* server = mg_surface_server_data_from_handle(handle); - if(server) - { - surface = malloc_type(mg_egl_surface); - if(surface) - { - memset(surface, 0, sizeof(mg_egl_surface)); - surface->layer = server->layer; - mg_egl_surface_init_for_native(surface, mp_layer_native_surface(&surface->layer)); - } + surface = malloc_type(mg_egl_surface); + if(surface) + { + memset(surface, 0, sizeof(mg_egl_surface)); + + mp_layer_init_for_sharing(&surface->layer, width, height); + mg_egl_surface_init_for_native(surface, mp_layer_native_surface(&surface->layer)); } + return((mg_surface_data*)surface); } diff --git a/src/egl_surface.h b/src/egl_surface.h index f59763f..8cd3fdb 100644 --- a/src/egl_surface.h +++ b/src/egl_surface.h @@ -13,6 +13,6 @@ #include"mp_app.h" mg_surface_data* mg_egl_surface_create_for_window(mp_window window); -mg_surface_data* mg_egl_surface_create_for_sharing(mg_surface_server handle); +mg_surface_data* mg_egl_surface_create_for_sharing(u32 width, u32 height); #endif // __EGL_SURFACE_H_ diff --git a/src/graphics.c b/src/graphics.c index 1d930f4..79e6f90 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -459,7 +459,7 @@ mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend) return(surfaceHandle); } -mg_surface mg_surface_create_for_sharing(mg_surface_server server, mg_backend_id backend) +mg_surface mg_surface_create_remote(u32 width, u32 height, mg_backend_id backend) { if(__mgData.init) { @@ -472,7 +472,7 @@ mg_surface mg_surface_create_for_sharing(mg_surface_server server, mg_backend_id { #if MG_COMPILE_BACKEND_GLES case MG_BACKEND_GLES: - surface = mg_egl_surface_create_for_sharing(server); + surface = mg_egl_surface_create_for_sharing(width, height); break; #endif @@ -484,7 +484,26 @@ mg_surface mg_surface_create_for_sharing(mg_surface_server server, mg_backend_id surfaceHandle = mg_surface_handle_alloc(surface); } return(surfaceHandle); +} +mg_surface_id mg_surface_remote_id(mg_surface handle) +{ + mg_surface_id remoteId = 0; + mg_surface_data* surface = mg_surface_data_from_handle(handle); + if(surface && surface->remoteId) + { + remoteId = surface->remoteId(surface); + } + return(remoteId); +} + +void mg_surface_host_connect(mg_surface handle, mg_surface_id remoteID) +{ + mg_surface_data* surface = mg_surface_data_from_handle(handle); + if(surface && surface->connect) + { + surface->connect(surface, remoteID); + } } void mg_surface_destroy(mg_surface handle) diff --git a/src/graphics.h b/src/graphics.h index 3cc1a9a..a5f7e7f 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -102,21 +102,13 @@ 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 sharing -//------------------------------------------------------------------------------------------ +typedef u64 mg_surface_id; -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_id(mg_surface_server server); - -MP_API mg_surface mg_surface_create_for_sharing(mg_surface_server server, mg_backend_id backend); - -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 mg_surface mg_surface_create_remote(u32 width, u32 height, mg_backend_id backend); +MP_API mg_surface mg_surface_create_host(mp_window window); +MP_API mg_surface_id mg_surface_remote_id(mg_surface surface); +MP_API void mg_surface_host_connect(mg_surface surface, mg_surface_id remoteId); //------------------------------------------------------------------------------------------ //NOTE(martin): graphics canvas structs diff --git a/src/graphics_internal.h b/src/graphics_internal.h index d50685e..50efdbf 100644 --- a/src/graphics_internal.h +++ b/src/graphics_internal.h @@ -15,14 +15,6 @@ extern "C" { #endif - -typedef struct mg_surface_server_data -{ - mp_layer layer; - -} mg_surface_server_data; - -mg_surface_server_data* mg_surface_server_data_from_handle(mg_surface_server handle); //--------------------------------------------------------------- // surface interface //--------------------------------------------------------------- @@ -38,6 +30,8 @@ typedef void (*mg_surface_set_frame_proc)(mg_surface_data* surface, mp_rect fram 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 mg_surface_id (*mg_surface_remote_id_proc)(mg_surface_data* surface); +typedef void (*mg_surface_connect_proc)(mg_surface_data* surface, mg_surface_id remoteId); typedef struct mg_surface_data { @@ -53,6 +47,8 @@ typedef struct mg_surface_data mg_surface_get_hidden_proc getHidden; mg_surface_set_hidden_proc setHidden; mg_surface_native_layer_proc nativeLayer; + mg_surface_remote_id_proc remoteId; + mg_surface_connect_proc connect; } mg_surface_data; mg_surface mg_surface_alloc_handle(mg_surface_data* surface); diff --git a/src/mp_app_internal.h b/src/mp_app_internal.h index 8489e70..70dccf3 100644 --- a/src/mp_app_internal.h +++ b/src/mp_app_internal.h @@ -150,4 +150,21 @@ typedef struct mp_app MP_PLATFORM_APP_DATA } mp_app; +//-------------------------------------------------------------------- +// layer management +//-------------------------------------------------------------------- + +typedef struct mp_layer mp_layer; +void mp_layer_init_for_window(mp_layer* layer, mp_window_data* window); +void mp_layer_init_for_sharing(mp_layer* layer, u32 width, u32 height); +void mp_layer_cleanup(mp_layer* layer); + +vec2 mp_layer_contents_scaling(mp_layer* layer); +mp_rect mp_layer_get_frame(mp_layer* layer); +void mp_layer_set_frame(mp_layer* layer, mp_rect frame); +void mp_layer_set_hidden(mp_layer* layer, bool hidden); +bool mp_layer_get_hidden(mp_layer* layer); + +void* mp_layer_native_surface(mp_layer* layer); + #endif // __MP_APP_INTERNAL_H_ diff --git a/src/win32_app.c b/src/win32_app.c index ef665c6..8ee0bc8 100644 --- a/src/win32_app.c +++ b/src/win32_app.c @@ -804,6 +804,42 @@ void mp_layer_init_for_window(mp_layer* layer, mp_window_data* window) 0); } +void mp_layer_init_for_sharing(mp_layer* layer, u32 width, u32 height) +{ + WNDCLASS layerWindowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, + .lpfnWndProc = DefWindowProc, + .hInstance = GetModuleHandleW(NULL), + .lpszClassName = "server_layer_window_class", + .hCursor = LoadCursor(0, IDC_ARROW)}; + + RegisterClass(&layerWindowClass); + + //NOTE(martin): create a temporary parent window. This seems like a necessary hack, because if layer window is created as + // a normal window first, and then parented to the client window, it breaks resizing the parent + // window for some reason... + HWND tmpParent = CreateWindow("server_layer_window_class", "layerParent", + WS_OVERLAPPED, + 0, 0, width, height, + 0, + 0, + layerWindowClass.hInstance, + 0); + + //NOTE: create the layer window + layer->hWnd = CreateWindowEx(WS_EX_NOACTIVATE, + "server_layer_window_class", "layer", + WS_CHILD, + 0, 0, width, height, + tmpParent, + 0, + layerWindowClass.hInstance, + 0); + + //NOTE: unparent it and destroy tmp parent + SetParent(layer->hWnd, 0); + DestroyWindow(tmpParent); +} + void mp_layer_cleanup(mp_layer* layer) { DestroyWindow(layer->hWnd); diff --git a/src/win32_surface_sharing.c b/src/win32_surface_sharing.c index e0dd5de..517c6f3 100644 --- a/src/win32_surface_sharing.c +++ b/src/win32_surface_sharing.c @@ -8,156 +8,67 @@ *****************************************************************/ #include"graphics_internal.h" -//------------------------------------------------------------------------------------------------ -// Surface server -//------------------------------------------------------------------------------------------------ - -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); - - //NOTE(martin): create a child window for the surface - WNDCLASS layerWindowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, - .lpfnWndProc = DefWindowProc, - .hInstance = GetModuleHandleW(NULL), - .lpszClassName = "server_layer_window_class", - .hCursor = LoadCursor(0, IDC_ARROW)}; - - RegisterClass(&layerWindowClass); - -// RECT parentRect; -// GetClientRect(window->win32.hWnd, &parentRect); - -// int width = parentRect.right - parentRect.left; -// int height = parentRect.bottom - parentRect.top; - - int width = 200; - int height = 200; - - //NOTE(martin): create dummy window - HWND dummyParent = CreateWindow("server_layer_window_class", "layerParent", - WS_OVERLAPPED, - 0, 0, width, height, - 0, - 0, - layerWindowClass.hInstance, - 0); - - server->layer.hWnd = CreateWindowEx(WS_EX_NOACTIVATE, - "server_layer_window_class", "layer", - WS_CHILD, - 0, 0, width, height, - dummyParent, - 0, - layerWindowClass.hInstance, - 0); - - - SetParent(server->layer.hWnd, 0); - - DestroyWindow(dummyParent); -/* - mp_window window = mp_window_create((mp_rect){0, 0, 100, 100}, "server", 0); - mp_layer_init_for_window(&server->layer, mp_window_ptr_from_handle(window)); -*/ - 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) - { - //TODO - - free(server); - mg_handle_recycle(handle.h); - } -} - -MP_API mg_surface_connection_id mg_surface_server_id(mg_surface_server handle) -{ - mg_surface_connection_id res = 0; - - mg_surface_server_data* server = mg_surface_server_data_from_handle(handle); - if(server) - { - //NOTE: just a quick test - HWND layerWindow = (HWND)mp_layer_native_surface(&server->layer); - res = (mg_surface_connection_id)layerWindow; - //res = (mg_surface_connection_id)GetParent(layerWindow); - } - return(res); -} - //------------------------------------------------------------------------------------------------ // Surface client //------------------------------------------------------------------------------------------------ -typedef struct mg_win32_surface_client +typedef struct mg_win32_surface_host { mg_surface_data interface; mp_layer layer; -} mg_win32_surface_client; +} mg_win32_surface_host; -void mg_win32_surface_client_prepare(mg_surface_data* interface) +void mg_win32_surface_host_prepare(mg_surface_data* interface) {} -void mg_win32_surface_client_present(mg_surface_data* interface) +void mg_win32_surface_host_present(mg_surface_data* interface) {} -void mg_win32_surface_client_swap_interval(mg_surface_data* interface, int swap) +void mg_win32_surface_host_swap_interval(mg_surface_data* interface, int swap) { //TODO } -vec2 mg_win32_surface_client_contents_scaling(mg_surface_data* interface) +vec2 mg_win32_surface_host_contents_scaling(mg_surface_data* interface) { - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; return(mp_layer_contents_scaling(&surface->layer)); } -mp_rect mg_win32_surface_client_get_frame(mg_surface_data* interface) +mp_rect mg_win32_surface_host_get_frame(mg_surface_data* interface) { - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; return(mp_layer_get_frame(&surface->layer)); } -void mg_win32_surface_client_set_frame(mg_surface_data* interface, mp_rect frame) +void mg_win32_surface_host_set_frame(mg_surface_data* interface, mp_rect frame) { - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; mp_layer_set_frame(&surface->layer, frame); } -void mg_win32_surface_client_set_hidden(mg_surface_data* interface, bool hidden) +void mg_win32_surface_host_set_hidden(mg_surface_data* interface, bool hidden) { - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; mp_layer_set_hidden(&surface->layer, hidden); } -bool mg_win32_surface_client_get_hidden(mg_surface_data* interface) +bool mg_win32_surface_host_get_hidden(mg_surface_data* interface) { - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; return(mp_layer_get_hidden(&surface->layer)); } -void* mg_win32_surface_client_native_layer(mg_surface_data* interface) +void* mg_win32_surface_host_native_layer(mg_surface_data* interface) { - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; return(mp_layer_native_surface(&surface->layer)); } -void mg_win32_surface_client_destroy(mg_surface_data* interface) +void mg_win32_surface_host_destroy(mg_surface_data* interface) { - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; mp_layer_cleanup(&surface->layer); //TODO... @@ -165,76 +76,70 @@ void mg_win32_surface_client_destroy(mg_surface_data* interface) free(surface); } -mg_surface_data* mg_win32_surface_client_create_for_window(mp_window window) +MP_API void mg_win32_surface_host_connect(mg_surface_data* interface, mg_surface_id ID) { - mg_win32_surface_client* surface = 0; + mg_win32_surface_host* surface = (mg_win32_surface_host*)interface; + + //NOTE:Quick test + HWND dstWnd = mp_layer_native_surface(&surface->layer); + HWND srcWnd = (HWND)ID; + + RECT dstRect; + GetClientRect(dstWnd, &dstRect); + + SetParent(srcWnd, dstWnd); + ShowWindow(srcWnd, SW_NORMAL); + + SetWindowPos(srcWnd, + HWND_TOP, + 0, + 0, + dstRect.right - dstRect.left, + dstRect.bottom - dstRect.top, + SWP_NOACTIVATE | SWP_NOZORDER); +} + +mg_surface_data* mg_win32_surface_create_host(mp_window window) +{ + mg_win32_surface_host* surface = 0; mp_window_data* windowData = mp_window_ptr_from_handle(window); if(windowData) { - surface = malloc_type(mg_win32_surface_client); + surface = malloc_type(mg_win32_surface_host); if(surface) { mp_layer_init_for_window(&surface->layer, windowData); surface->interface.backend = MG_BACKEND_REMOTE; - surface->interface.destroy = mg_win32_surface_client_destroy; - surface->interface.prepare = mg_win32_surface_client_prepare; - surface->interface.present = mg_win32_surface_client_present; - surface->interface.swapInterval = mg_win32_surface_client_swap_interval; - surface->interface.contentsScaling = mg_win32_surface_client_contents_scaling; - surface->interface.getFrame = mg_win32_surface_client_get_frame; - surface->interface.setFrame = mg_win32_surface_client_set_frame; - surface->interface.getHidden = mg_win32_surface_client_get_hidden; - surface->interface.setHidden = mg_win32_surface_client_set_hidden; - surface->interface.nativeLayer = mg_win32_surface_client_native_layer; - + surface->interface.destroy = mg_win32_surface_host_destroy; + surface->interface.prepare = mg_win32_surface_host_prepare; + surface->interface.present = mg_win32_surface_host_present; + surface->interface.swapInterval = mg_win32_surface_host_swap_interval; + surface->interface.contentsScaling = mg_win32_surface_host_contents_scaling; + surface->interface.getFrame = mg_win32_surface_host_get_frame; + surface->interface.setFrame = mg_win32_surface_host_set_frame; + surface->interface.getHidden = mg_win32_surface_host_get_hidden; + surface->interface.setHidden = mg_win32_surface_host_set_hidden; + surface->interface.nativeLayer = mg_win32_surface_host_native_layer; + surface->interface.connect = mg_win32_surface_host_connect; //TODO } } return((mg_surface_data*)surface); } -mg_surface mg_surface_client_create_for_window(mp_window window) +mg_surface mg_surface_create_host(mp_window window) { if(!__mgData.init) { mg_init(); } mg_surface surfaceHandle = {0}; - mg_surface_data* surface = mg_win32_surface_client_create_for_window(window); + mg_surface_data* surface = mg_win32_surface_create_host(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_win32_surface_client* surface = (mg_win32_surface_client*)interface; - - //NOTE:Quick test - HWND dstWnd = mp_layer_native_surface(&surface->layer); - HWND srcWnd = (HWND)ID; - - RECT dstRect; - GetClientRect(dstWnd, &dstRect); - - SetParent(srcWnd, dstWnd); - ShowWindow(srcWnd, SW_NORMAL); -// SetWindowLongPtr(srcWnd, GWL_STYLE, WS_CHILD|WS_VISIBLE); - - SetWindowPos(srcWnd, - HWND_TOP, - 0, - 0, - dstRect.right - dstRect.left, - dstRect.bottom - dstRect.top, - SWP_NOACTIVATE | SWP_NOZORDER); - - } -}