diff --git a/examples/glTriangle/build.sh b/examples/simpleWindow/build.sh similarity index 79% rename from examples/glTriangle/build.sh rename to examples/simpleWindow/build.sh index a96768b..4c97e8e 100755 --- a/examples/glTriangle/build.sh +++ b/examples/simpleWindow/build.sh @@ -3,9 +3,10 @@ BINDIR=../../bin RESDIR=../../resources SRCDIR=../../src +EXTDIR=../../ext INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app" LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore" FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG" -clang -g $FLAGS $LIBS $INCLUDES -o test main.c +clang -g $FLAGS -Wl,-dead_strip $LIBS $INCLUDES -o test main.c diff --git a/examples/glTriangle/build.bat b/examples/triangleGL/build.bat similarity index 100% rename from examples/glTriangle/build.bat rename to examples/triangleGL/build.bat diff --git a/examples/glTriangle/main.c b/examples/triangleGL/main.c similarity index 100% rename from examples/glTriangle/main.c rename to examples/triangleGL/main.c diff --git a/examples/triangleMetal/build.sh b/examples/triangleMetal/build.sh new file mode 100755 index 0000000..fc51e7d --- /dev/null +++ b/examples/triangleMetal/build.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +BINDIR=../../bin +RESDIR=../../resources +SRCDIR=../../src + +INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app" +LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore" +FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip" + +xcrun -sdk macosx metal -c -o shader.air shader.metal +xcrun -sdk macosx metallib -o shader.metallib shader.air + +clang -g $FLAGS $LIBS $INCLUDES -o test main.m diff --git a/examples/triangleMetal/main.m b/examples/triangleMetal/main.m new file mode 100644 index 0000000..5c5326e --- /dev/null +++ b/examples/triangleMetal/main.m @@ -0,0 +1,189 @@ +/************************************************************//** +* +* @file: main.cpp +* @author: Martin Fouilleul +* @date: 30/07/2022 +* @revision: +* +*****************************************************************/ +#include +#include + +#define _USE_MATH_DEFINES //NOTE: necessary for MSVC +#include + +#include"milepost.h" +#include"metal_surface.h" + +#define LOG_SUBSYSTEM "Main" + +#import +#import + +#include"vertex.h" + +static const my_vertex triangle[3] = {{{250, -250},{1, 0, 0, 1}}, + {{-250, -250},{0, 1, 0, 1}}, + {{0, 250},{0, 0, 1, 1}}}; + +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_init(); + mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_METAL); + + //NOTE(martin): load the library + id device = MTLCreateSystemDefaultDevice(); + + const char* shaderPath = "shader.metallib"; + NSString* metalFileName = [[NSString alloc] initWithCString: shaderPath encoding: NSUTF8StringEncoding]; + NSError* err = 0; + id library = [device newLibraryWithFile: metalFileName error:&err]; + if(err != nil) + { + const char* errStr = [[err localizedDescription] UTF8String]; + printf("error : %s\n", errStr); + return(-1); + } + id vertexFunction = [library newFunctionWithName:@"VertexShader"]; + id fragmentFunction = [library newFunctionWithName:@"FragmentShader"]; + + //NOTE(martin): create a render pipeline + MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + pipelineStateDescriptor.label = @"My simple pipeline"; + pipelineStateDescriptor.vertexFunction = vertexFunction; + pipelineStateDescriptor.fragmentFunction = fragmentFunction; + + CAMetalLayer* layer = mg_metal_surface_layer(surface); + pipelineStateDescriptor.colorAttachments[0].pixelFormat = layer.pixelFormat; + + id pipelineState = [device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err]; + if(err != nil) + { + const char* errStr = [[err localizedDescription] UTF8String]; + printf("error : %s\n", errStr); + return(-1); + } + + // start app + + mp_window_bring_to_front(window); + mp_window_focus(window); + + while(!mp_should_quit()) + { + mp_pump_events(0); + mp_event event = {0}; + while(mp_next_event(&event)) + { + switch(event.type) + { + case MP_EVENT_WINDOW_CLOSE: + { + mp_request_quit(); + } break; + + case MP_EVENT_WINDOW_RESIZE: + { + printf("resized, rect = {%f, %f, %f, %f}\n", + event.frame.rect.x, + event.frame.rect.y, + event.frame.rect.w, + event.frame.rect.h); + } break; + + case MP_EVENT_WINDOW_MOVE: + { + printf("moved, rect = {%f, %f, %f, %f}\n", + event.frame.rect.x, + event.frame.rect.y, + event.frame.rect.w, + event.frame.rect.h); + } break; + + case MP_EVENT_MOUSE_MOVE: + { + printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n", + event.move.x, + event.move.y, + event.move.deltaX, + event.move.deltaY); + } break; + + case MP_EVENT_MOUSE_WHEEL: + { + printf("mouse wheel, delta = {%f, %f}\n", + event.move.deltaX, + event.move.deltaY); + } break; + + case MP_EVENT_MOUSE_ENTER: + { + printf("mouse enter\n"); + } break; + + case MP_EVENT_MOUSE_LEAVE: + { + printf("mouse leave\n"); + } break; + + case MP_EVENT_MOUSE_BUTTON: + { + printf("mouse button %i: %i\n", + event.key.code, + event.key.action == MP_KEY_PRESS ? 1 : 0); + } break; + + case MP_EVENT_KEYBOARD_KEY: + { + printf("key %i: %s\n", + event.key.code, + event.key.action == MP_KEY_PRESS ? "press" : (event.key.action == MP_KEY_RELEASE ? "release" : "repeat")); + } break; + + case MP_EVENT_KEYBOARD_CHAR: + { + printf("entered char %s\n", event.character.sequence); + } break; + + default: + break; + } + } + + vector_uint2 viewportSize; + viewportSize.x = 800; + viewportSize.y = 600; + + mg_surface_prepare(surface); + id drawable = mg_metal_surface_drawable(surface); + id commandBuffer = mg_metal_surface_command_buffer(surface); + + MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; + renderPassDescriptor.colorAttachments[0].texture = drawable.texture; + renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; + id encoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + + //Set the pipeline state + [encoder setRenderPipelineState:pipelineState]; + + //Send data to the shader and add draw call + [encoder setVertexBytes: triangle length:sizeof(triangle) atIndex: vertexInputIndexVertices]; + [encoder setVertexBytes: &viewportSize length:sizeof(viewportSize) atIndex: vertexInputIndexViewportSize]; + [encoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart: 0 vertexCount: 3]; + [encoder endEncoding]; + + mg_surface_present(surface); + } + + mp_terminate(); + + return(0); +} diff --git a/examples/triangleMetal/shader.metal b/examples/triangleMetal/shader.metal new file mode 100644 index 0000000..a9c32e5 --- /dev/null +++ b/examples/triangleMetal/shader.metal @@ -0,0 +1,36 @@ + +#include +#include + +using namespace metal; + +#import "vertex.h" + +typedef unsigned int uint; + +typedef struct +{ + float4 clipSpacePos [[position]]; + float4 color; + +} rasterizer_data; + +vertex rasterizer_data VertexShader(uint vertexID [[vertex_id]], + constant my_vertex* vertices [[buffer(vertexInputIndexVertices)]], + constant vector_uint2* viewportSizePointer [[buffer(vertexInputIndexViewportSize)]]) +{ + float2 pixelPos = vertices[vertexID].pos.xy; + float2 viewportSize = vector_float2(*viewportSizePointer); + + rasterizer_data out; + out.clipSpacePos = vector_float4(0, 0, 0, 1); + out.clipSpacePos.xy = pixelPos/(viewportSize/2); + out.color = vertices[vertexID].col; + + return(out); +} + +fragment float4 FragmentShader(rasterizer_data in [[stage_in]]) +{ + return(in.color); +} diff --git a/examples/triangleMetal/vertex.h b/examples/triangleMetal/vertex.h new file mode 100644 index 0000000..d14cb6f --- /dev/null +++ b/examples/triangleMetal/vertex.h @@ -0,0 +1,17 @@ + +#ifndef __VERTEX_H__ +#define __VERTEX_H__ + +#include + +typedef struct +{ + vector_float2 pos; + vector_float4 col; +} my_vertex; + +typedef enum { vertexInputIndexVertices = 0, + vertexInputIndexViewportSize = 1 } vertexInputIndex; + + +#endif //__VERTEX_H__ diff --git a/src/graphics.c b/src/graphics.c index ffa2f9e..0072bd3 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -537,15 +537,13 @@ mg_image_data* mg_image_ptr_from_handle(mg_canvas_data* context, mg_image handle //--------------------------------------------------------------- #ifdef MG_IMPLEMENTS_BACKEND_METAL - //NOTE: function is defined in metal_backend.mm - mg_surface mg_metal_surface_create_for_window(mp_window window); - mg_surface mg_metal_surface_create_for_view(mp_view view); -#endif //MG_IMPLEMENTS_BACKEND_METAL + #include"metal_surface.h" +#endif #ifdef MG_IMPLEMENTS_BACKEND_GLES mg_surface mg_gles_surface_create_offscreen(u32 width, u32 height); mg_surface_server mg_gles_surface_create_server(mg_surface_info* surface); -#endif //MG_IMPLEMENTS_BACKEND_GLES +#endif #ifdef MG_IMPLEMENTS_BACKEND_GL mg_surface mg_gl_surface_create_for_window(mp_window window); @@ -582,29 +580,6 @@ mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend) return(surface); } -mg_surface mg_surface_create_for_view(mp_view view, mg_backend_id backend) -{ - DEBUG_ASSERT(__mgInfo.init); - - mg_surface surface = mg_surface_nil(); - - switch(backend) - { - #ifdef MG_IMPLEMENTS_BACKEND_METAL - case MG_BACKEND_METAL: - surface = mg_metal_surface_create_for_view(view); - break; - #endif - - //... - - default: - break; - } - - return(surface); -} - mg_surface mg_surface_create_offscreen(mg_backend_id backend, u32 width, u32 height) { DEBUG_ASSERT(__mgInfo.init); @@ -795,17 +770,6 @@ void mg_surface_client_destroy(mg_surface_client handle) } } -void mg_surface_client_attach_to_view(mg_surface_client client, mp_view view) -{ - mg_surface_client_info* clientInfo = mg_surface_client_ptr_from_handle(client); - - if(clientInfo) - { - clientInfo->attachment = view; - clientInfo->attach(clientInfo); - } -} - void mg_surface_client_detach(mg_surface_client client) { mg_surface_client_info* clientInfo = mg_surface_client_ptr_from_handle(client); diff --git a/src/graphics.h b/src/graphics.h index 8c9ae9d..54c338d 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -33,7 +33,6 @@ void mg_init(); mg_surface mg_surface_nil(); bool mg_surface_is_nil(mg_surface surface); mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend); -mg_surface mg_surface_create_for_view(mp_view view, mg_backend_id backend); mg_surface mg_surface_create_offscreen(mg_backend_id backend, u32 width, u32 height); void mg_surface_destroy(mg_surface surface); @@ -41,10 +40,13 @@ void* mg_surface_get_os_resource(mg_surface surface); void mg_surface_prepare(mg_surface surface); void mg_surface_present(mg_surface surface); + void mg_surface_resize(mg_surface surface, int width, int height); +void mg_surface_set_frame(mg_surface surface, mp_rect frame); void mg_surface_set_hidden(mg_surface surface, bool hidden); vec2 mg_surface_size(mg_surface surface); +mp_rect mg_surface_frame(mg_surface surface); //------------------------------------------------------------------------------------------ //NOTE(martin): graphics surface sharing @@ -61,8 +63,6 @@ mg_surface_server_id mg_surface_server_get_id(mg_surface_server server); mg_surface_client mg_surface_client_create(mg_surface_server_id id); void mg_surface_client_destroy(mg_surface_client client); -void mg_surface_client_attach_to_view(mg_surface_client client, mp_view view); -void mg_surface_client_detach(mg_surface_client client); //------------------------------------------------------------------------------------------ //NOTE(martin): canvas drawing structs diff --git a/src/graphics_internal.h b/src/graphics_internal.h index a137f77..2008166 100644 --- a/src/graphics_internal.h +++ b/src/graphics_internal.h @@ -75,8 +75,6 @@ typedef struct mg_surface_client_info mg_surface_client_attach_proc attach; mg_surface_client_detach_proc detach; - mp_view attachment; - } mg_surface_client_info; mg_surface_client mg_surface_client_alloc_handle(mg_surface_client_info* client); diff --git a/src/metal_surface.h b/src/metal_surface.h new file mode 100644 index 0000000..8325ae5 --- /dev/null +++ b/src/metal_surface.h @@ -0,0 +1,24 @@ +/************************************************************//** +* +* @file: metal_surface.h +* @author: Martin Fouilleul +* @date: 25/12/2022 +* @revision: +* +*****************************************************************/ +#ifndef __METAL_SURFACE_H_ +#define __METAL_SURFACE_H_ + +#ifdef __OBJC__ + #import +#endif + +mg_surface mg_metal_surface_create_for_window(mp_window window); +void* mg_metal_surface_render_encoder(mg_surface surface); +void* mg_metal_surface_compute_encoder(mg_surface surface); + +void* mg_metal_surface_layer(mg_surface surface); +void* mg_metal_surface_drawable(mg_surface surface); +void* mg_metal_surface_command_buffer(mg_surface surface); + +#endif //__METAL_SURFACE_H_ diff --git a/src/metal_surface.m b/src/metal_surface.m index c7933a0..a75ac04 100644 --- a/src/metal_surface.m +++ b/src/metal_surface.m @@ -154,7 +154,6 @@ void mg_metal_surface_set_hidden(mg_surface_info* interface, bool hidden) } } - vec2 mg_metal_surface_get_size(mg_surface_info* interface) { mg_metal_surface* surface = (mg_metal_surface*)interface; @@ -175,10 +174,10 @@ void* mg_metal_surface_get_os_resource(mg_surface_info* interface) static const f32 MG_METAL_SURFACE_CONTENTS_SCALING = 2; -mg_surface mg_metal_surface_create_for_view(mp_view view) +mg_surface mg_metal_surface_create_for_window(mp_window window) { - mp_view_data* viewData = mp_view_ptr_from_handle(view); - if(!viewData) + mp_window_data* windowData = mp_window_ptr_from_handle(window); + if(!windowData) { return(mg_surface_nil()); } @@ -198,6 +197,12 @@ mg_surface mg_metal_surface_create_for_view(mp_view view) @autoreleasepool { + NSRect frame = [[windowData->osx.nsWindow contentView] frame]; + surface->view = [[NSView alloc] initWithFrame: frame]; + [surface->view setWantsLayer:YES]; + + [[windowData->osx.nsWindow contentView] addSubview: surface->view]; + surface->drawableSemaphore = dispatch_semaphore_create(MP_METAL_MAX_DRAWABLES_IN_FLIGHT); //----------------------------------------------------------- @@ -211,8 +216,6 @@ mg_surface mg_metal_surface_create_for_view(mp_view view) surface->metalLayer.device = surface->device; - surface->view = viewData->nsView; - //----------------------------------------------------------- //NOTE(martin): set the size and scaling //----------------------------------------------------------- @@ -244,23 +247,51 @@ mg_surface mg_metal_surface_create_for_view(mp_view view) } mg_surface handle = mg_surface_alloc_handle((mg_surface_info*)surface); - viewData->surface = handle; - return(handle); } } -mg_surface mg_metal_surface_create_for_window(mp_window window) +void* mg_metal_surface_layer(mg_surface surface) { - mp_window_data* windowData = mp_window_ptr_from_handle(window); - if(!windowData) + mg_surface_info* surfaceData = mg_surface_ptr_from_handle(surface); + if(surfaceData && surfaceData->backend == MG_BACKEND_METAL) { - return(mg_surface_nil()); + mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData; + return(metalSurface->metalLayer); } else { - return(mg_metal_surface_create_for_view(windowData->osx.mainView)); + return(nil); } } +void* mg_metal_surface_drawable(mg_surface surface) +{ + mg_surface_info* surfaceData = mg_surface_ptr_from_handle(surface); + if(surfaceData && surfaceData->backend == MG_BACKEND_METAL) + { + mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData; + return(metalSurface->drawable); + } + else + { + return(nil); + } +} + +void* mg_metal_surface_command_buffer(mg_surface surface) +{ + mg_surface_info* surfaceData = mg_surface_ptr_from_handle(surface); + if(surfaceData && surfaceData->backend == MG_BACKEND_METAL) + { + mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData; + return(metalSurface->commandBuffer); + } + else + { + return(nil); + } +} + + #undef LOG_SUBSYSTEM diff --git a/src/milepost.m b/src/milepost.m index dd61be8..9fae1dc 100644 --- a/src/milepost.m +++ b/src/milepost.m @@ -16,4 +16,4 @@ #include"osx_gles_surface.m" #pragma clang diagnostic pop -#include"osx_surface_client.m" +//#include"osx_surface_client.m" diff --git a/src/mp_app.h b/src/mp_app.h index 9f1e7cc..e46fff2 100644 --- a/src/mp_app.h +++ b/src/mp_app.h @@ -22,7 +22,6 @@ extern "C" { //-------------------------------------------------------------------- typedef struct mp_window { u64 h; } mp_window; -typedef struct mp_view { u64 h; } mp_view; typedef enum { MP_MOUSE_CURSOR_ARROW, MP_MOUSE_CURSOR_RESIZE_0, @@ -320,16 +319,6 @@ void mp_window_center(mp_window window); mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style); mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style); -//-------------------------------------------------------------------- -// View management -//-------------------------------------------------------------------- - -mp_view mp_view_nil(); -bool mp_view_is_nil(mp_view view); -mp_view mp_view_create(mp_window window, mp_rect frame); -void mp_view_destroy(mp_view view); -void mp_view_set_frame(mp_view view, mp_rect frame); - //-------------------------------------------------------------------- // Input state polling //-------------------------------------------------------------------- diff --git a/src/osx_app.h b/src/osx_app.h index 3b1357e..5c08f1b 100644 --- a/src/osx_app.h +++ b/src/osx_app.h @@ -30,22 +30,10 @@ typedef struct osx_window_data NSView* nsView; NSObject* nsWindowDelegate; - mp_view mainView; - } osx_window_data; #define MP_PLATFORM_WINDOW_DATA osx_window_data osx; -typedef struct mp_view_data -{ - list_elt freeListElt; - u32 generation; - - mp_window window; - NSView* nsView; - mg_surface surface; -} mp_view_data; - const u32 MP_APP_MAX_VIEWS = 128; typedef struct osx_app_data @@ -57,9 +45,6 @@ typedef struct osx_app_data void* kbLayoutUnicodeData; id kbLayoutListener; - list_info viewFreeList; - mp_view_data viewPool[MP_APP_MAX_VIEWS]; - } osx_app_data; #define MP_PLATFORM_APP_DATA osx_app_data osx; diff --git a/src/osx_app.m b/src/osx_app.m index 8deeeb2..b05a70d 100644 --- a/src/osx_app.m +++ b/src/osx_app.m @@ -90,64 +90,6 @@ static u32 mp_osx_get_window_style_mask(mp_window_style style) } //--------------------------------------------------------------- -// App struct and utility functions -//--------------------------------------------------------------- -///////////////////////////////////////////////////////////////////////////////////////////////////////// - -void mp_init_view_handles() -{ - ListInit(&__mpApp.osx.viewFreeList); - for(int i=0; i>32; - u32 generation = handle.h & 0xffffffff; - if(index >= MP_APP_MAX_VIEWS) - { - return(0); - } - mp_view_data* view = &__mpApp.osx.viewPool[index]; - if(view->generation != generation) - { - return(0); - } - else - { - return(view); - } -} - -mp_view mp_view_handle_from_ptr(mp_view_data* view) -{ - DEBUG_ASSERT( (view - __mpApp.osx.viewPool) >= 0 - && (view - __mpApp.osx.viewPool) < MP_APP_MAX_VIEWS); - - u64 h = ((u64)(view - __mpApp.osx.viewPool))<<32 - | ((u64)view->generation); - - return((mp_view){h}); -} - -void mp_view_recycle_ptr(mp_view_data* view) -{ - view->generation++; - ListPush(&__mpApp.osx.viewFreeList, &view->freeListElt); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////// - static void mp_init_osx_keys() { @@ -719,10 +661,6 @@ static void mp_update_key_mods(mp_key_mods mods) event.frame.rect.w = contentRect.size.width; event.frame.rect.h = contentRect.size.height; - mp_rect viewFrame = {0, 0, contentRect.size.width, contentRect.size.height}; - mp_view_set_frame(mpWindow->osx.mainView, viewFrame); - - if(__mpApp.liveResizeCallback) { __mpApp.liveResizeCallback(event, __mpApp.liveResizeData); @@ -1269,7 +1207,6 @@ void mp_init() LOG_MESSAGE("init handles\n"); mp_init_window_handles(); - mp_init_view_handles(); LOG_MESSAGE("init event queue\n"); ringbuffer_init(&__mpApp.eventQueue, 16); @@ -1508,9 +1445,6 @@ mp_window mp_window_create(mp_rect contentRect, const char* title, mp_window_sty mp_window windowHandle = mp_window_handle_from_ptr(window); - mp_rect mainViewFrame = {0, 0, contentRect.w, contentRect.h}; - window->osx.mainView = mp_view_create(windowHandle, mainViewFrame); - return(windowHandle); }//autoreleasepool } @@ -1780,17 +1714,7 @@ void mp_window_set_content_size(mp_window window, int width, int height) //-------------------------------------------------------------------- // view management //-------------------------------------------------------------------- - -mp_view mp_view_nil() -{ - return((mp_view){0}); -} - -bool mp_view_is_nil(mp_view view) -{ - return(!view.h); -} - +/* mp_view mp_view_create(mp_window windowHandle, mp_rect frame) {@autoreleasepool{ mp_window_data* window = mp_window_ptr_from_handle(windowHandle); @@ -1853,7 +1777,7 @@ void mp_view_set_frame(mp_view viewHandle, mp_rect frame) mg_surface_resize(view->surface, frame.w, frame.h); } } - +*/ //-------------------------------------------------------------------- // Main loop throttle //-------------------------------------------------------------------- diff --git a/todo.txt b/todo.txt index 90c2643..e724c15 100644 --- a/todo.txt +++ b/todo.txt @@ -19,23 +19,62 @@ Windows port (mp_app.c can 'see' platform specific stuff, so ObjectiveC defs pose a problem, but we can define id as void* when not in ObjC...) -[ ] Check changes in macos version +[.] Check changes in macos version [x] Restructure macos version to use mp_app_internal.h/mp_app.c [x] test new run loop structure on macos [x] Fix resize crash when there's no surface - [ ] separate data for key and mouse event? - [ ] Clarify how we want to do view handling across platforms - [ ] Views (using docked windows?) -- or see if we can use surfaces and restrict their location? - [ ] pull views in common stuff - [ ] use isARepeat in macos keyDown event and simplify update key state + [>] separate data for key and mouse event? + [>] Simplify event structs + [ ] use isARepeat in macos keyDown event and simplify update key state -[ ] Simplify event structs + [>] Clarify how we want to do view handling across platforms + [.] use surfaces to define restricted drawing locations + [x] Implement with NSView subviews on osx + [/] Maybe switch to just using CALayers? + [ ] Clarify metal-specific surface API + > right now mg_surface doesn't really give access to directly drawing in metal + we only need render encoder from the surface? -> if we just want to issue draw calls. + We'll likely need the command buffer if we want other passes? or also have get_compute_encoder(). + We only need the command buffer/command queue if we want to manually create encoders, eg with different clear color + + -> get pixel format / command buffer / texture + (don't get drawable as it is specific to the kind of target (window or image)) + -> as helper, get simple encoders in the command buffer + + maybe even _just_ get a CAMetalDrawable and pixel format, and let user code create commandQueue, buffers, encoders... + -> but we need to present the drawable to a specific commandbuffer + -> so, maybe the view should also maintain a command buffer + -> pixel format, drawable, command buffer, + helpers for encoders(passes) + + --> but then, mg_surface doesn't really abstract anything (usage code needs to know which kind of surface it is to be able to draw inside it) + (well, it abstracts the creation of the context and the presentation...) + + maybe we should actually abstract over that, a la sokol_gfx... And then the 2D vector graphics uses this abstract API? + -> but this is a bigger endeavour + + Maybe keep surface simple, write an opengl version, then try to port painter to opengl version, + and then we will have more info to decide if we want to abstract over the different APIs. + + Do surfaces for different graphics API even need to be abstracted? don't we always know which surface we're using? + + + + ->> how much do we abstract graphics API vs how much we give access to native calls... + + ie we could abstract shaders, buffers, textures, pipeline, encoders, etc... but also provide access to native data structures + + + + + [ ] Cleanup graphics backend compile-time/runtime selection + [ ] Implement surfaces with child windows on win32 + [/] Maybe implement compositing directly in d3d and opengl compat extension... [.] Implement input polling [ ] Simplify input polling API names [/] Try to simplify input state and polling once we have UI usage code -[ ] Finish window properties query/setting +[ ] Finish win32 window create flags and properties query/setting [ ] Implement clipboard [ ] Implement file dialogs