[win32 surface sharing] hacky proof of concept
This commit is contained in:
parent
3ada8ece9a
commit
ee87976429
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//---------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue