[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
|
@ -15,3 +15,4 @@ build
|
||||||
|
|
||||||
Debug/*
|
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
|
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:
|
* @revision:
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
#include<stdio.h>
|
||||||
#include<stdlib.h>
|
#include<stdlib.h>
|
||||||
#include<string.h>
|
#include<string.h>
|
||||||
|
|
||||||
|
@ -15,8 +16,6 @@
|
||||||
#define MG_INCLUDE_GL_API 1
|
#define MG_INCLUDE_GL_API 1
|
||||||
#include"milepost.h"
|
#include"milepost.h"
|
||||||
|
|
||||||
#define LOG_SUBSYSTEM "Main"
|
|
||||||
|
|
||||||
unsigned int program;
|
unsigned int program;
|
||||||
|
|
||||||
const char* vshaderSource =
|
const char* vshaderSource =
|
||||||
|
@ -60,15 +59,13 @@ void compile_shader(GLuint shader, const char* source)
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
LogLevel(LOG_LEVEL_DEBUG);
|
|
||||||
|
|
||||||
mp_init();
|
mp_init();
|
||||||
|
|
||||||
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
|
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
|
||||||
mp_window window = mp_window_create(rect, "test", 0);
|
mp_window window = mp_window_create(rect, "test", 0);
|
||||||
|
|
||||||
//NOTE: create surface
|
//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);
|
mg_surface_prepare(surface);
|
||||||
|
|
||||||
//NOTE: init shader and gl state
|
//NOTE: init shader and gl state
|
||||||
|
@ -115,10 +112,10 @@ int main()
|
||||||
while(!mp_should_quit())
|
while(!mp_should_quit())
|
||||||
{
|
{
|
||||||
mp_pump_events(0);
|
mp_pump_events(0);
|
||||||
mp_event event = {0};
|
mp_event* event = 0;
|
||||||
while(mp_next_event(&event))
|
while((event = mp_next_event(mem_scratch())) != 0)
|
||||||
{
|
{
|
||||||
switch(event.type)
|
switch(event->type)
|
||||||
{
|
{
|
||||||
case MP_EVENT_WINDOW_CLOSE:
|
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);
|
glClearColor(0.3, 0.3, 1, 1);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
@ -156,8 +153,12 @@ int main()
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
|
||||||
|
mem_arena_clear(mem_scratch());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mg_surface_destroy(surface);
|
||||||
|
mp_window_destroy(window);
|
||||||
mp_terminate();
|
mp_terminate();
|
||||||
|
|
||||||
return(0);
|
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)
|
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)
|
gl41 = gather_api(tree, 'gl', 4.1)
|
||||||
gl43 = gather_api(tree, 'gl', 4.3)
|
gl43 = gather_api(tree, 'gl', 4.3)
|
||||||
gl44 = gather_api(tree, 'gl', 4.4)
|
gl44 = gather_api(tree, 'gl', 4.4)
|
||||||
gles30 = gather_api(tree, 'gles2', 3.1)
|
gles31 = gather_api(tree, 'gles2', 3.1)
|
||||||
gles31 = gather_api(tree, 'gles2', 3.2)
|
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
|
# generate interface struct
|
||||||
f.write('typedef struct mg_gl_api\n{\n')
|
f.write('typedef struct mg_gl_api\n{\n')
|
||||||
|
|
||||||
|
f.write(' const char* name;\n')
|
||||||
|
|
||||||
for func in glall:
|
for func in glall:
|
||||||
f.write('\t' + 'PFN' + func.upper() + 'PROC ' + remove_prefix(func, 'gl') + ';\n')
|
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")
|
f.write("void mg_gl_select_api(mg_gl_api* api);\n\n")
|
||||||
|
|
||||||
|
|
||||||
emit_end_guard(f, loaderName)
|
emit_end_guard(f, loaderName)
|
||||||
f.close()
|
f.close()
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
|
@ -139,10 +148,88 @@ f.close()
|
||||||
def emit_loader(f, name, procs):
|
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('void mg_gl_load_'+ name +'(mg_gl_api* api, mg_gl_load_proc loadProc)\n')
|
||||||
f.write("{\n")
|
f.write("{\n")
|
||||||
for proc in procs:
|
f.write(' api->name = "'+ name +'";\n')
|
||||||
f.write('\tapi->' + remove_prefix(proc, 'gl') + ' = loadProc("' + proc + '");\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")
|
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')
|
f = open(loaderCPath, 'w')
|
||||||
|
|
||||||
emit_doc(f, loaderName, '.c')
|
emit_doc(f, loaderName, '.c')
|
||||||
|
@ -150,15 +237,17 @@ emit_doc(f, loaderName, '.c')
|
||||||
f.write('#include"' + loaderName + '.h"\n')
|
f.write('#include"' + loaderName + '.h"\n')
|
||||||
f.write('#include"platform.h"\n\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, 'gl41', gl41)
|
||||||
emit_loader(f, 'gl43', gl43)
|
emit_loader(f, 'gl43', gl43)
|
||||||
emit_loader(f, 'gl44', gl44)
|
emit_loader(f, 'gl44', gl44)
|
||||||
emit_loader(f, 'gles30', gles30)
|
|
||||||
emit_loader(f, 'gles31', gles31)
|
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_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.write("mg_gl_api* mg_gl_get_api(void) { return(__mgGLAPI); }\n\n")
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
|
@ -22,12 +22,12 @@
|
||||||
//TODO: use version hints, once we have all api versions correctly categorized by glapi.py
|
//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_MAJOR 3
|
||||||
#define MG_GLES_VERSION_MINOR 0
|
#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
|
#else
|
||||||
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
|
||||||
#define MG_GLES_VERSION_MAJOR 3
|
#define MG_GLES_VERSION_MAJOR 3
|
||||||
#define MG_GLES_VERSION_MINOR 1
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ void mg_egl_surface_destroy(mg_surface_data* interface)
|
||||||
|
|
||||||
if(&surface->api == mg_gl_get_api())
|
if(&surface->api == mg_gl_get_api())
|
||||||
{
|
{
|
||||||
mg_gl_select_api(0);
|
mg_gl_deselect_api();
|
||||||
}
|
}
|
||||||
if(eglGetCurrentContext() == surface->eglContext)
|
if(eglGetCurrentContext() == surface->eglContext)
|
||||||
{
|
{
|
||||||
|
@ -76,6 +76,13 @@ void mg_egl_surface_present(mg_surface_data* interface)
|
||||||
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
|
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)
|
void mg_egl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||||
{
|
{
|
||||||
mg_egl_surface* surface = (mg_egl_surface*)interface;
|
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.destroy = mg_egl_surface_destroy;
|
||||||
surface->interface.prepare = mg_egl_surface_prepare;
|
surface->interface.prepare = mg_egl_surface_prepare;
|
||||||
surface->interface.present = mg_egl_surface_present;
|
surface->interface.present = mg_egl_surface_present;
|
||||||
|
surface->interface.deselect = mg_egl_surface_deselect;
|
||||||
surface->interface.swapInterval = mg_egl_surface_swap_interval;
|
surface->interface.swapInterval = mg_egl_surface_swap_interval;
|
||||||
|
|
||||||
EGLAttrib displayAttribs[] = {
|
EGLAttrib displayAttribs[] = {
|
||||||
|
|
2159
src/gl_api.h
2159
src/gl_api.h
File diff suppressed because it is too large
Load Diff
11578
src/gl_loader.c
11578
src/gl_loader.c
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* @file: gl_loader.h
|
* @file: gl_loader.h
|
||||||
* @note: auto-generated by glapi.py from gl.xml
|
* @note: auto-generated by glapi.py from gl.xml
|
||||||
* @date: 12/072023
|
* @date: 07/082023
|
||||||
*
|
*
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
#ifndef __GL_LOADER_H__
|
#ifndef __GL_LOADER_H__
|
||||||
|
|
|
@ -207,6 +207,11 @@ void mg_surface_destroy(mg_surface handle)
|
||||||
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
mg_surface_data* surface = mg_surface_data_from_handle(handle);
|
||||||
if(surface)
|
if(surface)
|
||||||
{
|
{
|
||||||
|
if(__mgSelectedSurface.h == handle.h)
|
||||||
|
{
|
||||||
|
mg_surface_deselect();
|
||||||
|
}
|
||||||
|
|
||||||
if(surface->backend && surface->backend->destroy)
|
if(surface->backend && surface->backend->destroy)
|
||||||
{
|
{
|
||||||
surface->backend->destroy(surface->backend);
|
surface->backend->destroy(surface->backend);
|
||||||
|
@ -350,7 +355,12 @@ void mg_surface_render_commands(mg_surface surface,
|
||||||
mg_path_elt* elements)
|
mg_path_elt* elements)
|
||||||
{
|
{
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
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,
|
surfaceData->backend->render(surfaceData->backend,
|
||||||
clearColor,
|
clearColor,
|
||||||
|
@ -380,7 +390,12 @@ mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
mg_image image = mg_image_nil();
|
mg_image image = mg_image_nil();
|
||||||
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
|
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);
|
DEBUG_ASSERT(surfaceData->api == MG_CANVAS);
|
||||||
|
|
||||||
|
@ -397,7 +412,14 @@ mg_image mg_image_create(mg_surface surface, u32 width, u32 height)
|
||||||
void mg_image_destroy(mg_image image)
|
void mg_image_destroy(mg_image image)
|
||||||
{
|
{
|
||||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||||
|
|
||||||
if(imageData)
|
if(imageData)
|
||||||
|
{
|
||||||
|
if(imageData->surface.h != __mgSelectedSurface.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);
|
mg_surface_data* surface = mg_surface_data_from_handle(imageData->surface);
|
||||||
if(surface && surface->backend)
|
if(surface && surface->backend)
|
||||||
|
@ -407,11 +429,19 @@ void mg_image_destroy(mg_image image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
||||||
{
|
{
|
||||||
mg_image_data* imageData = mg_image_data_from_handle(image);
|
mg_image_data* imageData = mg_image_data_from_handle(image);
|
||||||
|
|
||||||
if(imageData)
|
if(imageData)
|
||||||
|
{
|
||||||
|
if(imageData->surface.h != __mgSelectedSurface.h)
|
||||||
|
{
|
||||||
|
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);
|
mg_surface_data* surfaceData = mg_surface_data_from_handle(imageData->surface);
|
||||||
if(surfaceData)
|
if(surfaceData)
|
||||||
|
@ -421,3 +451,4 @@ void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include"platform/osx_clock.c"
|
#include"platform/osx_clock.c"
|
||||||
#include"platform/posix_io.c"
|
#include"platform/posix_io.c"
|
||||||
#include"platform/posix_thread.c"
|
#include"platform/posix_thread.c"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include"platform/unix_rng.c"
|
#include"platform/unix_rng.c"
|
||||||
#include"platform/posix_socket.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_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);
|
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
|
// 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)
|
void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window)
|
||||||
{@autoreleasepool{
|
{@autoreleasepool{
|
||||||
|
|
||||||
surface->nativeLayer = mg_osx_surface_native_layer;
|
surface->nativeLayer = mg_osx_surface_native_layer;
|
||||||
surface->contentsScaling = mg_osx_surface_contents_scaling;
|
surface->contentsScaling = mg_osx_surface_contents_scaling;
|
||||||
surface->getSize = mg_osx_surface_get_size;
|
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
|
// system dialogs windows
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
extern void* orca_mem_grow(u64 size);
|
extern void* orca_mem_grow(u64 size);
|
||||||
#define MORECORE orca_mem_grow
|
#define MORECORE orca_mem_grow
|
||||||
|
#define MORECORE_CONTIGUOUS 0
|
||||||
/*
|
/*
|
||||||
This is a version (aka dlmalloc) of malloc/free/realloc written by
|
This is a version (aka dlmalloc) of malloc/free/realloc written by
|
||||||
Doug Lea and released to the public domain. Use, modify, and
|
Doug Lea and released to the public domain. Use, modify, and
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
* @file: win32_thread.c
|
* @file: win32_thread.c
|
||||||
* @author: Reuben Dunnington
|
* @author: Reuben Dunnington
|
||||||
* @date: 7/30/2023
|
* @date: 7/30/2023
|
||||||
* @revision:
|
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
#include<processthreadsapi.h>
|
#include<processthreadsapi.h>
|
||||||
#include<synchapi.h>
|
#include<synchapi.h>
|
||||||
#include<math.h> //INFINITY
|
#include<math.h> //INFINITY
|
||||||
|
#include<winuser.h> // PostMessage
|
||||||
|
|
||||||
#include"platform_thread.h"
|
#include"platform_thread.h"
|
||||||
|
|
||||||
|
|
|
@ -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 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_
|
#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)
|
void mg_wgl_surface_deselect(mg_surface_data* interface)
|
||||||
{
|
{
|
||||||
wglMakeCurrent(NULL, NULL);
|
wglMakeCurrent(NULL, NULL);
|
||||||
|
mg_gl_deselect_api();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_wgl_surface_swap_interval(mg_surface_data* interface, int swap)
|
void mg_wgl_surface_swap_interval(mg_surface_data* interface, int swap)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include<dwmapi.h>
|
#include<dwmapi.h>
|
||||||
#include"mp_app.c"
|
#include"mp_app.c"
|
||||||
|
#include"platform_thread.h"
|
||||||
|
|
||||||
void mp_init_keys()
|
void mp_init_keys()
|
||||||
{
|
{
|
||||||
|
@ -504,6 +505,13 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
//TODO
|
//TODO
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case MP_WM_USER_DISPATCH_PROC:
|
||||||
|
{
|
||||||
|
mp_dispatch_proc proc = (mp_dispatch_proc)wParam;
|
||||||
|
void* user = (void*)lParam;
|
||||||
|
result = proc(user);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
result = DefWindowProc(windowHandle, message, wParam, lParam);
|
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
|
// window management
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
|
@ -45,4 +45,9 @@ typedef struct win32_app_data
|
||||||
|
|
||||||
#define MP_PLATFORM_APP_DATA win32_app_data win32;
|
#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_
|
#endif __WIN32_APP_H_
|
||||||
|
|
Loading…
Reference in New Issue