From 2be0d5a7e097c329ac31e8558be59b939546e010 Mon Sep 17 00:00:00 2001 From: Carlos Aragones <> Date: Sun, 17 May 2020 18:31:00 +0200 Subject: [PATCH] refactor iOS added mfb_set_resize_callback to iOS minor fixes on iOS & MacOS X --- CMakeLists.txt | 2 + README.md | 1 + src/ios/WindowData_IOS.h | 3 +- src/ios/iOSMiniFB.m | 61 +++++++++++++++++-------- src/ios/iOSViewDelegate.h | 4 +- src/ios/iOSViewDelegate.m | 29 ++++++------ src/macosx/MacMiniFB.m | 80 ++++++++++++++++++++++++--------- src/macosx/OSXWindowFrameView.m | 16 +++---- tests/ios/AppDelegate.m | 41 ++++++++++++----- 9 files changed, 158 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b0d38d5..3b8a17d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,8 @@ set(SrcMacOSX set(SrcIOS src/ios/WindowData_IOS.h src/ios/iOSMiniFB.m + src/ios/iOSView.h + src/ios/iOSView.m src/ios/iOSViewController.h src/ios/iOSViewController.m src/ios/iOSViewDelegate.h diff --git a/README.md b/README.md index 678770b..382bdc4 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,7 @@ bool mfb_set_viewport(struct mfb_window *window, unsigned offset_ void mfb_set_mouse_button_callback(struct mfb_window *window, mfb_mouse_button_func callback); void mfb_set_mouse_move_callback(struct mfb_window *window, mfb_mouse_move_func callback); +void mfb_set_resize_callback(struct mfb_window *window, mfb_resize_func callback); unsigned mfb_get_window_width(struct mfb_window *window); unsigned mfb_get_window_height(struct mfb_window *window); diff --git a/src/ios/WindowData_IOS.h b/src/ios/WindowData_IOS.h index 51fd80a..93b97a6 100644 --- a/src/ios/WindowData_IOS.h +++ b/src/ios/WindowData_IOS.h @@ -9,6 +9,5 @@ typedef struct Vertex { } Vertex; typedef struct { - id command_queue; - id pipeline_state; + Vertex vertices[4]; } SWindowData_IOS; diff --git a/src/ios/iOSMiniFB.m b/src/ios/iOSMiniFB.m index 3ff2218..5b763d9 100644 --- a/src/ios/iOSMiniFB.m +++ b/src/ios/iOSMiniFB.m @@ -13,14 +13,26 @@ create_window_data(unsigned width, unsigned height) { SWindowData *window_data; window_data = malloc(sizeof(SWindowData)); + if(window_data == 0x0) { + NSLog(@"Cannot allocate window data"); + return 0x0; + } memset(window_data, 0, sizeof(SWindowData)); SWindowData_IOS *window_data_ios = malloc(sizeof(SWindowData_IOS)); + if(window_data_ios == 0x0) { + free(window_data); + NSLog(@"Cannot allocate ios window data"); + return 0x0; + } memset((void *) window_data_ios, 0, sizeof(SWindowData_IOS)); - window_data->specific = window_data_ios; - window_data->window_width = [UIScreen mainScreen].bounds.size.width; - window_data->window_height = [UIScreen mainScreen].bounds.size.height; + float scale = [UIScreen mainScreen].scale; + + window_data->specific = window_data_ios; + + window_data->window_width = [UIScreen mainScreen].bounds.size.width * scale; + window_data->window_height = [UIScreen mainScreen].bounds.size.height * scale; window_data->dst_width = width; window_data->dst_height = height; @@ -29,8 +41,10 @@ create_window_data(unsigned width, unsigned height) { window_data->buffer_height = height; window_data->buffer_stride = width * 4; - window_data->draw_buffer = malloc(width * height * 4); + window_data->draw_buffer = malloc(width * height * 4); if (!window_data->draw_buffer) { + free(window_data); + free(window_data_ios); NSLog(@"Unable to create draw buffer"); return 0x0; } @@ -47,6 +61,10 @@ mfb_open(const char *title, unsigned width, unsigned height) { //------------------------------------- struct mfb_window * mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) { + UIWindow *window; + NSArray *windows; + size_t numWindows; + kUnused(title); kUnused(flags); @@ -54,10 +72,15 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) if (window_data == 0x0) { return 0x0; } - - UIWindow *window; - NSArray *windows; - size_t numWindows; + SWindowData_IOS *window_data_ios = (SWindowData_IOS *) window_data->specific; + + static Vertex s_vertices[4] = { + {-1.0, -1.0, 0, 1}, + {-1.0, 1.0, 0, 1}, + { 1.0, -1.0, 0, 1}, + { 1.0, 1.0, 0, 1}, + }; + memcpy(window_data_ios->vertices, s_vertices, sizeof(s_vertices)); windows = [[UIApplication sharedApplication] windows]; numWindows = [windows count]; @@ -130,6 +153,7 @@ mfb_update(struct mfb_window *window, void *buffer) { //------------------------------------- mfb_update_state mfb_update_events(struct mfb_window *window) { + kUnused(window); return STATE_OK; } @@ -138,12 +162,11 @@ extern double g_time_for_frame; bool mfb_wait_sync(struct mfb_window *window) { + kUnused(window); return true; } //------------------------------------- -extern Vertex g_vertices[4]; - bool mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { SWindowData *window_data = (SWindowData *) window; @@ -165,17 +188,19 @@ mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y float y1 = ((float) offset_y / window_data->window_height) * 2.0f - 1.0f; float y2 = (((float) offset_y + height) / window_data->window_height) * 2.0f - 1.0f; - g_vertices[0].x = x1; - g_vertices[0].y = y1; + SWindowData_IOS *window_data_ios = (SWindowData_IOS *) window_data->specific; - g_vertices[1].x = x1; - g_vertices[1].y = y2; + window_data_ios->vertices[0].x = x1; + window_data_ios->vertices[0].y = y1; - g_vertices[2].x = x2; - g_vertices[2].y = y1; + window_data_ios->vertices[1].x = x1; + window_data_ios->vertices[1].y = y2; - g_vertices[3].x = x2; - g_vertices[3].y = y2; + window_data_ios->vertices[2].x = x2; + window_data_ios->vertices[2].y = y1; + + window_data_ios->vertices[3].x = x2; + window_data_ios->vertices[3].y = y2; return true; } diff --git a/src/ios/iOSViewDelegate.h b/src/ios/iOSViewDelegate.h index 986a66a..03c00fe 100644 --- a/src/ios/iOSViewDelegate.h +++ b/src/ios/iOSViewDelegate.h @@ -8,13 +8,15 @@ #import #include "WindowData.h" +#include "WindowData_IOS.h" // Our platform independent renderer class. // Implements the MTKViewDelegate protocol which allows it to accept per-frame // update and drawable resize callbacks. @interface iOSViewDelegate : NSObject { - @public SWindowData *window_data; + @public SWindowData *window_data; + @public SWindowData_IOS *window_data_ios; } -(nonnull instancetype) initWithMetalKitView:(nonnull MTKView *) view windowData:(nonnull SWindowData *) windowData; diff --git a/src/ios/iOSViewDelegate.m b/src/ios/iOSViewDelegate.m index aad5104..abba8d9 100644 --- a/src/ios/iOSViewDelegate.m +++ b/src/ios/iOSViewDelegate.m @@ -13,6 +13,7 @@ #include "WindowData_IOS.h" #include #include +#include //------------------------------------- #define kShader(inc, src) @inc#src @@ -23,14 +24,6 @@ enum { MaxBuffersInFlight = 3 }; // Number of textures in flight (tripple buf id g_metal_device = nil; id g_library = nil; -//-- -Vertex g_vertices[4] = { - {-1.0, -1.0, 0, 1}, - {-1.0, 1.0, 0, 1}, - { 1.0, -1.0, 0, 1}, - { 1.0, 1.0, 0, 1}, -}; - //-- NSString *g_shader_src = kShader( "#include \n", @@ -87,14 +80,15 @@ NSString *g_shader_src = kShader( -(nonnull instancetype) initWithMetalKitView:(nonnull MTKView *) view windowData:(nonnull SWindowData *) windowData { self = [super init]; if (self) { - self->window_data = windowData; - - g_metal_device = view.device; + self->window_data = windowData; + self->window_data_ios = (SWindowData_IOS *) windowData->specific; view.colorPixelFormat = MTLPixelFormatBGRA8Unorm; - view.sampleCount = 1; + view.sampleCount = 1; - m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight); + g_metal_device = view.device; + + m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight); m_command_queue = [g_metal_device newCommandQueue]; [self _createShaders]; @@ -157,8 +151,7 @@ NSString *g_shader_src = kShader( } //------------------------------------- -- (void) drawInMTKView:(nonnull MTKView *) view -{ +- (void) drawInMTKView:(nonnull MTKView *) view { // Per frame updates here dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER); @@ -189,7 +182,7 @@ NSString *g_shader_src = kShader( // Set render command encoder state [renderEncoder setRenderPipelineState:m_pipeline_state]; - [renderEncoder setVertexBytes:g_vertices length:sizeof(g_vertices) atIndex:0]; + [renderEncoder setVertexBytes:window_data_ios->vertices length:sizeof(window_data_ios->vertices) atIndex:0]; //[renderEncoder setFragmentTexture:m_texture_buffers[m_current_buffer] atIndex:0]; [renderEncoder setFragmentTexture:m_texture_buffer atIndex:0]; @@ -211,6 +204,10 @@ NSString *g_shader_src = kShader( //------------------------------------- - (void) mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { // Respond to drawable size or orientation changes here + window_data->window_width = size.width; + window_data->window_height = size.height; + + kCall(resize_func, size.width, size.height); } @end diff --git a/src/macosx/MacMiniFB.m b/src/macosx/MacMiniFB.m index 6b7ab38..b884f08 100644 --- a/src/macosx/MacMiniFB.m +++ b/src/macosx/MacMiniFB.m @@ -120,18 +120,24 @@ mfb_open(const char *title, unsigned width, unsigned height) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -struct mfb_window * -mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - init_keycodes(); - +SWindowData * +create_window_data(unsigned width, unsigned height) { SWindowData *window_data = malloc(sizeof(SWindowData)); + if(window_data == 0x0) { + NSLog(@"Cannot allocate window data"); + return 0x0; + } memset(window_data, 0, sizeof(SWindowData)); SWindowData_OSX *window_data_osx = malloc(sizeof(SWindowData_OSX)); + if(window_data_osx == 0x0) { + free(window_data); + NSLog(@"Cannot allocate osx window data"); + return 0x0; + } memset(window_data_osx, 0, sizeof(SWindowData_OSX)); - window_data->specific = window_data_osx; + + window_data->specific = window_data_osx; window_data->window_width = width; window_data->window_height = height; @@ -143,21 +149,34 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) window_data->buffer_height = height; window_data->buffer_stride = width * 4; - [NSApplication sharedApplication]; - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - #if defined(USE_METAL_API) - g_metal_device = MTLCreateSystemDefaultDevice(); - if (!g_metal_device) { - NSLog(@"Metal is not supported on this device"); - return 0x0; - } - - if (!create_shaders((SWindowData_OSX *) window_data->specific)) { + window_data->draw_buffer = malloc(width * height * 4); + if (!window_data->draw_buffer) { + free(window_data_osx); + free(window_data); + NSLog(@"Unable to create draw buffer"); return 0x0; } #endif + return window_data; +} + +struct mfb_window * +mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + SWindowData *window_data = create_window_data(width, height); + if (window_data == 0x0) { + return 0x0; + } + SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window_data->specific; + + init_keycodes(); + + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + NSWindowStyleMask styles = NSWindowStyleMaskClosable | NSWindowStyleMaskTitled; if (flags & WF_BORDERLESS) @@ -169,14 +188,27 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) NSRect rectangle = NSMakeRect(0, 0, width, height); NSRect frameRect = [NSWindow frameRectForContentRect:rectangle styleMask:styles]; window_data_osx->window = [[OSXWindow alloc] initWithContentRect:frameRect styleMask:styles backing:NSBackingStoreBuffered defer:NO windowData:window_data]; - if (!window_data_osx->window) + if (!window_data_osx->window) { + NSLog(@"Cannot create window"); + if(window_data->draw_buffer != 0x0) { + free(window_data->draw_buffer); + window_data->draw_buffer = 0x0; + } + free(window_data_osx); + free(window_data); return 0x0; + } #if defined(USE_METAL_API) - window_data->draw_buffer = malloc(width * height * 4); - - if (!window_data->draw_buffer) + g_metal_device = MTLCreateSystemDefaultDevice(); + if (!g_metal_device) { + NSLog(@"Metal is not supported on this device"); return 0x0; + } + + if (!create_shaders((SWindowData_OSX *) window_data->specific)) { + return 0x0; + } static Vertex s_vertices[4] = { {-1.0, -1.0, 0, 1}, @@ -263,6 +295,12 @@ destroy_window_data(SWindowData *window_data) { memset(window_data_osx, 0, sizeof(SWindowData_OSX)); free(window_data_osx); } + + if(window_data->draw_buffer != 0x0) { + free(window_data->draw_buffer); + window_data->draw_buffer = 0x0; + } + memset(window_data, 0, sizeof(SWindowData)); free(window_data); diff --git a/src/macosx/OSXWindowFrameView.m b/src/macosx/OSXWindowFrameView.m index 2f678f3..8f1682f 100644 --- a/src/macosx/OSXWindowFrameView.m +++ b/src/macosx/OSXWindowFrameView.m @@ -6,17 +6,8 @@ #if defined(USE_METAL_API) #import -extern id g_metal_device; -extern id g_library; - @implementation WindowViewController -- (void) mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { - (void)view; - (void)size; - // resize -} - - (void) drawInMTKView:(nonnull MTKView *)view { OSXWindow *window = (OSXWindow *) view.window; SWindowData *window_data = window->window_data; @@ -84,6 +75,13 @@ extern id g_library; // Finalize rendering here & push the command buffer to the GPU [commandBuffer commit]; } + +- (void) mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { + (void)view; + (void)size; + // resize +} + @end #endif diff --git a/tests/ios/AppDelegate.m b/tests/ios/AppDelegate.m index 2841103..2eac44d 100644 --- a/tests/ios/AppDelegate.m +++ b/tests/ios/AppDelegate.m @@ -17,6 +17,7 @@ struct mfb_window *g_window = 0x0; uint32_t *g_buffer = 0x0; uint32_t g_width = 0; uint32_t g_height = 0; +float g_scale = 1; //------------------------------------- @interface AppDelegate () @@ -37,6 +38,14 @@ mouse_move(struct mfb_window *window, int x, int y) { NSLog(@"Touch moved %d, %d", x, y); } +void +resize(struct mfb_window *window, int width, int height) { + kUnused(window); + g_width = width; + g_height = height; + NSLog(@"Resize %d, %d", width, height); +} + //------------------------------------- @implementation AppDelegate @@ -44,18 +53,24 @@ mouse_move(struct mfb_window *window, int x, int y) { - (void) OnUpdateFrame { static int seed = 0xbeef; int noise, carry; + int dis = 0; if(g_buffer != 0x0) { - for (uint32_t i = 0; i < g_width * g_height; ++i) { - noise = seed; - noise >>= 3; - noise ^= seed; - carry = noise & 1; - noise >>= 1; - seed >>= 1; - seed |= (carry << 30); - noise &= 0xFF; - g_buffer[i] = MFB_RGB(noise, noise, noise); + uint32_t i = 0; + for (uint32_t y = 0; y < g_height; ++y) { + for (uint32_t x = 0; x < g_width; ++x) { + noise = seed; + noise >>= 3; + noise ^= seed; + carry = noise & 1; + noise >>= 1; + seed >>= 1; + seed |= (carry << 30); + noise &= 0xFF >> dis; + g_buffer[i++] = MFB_RGB(noise, noise, noise); + } + if((y & 0x07) == 0x07) + dis ^= 0x01; } } @@ -75,13 +90,15 @@ mouse_move(struct mfb_window *window, int x, int y) { kUnused(launchOptions); if(g_window == 0x0) { - g_width = [UIScreen mainScreen].bounds.size.width; - g_height = [UIScreen mainScreen].bounds.size.height; + g_scale = [UIScreen mainScreen].scale; + g_width = [UIScreen mainScreen].bounds.size.width * g_scale; + g_height = [UIScreen mainScreen].bounds.size.height * g_scale; g_window = mfb_open("noise", g_width, g_height); if(g_window != 0x0) { g_buffer = malloc(g_width * g_height * 4); mfb_set_mouse_move_callback(g_window, mouse_move); mfb_set_mouse_button_callback(g_window, mouse_btn); + mfb_set_resize_callback(g_window, resize); } }