diff --git a/examples/surface_sharing/build.bat b/examples/surface_sharing/build.bat new file mode 100644 index 0000000..6a30ce4 --- /dev/null +++ b/examples/surface_sharing/build.bat @@ -0,0 +1,4 @@ + +set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers + +cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_surface_sharing.exe diff --git a/examples/surface_sharing/main.c b/examples/surface_sharing/main.c index 4a666e6..83e01eb 100644 --- a/examples/surface_sharing/main.c +++ b/examples/surface_sharing/main.c @@ -100,8 +100,12 @@ 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_window(window, MG_BACKEND_GLES); + mg_surface surface = mg_surface_create_for_sharing(server, MG_BACKEND_GLES); mg_surface_prepare(surface); //NOTE: init shader and gl state @@ -144,10 +148,6 @@ int child_main(int writeFd) 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(writeFd, &connectionID, sizeof(connectionID)); @@ -172,6 +172,10 @@ int child_main(int writeFd) mg_surface_prepare(surface); + mp_rect rect = mg_surface_get_frame(surface); + vec2 scaling = mg_surface_contents_scaling(surface); + + glViewport(0, 0, rect.w*scaling.x, rect.h*scaling.y); glClearColor(0.3, 0.3, 1, 1); glClear(GL_COLOR_BUFFER_BIT); diff --git a/src/egl_surface.c b/src/egl_surface.c index a3021f3..173fe8e 100644 --- a/src/egl_surface.c +++ b/src/egl_surface.c @@ -120,6 +120,89 @@ void* mg_egl_surface_native_layer(mg_surface_data* interface) return(mp_layer_native_surface(&surface->layer)); } +////////////////////////// +// PIGMODE +////////////////////////// + +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; + surface->interface.swapInterval = mg_egl_surface_swap_interval; + surface->interface.contentsScaling = mg_egl_surface_contents_scaling; + 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.nativeLayer = mg_egl_surface_native_layer; + + EGLAttrib displayAttribs[] = { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, MG_EGL_PLATFORM_ANGLE_TYPE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, + EGL_NONE}; + + 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, + mp_layer_native_surface(&surface->layer), + surfaceAttributes); + + eglBindAPI(EGL_OPENGL_ES_API); + EGLint contextAttributes[] = { + EGL_CONTEXT_MAJOR_VERSION_KHR, MG_GLES_VERSION_MAJOR, + EGL_CONTEXT_MINOR_VERSION_KHR, MG_GLES_VERSION_MINOR, + 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_gles(&surface->api, (mg_gl_load_proc)eglGetProcAddress); + + eglSwapInterval(surface->eglDisplay, 1); +} + +mg_surface_data* mg_egl_surface_create_for_sharing(mg_surface_server handle) +{ + 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)); + } + } + return((mg_surface_data*)surface); +} + mg_surface_data* mg_egl_surface_create_for_window(mp_window window) { mg_egl_surface* surface = 0; @@ -127,67 +210,13 @@ mg_surface_data* mg_egl_surface_create_for_window(mp_window window) if(windowData) { surface = malloc_type(mg_egl_surface); - memset(surface, 0, sizeof(mg_egl_surface)); + if(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.swapInterval = mg_egl_surface_swap_interval; - surface->interface.contentsScaling = mg_egl_surface_contents_scaling; - 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.nativeLayer = mg_egl_surface_native_layer; - - mp_layer_init_for_window(&surface->layer, windowData); - - EGLAttrib displayAttribs[] = { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, MG_EGL_PLATFORM_ANGLE_TYPE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, - EGL_NONE}; - - 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, - mp_layer_native_surface(&surface->layer), - surfaceAttributes); - - eglBindAPI(EGL_OPENGL_ES_API); - EGLint contextAttributes[] = { - EGL_CONTEXT_MAJOR_VERSION_KHR, MG_GLES_VERSION_MAJOR, - EGL_CONTEXT_MINOR_VERSION_KHR, MG_GLES_VERSION_MINOR, - 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_gles(&surface->api, (mg_gl_load_proc)eglGetProcAddress); - - eglSwapInterval(surface->eglDisplay, 1); + mp_layer_init_for_window(&surface->layer, windowData); + 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 698410b..f59763f 100644 --- a/src/egl_surface.h +++ b/src/egl_surface.h @@ -13,5 +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); #endif // __EGL_SURFACE_H_ diff --git a/src/graphics.c b/src/graphics.c index 39cd4fc..1d930f4 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -459,6 +459,34 @@ 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) +{ + if(__mgData.init) + { + mg_init(); + } + mg_surface surfaceHandle = mg_surface_nil(); + mg_surface_data* surface = 0; + + switch(backend) + { + #if MG_COMPILE_BACKEND_GLES + case MG_BACKEND_GLES: + surface = mg_egl_surface_create_for_sharing(server); + break; + #endif + + default: + break; + } + if(surface) + { + surfaceHandle = mg_surface_handle_alloc(surface); + } + return(surfaceHandle); + +} + void mg_surface_destroy(mg_surface handle) { DEBUG_ASSERT(__mgData.init); diff --git a/src/graphics.h b/src/graphics.h index 822da6e..3cc1a9a 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -103,7 +103,7 @@ 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 +//NOTE(martin): surface sharing //------------------------------------------------------------------------------------------ typedef struct mg_surface_server { u64 h; } mg_surface_server; @@ -111,12 +111,12 @@ 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_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 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 641b514..d50685e 100644 --- a/src/graphics_internal.h +++ b/src/graphics_internal.h @@ -15,6 +15,14 @@ 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 //--------------------------------------------------------------- diff --git a/src/win32_surface_sharing.c b/src/win32_surface_sharing.c index 7b84fe4..e0dd5de 100644 --- a/src/win32_surface_sharing.c +++ b/src/win32_surface_sharing.c @@ -12,11 +12,6 @@ // Surface server //------------------------------------------------------------------------------------------------ -typedef struct mg_surface_server_data -{ - int dummy; -} 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); @@ -27,8 +22,50 @@ MP_API mg_surface_server mg_surface_server_create(void) { mg_surface_server_data* server = malloc_type(mg_surface_server_data); - //TODO + //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); } @@ -45,7 +82,7 @@ MP_API void mg_surface_server_destroy(mg_surface_server handle) } } -MP_API mg_surface_connection_id mg_surface_server_start(mg_surface_server handle, mg_surface surface) +MP_API mg_surface_connection_id mg_surface_server_id(mg_surface_server handle) { mg_surface_connection_id res = 0; @@ -53,20 +90,13 @@ MP_API mg_surface_connection_id mg_surface_server_start(mg_surface_server handle if(server) { //NOTE: just a quick test - res = (u64)mg_surface_native_layer(surface); + HWND layerWindow = (HWND)mp_layer_native_surface(&server->layer); + res = (mg_surface_connection_id)layerWindow; + //res = (mg_surface_connection_id)GetParent(layerWindow); } 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) - { - //TODO - } -} - //------------------------------------------------------------------------------------------------ // Surface client //------------------------------------------------------------------------------------------------ @@ -76,34 +106,13 @@ typedef struct mg_win32_surface_client mg_surface_data interface; mp_layer layer; - HWND remoteWnd; - } mg_win32_surface_client; void mg_win32_surface_client_prepare(mg_surface_data* interface) {} void mg_win32_surface_client_present(mg_surface_data* interface) -{ - mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; - - HWND dstWindow = (HWND)mp_layer_native_surface(&surface->layer); - RECT dstRect; - GetClientRect(dstWindow, &dstRect); - - HDC dstDC = GetDC(dstWindow); - HDC srcDC = GetDC(surface->remoteWnd); - - int res = BitBlt(dstDC, - dstRect.left, - dstRect.top, - dstRect.right - dstRect.left, - dstRect.bottom - dstRect.top, - srcDC, - 0, - 0, - SRCCOPY); -} +{} void mg_win32_surface_client_swap_interval(mg_surface_data* interface, int swap) { @@ -209,15 +218,23 @@ MP_API void mg_surface_client_connect(mg_surface handle, mg_surface_connection_i mg_win32_surface_client* surface = (mg_win32_surface_client*)interface; //NOTE:Quick test - surface->remoteWnd = (HWND)ID; - } -} + 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); -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) - { - //TODO } }