[gles] Support for exposing GLES surfaces to orca apps
- update gles surface example - add mp_dispatch_on_main_thread_sync() to osx threads - add /experimental:c11atomics to glesTriangle build.bat - mp_dispatch_on_main_thread_sync: win32 impl - move mp_dispatch_on_main_thread_sync() on app layer - configure dlmalloc to not assume contiguity. This allows us to reserve blocks on our end without trashing malloc-owned zones. This way we can add a block to store GL static strings when needed. - implement deselect interface - Log an error when an OpenGL function is called while no OpenGL API is selected, or if that function is not part of the selected API - avoid dispatching calls to image or canvas API if surface is not selected. However, we could later allow it and temporarily select the surface _on behalf of the user_. - Adding support for format string and optional parameters in assert macros
This commit is contained in:
parent
c103c001f7
commit
d01dc832fb
|
@ -14,4 +14,5 @@ build
|
|||
*.sln
|
||||
|
||||
Debug/*
|
||||
src/glsl_shaders.h
|
||||
src/glsl_shaders.h
|
||||
scripts/__pycache__
|
|
@ -1,3 +1,3 @@
|
|||
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_gles_triangle.exe
|
||||
cl /we4013 /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_gles_triangle.exe
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
|
||||
|
@ -15,8 +16,6 @@
|
|||
#define MG_INCLUDE_GL_API 1
|
||||
#include"milepost.h"
|
||||
|
||||
#define LOG_SUBSYSTEM "Main"
|
||||
|
||||
unsigned int program;
|
||||
|
||||
const char* vshaderSource =
|
||||
|
@ -60,15 +59,13 @@ void compile_shader(GLuint shader, const char* source)
|
|||
|
||||
int main()
|
||||
{
|
||||
LogLevel(LOG_LEVEL_DEBUG);
|
||||
|
||||
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 surface = mg_surface_create_for_window(window, MG_GLES);
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
//NOTE: init shader and gl state
|
||||
|
@ -115,10 +112,10 @@ int main()
|
|||
while(!mp_should_quit())
|
||||
{
|
||||
mp_pump_events(0);
|
||||
mp_event event = {0};
|
||||
while(mp_next_event(&event))
|
||||
mp_event* event = 0;
|
||||
while((event = mp_next_event(mem_scratch())) != 0)
|
||||
{
|
||||
switch(event.type)
|
||||
switch(event->type)
|
||||
{
|
||||
case MP_EVENT_WINDOW_CLOSE:
|
||||
{
|
||||
|
@ -130,7 +127,7 @@ int main()
|
|||
}
|
||||
}
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
// mg_surface_prepare(surface);
|
||||
|
||||
glClearColor(0.3, 0.3, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
@ -156,8 +153,12 @@ int main()
|
|||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
mg_surface_present(surface);
|
||||
|
||||
mem_arena_clear(mem_scratch());
|
||||
}
|
||||
|
||||
mg_surface_destroy(surface);
|
||||
mp_window_destroy(window);
|
||||
mp_terminate();
|
||||
|
||||
return(0);
|
||||
|
|
105
scripts/glapi.py
105
scripts/glapi.py
|
@ -42,13 +42,21 @@ def gather_api(tree, api, version):
|
|||
|
||||
tree = et.parse(args.spec)
|
||||
|
||||
# put all GL commands in a dict
|
||||
commands = dict()
|
||||
commandsSpec = tree.find('./commands')
|
||||
for command in commandsSpec.iter('command'):
|
||||
name = command.find('proto/name')
|
||||
commands[name.text] = command
|
||||
|
||||
#gather command names per API
|
||||
gl41 = gather_api(tree, 'gl', 4.1)
|
||||
gl43 = gather_api(tree, 'gl', 4.3)
|
||||
gl44 = gather_api(tree, 'gl', 4.4)
|
||||
gles30 = gather_api(tree, 'gles2', 3.1)
|
||||
gles31 = gather_api(tree, 'gles2', 3.2)
|
||||
gles31 = gather_api(tree, 'gles2', 3.1)
|
||||
gles32 = gather_api(tree, 'gles2', 3.2)
|
||||
|
||||
glall = list(set().union(gl41, gl43, gl44, gles30, gles31))
|
||||
glall = list(set().union(gl41, gl43, gl44, gles31, gles32))
|
||||
|
||||
|
||||
#---------------------------------------------------------------
|
||||
|
@ -93,6 +101,8 @@ f.write('#include"GLES3/gl32.h"\n\n')
|
|||
# generate interface struct
|
||||
f.write('typedef struct mg_gl_api\n{\n')
|
||||
|
||||
f.write(' const char* name;\n')
|
||||
|
||||
for func in glall:
|
||||
f.write('\t' + 'PFN' + func.upper() + 'PROC ' + remove_prefix(func, 'gl') + ';\n')
|
||||
|
||||
|
@ -129,7 +139,6 @@ f.write("void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);\n\n")
|
|||
|
||||
f.write("void mg_gl_select_api(mg_gl_api* api);\n\n")
|
||||
|
||||
|
||||
emit_end_guard(f, loaderName)
|
||||
f.close()
|
||||
#---------------------------------------------------------------
|
||||
|
@ -139,10 +148,88 @@ f.close()
|
|||
def emit_loader(f, name, procs):
|
||||
f.write('void mg_gl_load_'+ name +'(mg_gl_api* api, mg_gl_load_proc loadProc)\n')
|
||||
f.write("{\n")
|
||||
for proc in procs:
|
||||
f.write('\tapi->' + remove_prefix(proc, 'gl') + ' = loadProc("' + proc + '");\n')
|
||||
f.write(' api->name = "'+ name +'";\n')
|
||||
|
||||
for proc in glall:
|
||||
if proc in procs:
|
||||
f.write(' api->' + remove_prefix(proc, 'gl') + ' = loadProc("' + proc + '");\n')
|
||||
else:
|
||||
f.write(' api->' + remove_prefix(proc, 'gl') + ' = mg_' + proc + '_noimpl;\n')
|
||||
|
||||
f.write("}\n\n")
|
||||
|
||||
|
||||
def emit_null_api(f, procs):
|
||||
|
||||
f.write('mg_gl_api __mgGLNoAPI;\n\n')
|
||||
|
||||
for name in procs:
|
||||
|
||||
command = commands.get(name)
|
||||
if command == None:
|
||||
print("Couldn't find definition for required command '" + name + "'")
|
||||
exit(-1)
|
||||
|
||||
proto = command.find("proto")
|
||||
ptype = proto.find("ptype")
|
||||
|
||||
retType = ''
|
||||
if proto.text != None:
|
||||
retType += proto.text
|
||||
|
||||
if ptype != None:
|
||||
if ptype.text != None:
|
||||
retType += ptype.text
|
||||
if ptype.tail != None:
|
||||
retType += ptype.tail
|
||||
|
||||
retType = retType.strip()
|
||||
|
||||
f.write(retType + ' mg_' + name + '_noimpl(')
|
||||
|
||||
params = command.findall('param')
|
||||
for i, param in enumerate(params):
|
||||
|
||||
argName = param.find('name').text
|
||||
|
||||
typeNode = param.find('ptype')
|
||||
typeName = ''
|
||||
|
||||
if param.text != None:
|
||||
typeName += param.text
|
||||
|
||||
if typeNode != None:
|
||||
if typeNode.text != None:
|
||||
typeName += typeNode.text
|
||||
if typeNode.tail != None:
|
||||
typeName += typeNode.tail
|
||||
|
||||
typeName = typeName.strip()
|
||||
|
||||
f.write(typeName + ' ' + argName)
|
||||
|
||||
if i < len(params)-1:
|
||||
f.write(', ')
|
||||
|
||||
f.write(')\n')
|
||||
f.write('{\n')
|
||||
f.write(' if(__mgGLAPI == &__mgGLNoAPI)\n')
|
||||
f.write(' {\n')
|
||||
f.write(' log_error("No GL or GLES API is selected. Make sure you call mg_surface_prepare() before calling OpenGL API functions.\\n");\n')
|
||||
f.write(' }\n')
|
||||
f.write(' else\n')
|
||||
f.write(' {\n')
|
||||
f.write(' log_error("'+ name +' is not part of currently selected %s API\\n", __mgGLAPI->name);\n')
|
||||
f.write(' }\n')
|
||||
if retType != 'void':
|
||||
f.write(' return(('+ retType +')0);\n')
|
||||
f.write('}\n')
|
||||
|
||||
f.write('mg_gl_api __mgGLNoAPI = {\n')
|
||||
for proc in procs:
|
||||
f.write(' .' + remove_prefix(proc, 'gl') + ' = mg_' + proc + '_noimpl,\n')
|
||||
f.write("};\n\n")
|
||||
|
||||
f = open(loaderCPath, 'w')
|
||||
|
||||
emit_doc(f, loaderName, '.c')
|
||||
|
@ -150,15 +237,17 @@ emit_doc(f, loaderName, '.c')
|
|||
f.write('#include"' + loaderName + '.h"\n')
|
||||
f.write('#include"platform.h"\n\n')
|
||||
|
||||
f.write("mp_thread_local mg_gl_api* __mgGLAPI = 0;\n\n")
|
||||
f.write("mp_thread_local mg_gl_api* __mgGLAPI = 0;\n")
|
||||
|
||||
emit_null_api(f, glall)
|
||||
emit_loader(f, 'gl41', gl41)
|
||||
emit_loader(f, 'gl43', gl43)
|
||||
emit_loader(f, 'gl44', gl44)
|
||||
emit_loader(f, 'gles30', gles30)
|
||||
emit_loader(f, 'gles31', gles31)
|
||||
emit_loader(f, 'gles32', gles32)
|
||||
|
||||
f.write("void mg_gl_select_api(mg_gl_api* api){ __mgGLAPI = api; }\n")
|
||||
f.write("void mg_gl_deselect_api(){ __mgGLAPI = &__mgGLNoAPI; }\n")
|
||||
f.write("mg_gl_api* mg_gl_get_api(void) { return(__mgGLAPI); }\n\n")
|
||||
|
||||
f.close()
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
//TODO: use version hints, once we have all api versions correctly categorized by glapi.py
|
||||
#define MG_GLES_VERSION_MAJOR 3
|
||||
#define MG_GLES_VERSION_MINOR 0
|
||||
#define mg_gl_load_gles mg_gl_load_gles30
|
||||
#define mg_gl_load_gles mg_gl_load_gles31
|
||||
#else
|
||||
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
||||
#define MG_GLES_VERSION_MAJOR 3
|
||||
#define MG_GLES_VERSION_MINOR 1
|
||||
#define mg_gl_load_gles mg_gl_load_gles31
|
||||
#define mg_gl_load_gles mg_gl_load_gles32
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -50,7 +50,7 @@ void mg_egl_surface_destroy(mg_surface_data* interface)
|
|||
|
||||
if(&surface->api == mg_gl_get_api())
|
||||
{
|
||||
mg_gl_select_api(0);
|
||||
mg_gl_deselect_api();
|
||||
}
|
||||
if(eglGetCurrentContext() == surface->eglContext)
|
||||
{
|
||||
|
@ -76,6 +76,13 @@ void mg_egl_surface_present(mg_surface_data* interface)
|
|||
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
|
||||
}
|
||||
|
||||
void mg_egl_surface_deselect(mg_surface_data* interface)
|
||||
{
|
||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
||||
eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
mg_gl_deselect_api();
|
||||
}
|
||||
|
||||
void mg_egl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
{
|
||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
||||
|
@ -91,6 +98,7 @@ void mg_egl_surface_init(mg_egl_surface* surface)
|
|||
surface->interface.destroy = mg_egl_surface_destroy;
|
||||
surface->interface.prepare = mg_egl_surface_prepare;
|
||||
surface->interface.present = mg_egl_surface_present;
|
||||
surface->interface.deselect = mg_egl_surface_deselect;
|
||||
surface->interface.swapInterval = mg_egl_surface_swap_interval;
|
||||
|
||||
EGLAttrib displayAttribs[] = {
|
||||
|
|
2245
src/gl_api.h
2245
src/gl_api.h
File diff suppressed because it is too large
Load Diff
11724
src/gl_loader.c
11724
src/gl_loader.c
File diff suppressed because it is too large
Load Diff
|
@ -1,23 +1,23 @@
|
|||
/********************************************************
|
||||
*
|
||||
* @file: gl_loader.h
|
||||
* @note: auto-generated by glapi.py from gl.xml
|
||||
* @date: 12/072023
|
||||
*
|
||||
*********************************************************/
|
||||
#ifndef __GL_LOADER_H__
|
||||
#define __GL_LOADER_H__
|
||||
|
||||
#include"gl_api.h"
|
||||
|
||||
typedef void*(*mg_gl_load_proc)(const char* name);
|
||||
|
||||
void mg_gl_load_gl41(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gl43(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gl44(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gles30(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
|
||||
void mg_gl_select_api(mg_gl_api* api);
|
||||
|
||||
#endif // __GL_LOADER_H__
|
||||
/********************************************************
|
||||
*
|
||||
* @file: gl_loader.h
|
||||
* @note: auto-generated by glapi.py from gl.xml
|
||||
* @date: 07/082023
|
||||
*
|
||||
*********************************************************/
|
||||
#ifndef __GL_LOADER_H__
|
||||
#define __GL_LOADER_H__
|
||||
|
||||
#include"gl_api.h"
|
||||
|
||||
typedef void*(*mg_gl_load_proc)(const char* name);
|
||||
|
||||
void mg_gl_load_gl41(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gl43(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gl44(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gles30(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);
|
||||
|
||||
void mg_gl_select_api(mg_gl_api* api);
|
||||
|
||||
#endif // __GL_LOADER_H__
|
||||
|
|
|
@ -207,6 +207,11 @@ void mg_surface_destroy(mg_surface handle)
|
|||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||
if(surface)
|
||||
{
|
||||
if(__mgSelectedSurface.h == handle.h)
|
||||
{
|
||||
mg_surface_deselect();
|
||||
}
|
||||
|
||||
if(surface->backend && surface->backend->destroy)
|
||||
{
|
||||
surface->backend->destroy(surface->backend);
|
||||
|
@ -350,7 +355,12 @@ void mg_surface_render_commands(mg_surface surface,
|
|||
mg_path_elt* elements)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->backend)
|
||||
|
||||
if(surface.h != __mgSelectedSurface.h)
|
||||
{
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before drawing onto a surface.\n");
|
||||
}
|
||||
else if(surfaceData && surfaceData->backend)
|
||||
{
|
||||
surfaceData->backend->render(surfaceData->backend,
|
||||
clearColor,
|
||||
|
@ -380,7 +390,12 @@ mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
|
|||
{
|
||||
mg_image image = mg_image_nil();
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
||||
if(surfaceData && surfaceData->backend)
|
||||
|
||||
if(surface.h != __mgSelectedSurface.h)
|
||||
{
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before modifying graphics resources.\n");
|
||||
}
|
||||
else if(surfaceData && surfaceData->backend)
|
||||
{
|
||||
DEBUG_ASSERT(surfaceData->api == MG_CANVAS);
|
||||
|
||||
|
@ -397,13 +412,21 @@ mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
|
|||
void mg_image_destroy(mg_image image)
|
||||
{
|
||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||
|
||||
if(imageData)
|
||||
{
|
||||
mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface);
|
||||
if(surface && surface->backend)
|
||||
if(imageData->surface.h != __mgSelectedSurface.h)
|
||||
{
|
||||
surface->backend->imageDestroy(surface->backend, imageData);
|
||||
mg_handle_recycle(image.h);
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before modifying graphics resources.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface);
|
||||
if(surface && surface->backend)
|
||||
{
|
||||
surface->backend->imageDestroy(surface->backend, imageData);
|
||||
mg_handle_recycle(image.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -411,13 +434,21 @@ void mg_image_destroy(mg_image image)
|
|||
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
||||
{
|
||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||
|
||||
if(imageData)
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface);
|
||||
if(surfaceData)
|
||||
if(imageData->surface.h != __mgSelectedSurface.h)
|
||||
{
|
||||
DEBUG_ASSERT(surfaceData->backend);
|
||||
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
|
||||
log_error("surface is not selected. Make sure to call mg_surface_prepare() before modifying graphics resources.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface);
|
||||
if(surfaceData)
|
||||
{
|
||||
DEBUG_ASSERT(surfaceData->backend);
|
||||
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include"platform/osx_clock.c"
|
||||
#include"platform/posix_io.c"
|
||||
#include"platform/posix_thread.c"
|
||||
|
||||
/*
|
||||
#include"platform/unix_rng.c"
|
||||
#include"platform/posix_socket.c"
|
||||
|
|
|
@ -330,6 +330,14 @@ MP_API void mp_window_center(mp_window window);
|
|||
MP_API mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style);
|
||||
MP_API mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Dispatching stuff to the main thread
|
||||
//---------------------------------------------------------------
|
||||
|
||||
typedef i32 (*mp_dispatch_proc)(void* user);
|
||||
|
||||
MP_API i32 mp_dispatch_on_main_thread_sync(mp_window main_window, mp_dispatch_proc proc, void* user);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Clipboard
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
@ -1629,7 +1629,6 @@ void mg_surface_cleanup(mg_surface_data* surface)
|
|||
|
||||
void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window)
|
||||
{@autoreleasepool{
|
||||
|
||||
surface->nativeLayer = mg_osx_surface_native_layer;
|
||||
surface->contentsScaling = mg_osx_surface_contents_scaling;
|
||||
surface->getSize = mg_osx_surface_get_size;
|
||||
|
@ -1901,6 +1900,25 @@ void mp_pump_events(f64 timeout)
|
|||
}
|
||||
}
|
||||
|
||||
i32 mp_dispatch_on_main_thread_sync(mp_window main_window, mp_dispatch_proc proc, void* user)
|
||||
{
|
||||
__block i32 result = 0;
|
||||
dispatch_block_t block = ^{
|
||||
result = proc(user);
|
||||
};
|
||||
|
||||
if([NSThread isMainThread])
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), block);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// system dialogs windows
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
extern void* orca_mem_grow(u64 size);
|
||||
#define MORECORE orca_mem_grow
|
||||
|
||||
#define MORECORE_CONTIGUOUS 0
|
||||
/*
|
||||
This is a version (aka dlmalloc) of malloc/free/realloc written by
|
||||
Doug Lea and released to the public domain. Use, modify, and
|
||||
|
|
|
@ -3,13 +3,12 @@
|
|||
* @file: win32_thread.c
|
||||
* @author: Reuben Dunnington
|
||||
* @date: 7/30/2023
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include<processthreadsapi.h>
|
||||
#include<synchapi.h>
|
||||
#include<math.h> //INFINITY
|
||||
#include<winuser.h> // PostMessage
|
||||
|
||||
#include"platform_thread.h"
|
||||
|
||||
|
@ -45,7 +44,7 @@ mp_thread* mp_thread_create_with_name(mp_thread_start_function start, void* user
|
|||
thread->name[0] = '\0';
|
||||
}
|
||||
|
||||
SECURITY_ATTRIBUTES childProcessSecurity = {
|
||||
SECURITY_ATTRIBUTES childProcessSecurity = {
|
||||
.nLength = sizeof(SECURITY_ATTRIBUTES),
|
||||
.bInheritHandle = false,
|
||||
};
|
||||
|
|
|
@ -120,4 +120,24 @@ static inline u64 next_pow2_u64(u64 x)
|
|||
|
||||
#define defer_loop(begin, end) begin; for(int __i__=0; __i__<1; __i__++, end)
|
||||
|
||||
|
||||
#define ORCA_COMMA ,
|
||||
#define ORCA_PASS(A, ...) A(__VA_ARGS__)
|
||||
#define ORCA_EXPAND(...) __VA_ARGS__
|
||||
#define ORCA_EXPAND_NIL(...)
|
||||
#define ORCA_PASTE(a , b) a##b
|
||||
#define ORCA_ARG1_UTIL(a, ...) a
|
||||
#define ORCA_ARG1(...) ORCA_ARG1_UTIL(__VA_ARGS__)
|
||||
#define ORCA_VA_COMMA_TAIL(a, ...) , ##__VA_ARGS__
|
||||
|
||||
//NOTE: this expands to opt if __VA_ARGS__ is empty, and to , va1, va2, ... opt otherwise
|
||||
#define ORCA_VA_NOPT_UTIL(opt, ...) ,##__VA_ARGS__ opt
|
||||
|
||||
//NOTE: this expands to opt if __VA_ARGS__ is empty, and to nothing otherwise
|
||||
#define ORCA_VA_NOPT(opt, ...) ORCA_PASS(ORCA_ARG1, ORCA_VA_NOPT_UTIL(opt, ##__VA_ARGS__))
|
||||
|
||||
//NOTE: this expands to opt if __VA_ARGS__ is non empty, and to nothing otherwise
|
||||
#define ORCA_VA_OPT(opt, ...) ORCA_PASS(ORCA_PASTE, ORCA_EXPAND , ORCA_VA_NOPT(_NIL, ##__VA_ARGS__))(opt)
|
||||
|
||||
|
||||
#endif //__MACRO_HELPERS_H_
|
||||
|
|
|
@ -156,6 +156,7 @@ void mg_wgl_surface_present(mg_surface_data* interface)
|
|||
void mg_wgl_surface_deselect(mg_surface_data* interface)
|
||||
{
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
mg_gl_deselect_api();
|
||||
}
|
||||
|
||||
void mg_wgl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include<dwmapi.h>
|
||||
#include"mp_app.c"
|
||||
#include"platform_thread.h"
|
||||
|
||||
void mp_init_keys()
|
||||
{
|
||||
|
@ -504,6 +505,13 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
//TODO
|
||||
} break;
|
||||
|
||||
case MP_WM_USER_DISPATCH_PROC:
|
||||
{
|
||||
mp_dispatch_proc proc = (mp_dispatch_proc)wParam;
|
||||
void* user = (void*)lParam;
|
||||
result = proc(user);
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
result = DefWindowProc(windowHandle, message, wParam, lParam);
|
||||
|
@ -552,6 +560,15 @@ void mp_pump_events(f64 timeout)
|
|||
}
|
||||
}
|
||||
|
||||
i32 mp_dispatch_on_main_thread_sync(mp_window main_window, mp_dispatch_proc proc, void* user)
|
||||
{
|
||||
mp_window_data* window_data = mp_window_ptr_from_handle(main_window);
|
||||
DEBUG_ASSERT(window_data != NULL);
|
||||
|
||||
LRESULT result = SendMessage(window_data->win32.hWnd, MP_WM_USER_DISPATCH_PROC, (WPARAM)proc, (LPARAM)user);
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// window management
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
@ -45,4 +45,9 @@ typedef struct win32_app_data
|
|||
|
||||
#define MP_PLATFORM_APP_DATA win32_app_data win32;
|
||||
|
||||
enum MP_WM_USER
|
||||
{
|
||||
MP_WM_USER_DISPATCH_PROC = 0x0400, // WM_USER messages are defined from 0x400 to 0x7FFF
|
||||
};
|
||||
|
||||
#endif __WIN32_APP_H_
|
||||
|
|
Loading…
Reference in New Issue