From c4633a906f25d6659925c124ae3c661374d559b0 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Thu, 11 Jul 2019 22:33:58 +0200 Subject: [PATCH] update osx project --- PanoPainter-OSX/main.cpp | 221 ++++++++++-------------------------- PanoPainter-OSX/main.h | 1 - src/app.cpp | 14 +++ src/app.h | 24 ++-- src/node_stroke_preview.cpp | 10 +- src/objc_utils.cpp | 25 +++- src/shape.cpp | 2 +- 7 files changed, 114 insertions(+), 183 deletions(-) diff --git a/PanoPainter-OSX/main.cpp b/PanoPainter-OSX/main.cpp index c8e5854..08253e3 100644 --- a/PanoPainter-OSX/main.cpp +++ b/PanoPainter-OSX/main.cpp @@ -17,9 +17,6 @@ #include #include -std::deque> tasklist; -std::mutex task_mutex; - @implementation View { NSSharingService *airdrop_service; @@ -192,136 +189,48 @@ std::mutex task_mutex; } - (void)prepareOpenGL { + [super prepareOpenGL]; + NSLog(@"prepare"); // Synchronize buffer swaps with vertical refresh rate GLint swapInt = 1; [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; - // Create a display link capable of being used with all active displays - CVDisplayLinkCreateWithActiveCGDisplays(&dl); - - // Set the renderer output callback function - CVDisplayLinkSetOutputCallback(dl, &MyDisplayLinkCallback, (__bridge void*)self); - - // Set the display link for the current renderer - CGLContextObj cglContext = [[self openGLContext] CGLContextObj]; - CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj]; - CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(dl, cglContext, cglPixelFormat); - - CGLEnable([self.openGLContext CGLContextObj], kCGLCECrashOnRemovedFunctions); - - // Activate the display link - CVDisplayLinkStart(dl); - cgl = [[self openGLContext] CGLContextObj]; glctx = [self openGLContext]; CGLLockContext([[self openGLContext] CGLContextObj]); - App::I.init(); [self.window setTitle:[NSString stringWithFormat:@"%s - %s", g_window_title, glGetString(GL_RENDERER)]]; CGLUnlockContext([[self openGLContext] CGLContextObj]); gl_ready = true; + + App::I->render_thread_start(); + App::I->render_sync(); if ([file2open length] > 0) { - LOG("open file %s", [file2open UTF8String]); - App::I.open_document([file2open UTF8String]); + std::string s = [file2open UTF8String]; + App::I->render_task([=] + { + LOG("open file %s", s.c_str()); + App::I->open_document(s); + }); } } - (void)terminateGL { - CVDisplayLinkRelease(dl); - App::I.terminate(); -} - -// This is the renderer output callback function -static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, - const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) -{ - CVReturn result = [(__bridge View*)displayLinkContext getFrameForTime:outputTime]; - return result; -} - -- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime -{ - static double _timeFreq = CVGetHostClockFrequency(); - static double _prevTime = (double)outputTime->hostTime / _timeFreq; - static double elapsed = 0; - double hostTime = (double)outputTime->hostTime; - double now = hostTime / _timeFreq; - double dt = now - _prevTime; - _prevTime = now; - - // this will not update unless 1/30th of a second has passed since the last update - //if (now < _prevTime + (1.0 / 30.0)) - { - std::deque> working_list; - { - std::lock_guard lock(task_mutex); - working_list = std::move(tasklist); - } - - // We draw on a secondary thread through the display link - // When resizing the view, -reshape is called automatically on the main - // thread. Add a mutex around to avoid the threads accessing the context - // simultaneously when resizing - CGLLockContext([glctx CGLContextObj]); - [glctx makeCurrentContext]; - - while (!working_list.empty()) - { - working_list.front()(); - working_list.pop_front(); - } - - App::I.tick(dt); - - if (App::I.redraw) - { - App::I.clear(); - App::I.update(elapsed); - elapsed = 0; - CGLFlushDrawable([glctx CGLContextObj]); - } - - //[[self openGLContext] flushBuffer]; - // returning NO will cause the layer to NOT be redrawn - - CGLUnlockContext([glctx CGLContextObj]); - return NO; - } - - return kCVReturnSuccess; -} - -- (void)dealloc -{ - // Release the display link - CVDisplayLinkRelease(dl); + App::I->ui_thread_stop(); + App::I->render_thread_stop(); + App::I->terminate(); + delete App::I; + App::I = nullptr; } - (void)drawRect:(NSRect)dirtyRect { - NSLog(@"drawRect"); - - // We draw on a secondary thread through the display link - // When resizing the view, -reshape is called automatically on the main - // thread. Add a mutex around to avoid the threads accessing the context - // simultaneously when resizing - CGLLockContext(cgl); - [glctx makeCurrentContext]; - - App::I.redraw = true; - App::I.clear(); - App::I.update(0); - - //[[self openGLContext] flushBuffer]; - // returning NO will cause the layer to NOT be redrawn - - CGLFlushDrawable(cgl); - CGLUnlockContext(cgl); + return; } - (void)updateTrackingAreas { @@ -343,7 +252,6 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime // resizing the view, -drawRect is called on the main thread. // Add a mutex around to avoid the threads accessing the context // simultaneously when resizing. - CGLLockContext([[self openGLContext] CGLContextObj]); #if SUPPORT_RETINA_RESOLUTION @@ -371,9 +279,10 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime NSRect viewRectPixels = viewRectPoints; #endif // !SUPPORT_RETINA_RESOLUTION - App::I.resize(viewRectPixels.size.width, viewRectPixels.size.height); - - CGLUnlockContext([[self openGLContext] CGLContextObj]); + App::I->ui_task_async([=] + { + App::I->resize(viewRectPixels.size.width, viewRectPixels.size.height); + }); } - (void)renewGState { @@ -391,57 +300,50 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime - (void)mouseDown:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc,p=theEvent.pressure] { - App::I.mouse_down(0, mouseLoc.x, App::I.height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); + App::I->ui_task_async([mouseLoc,p=theEvent.pressure] { + App::I->mouse_down(0, mouseLoc.x, App::I->height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); }); } - (void)rightMouseDown:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc,p=theEvent.pressure] { - App::I.mouse_down(1, mouseLoc.x, App::I.height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); + App::I->ui_task_async([mouseLoc,p=theEvent.pressure] { + App::I->mouse_down(1, mouseLoc.x, App::I->height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); }); } - (void)mouseUp:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc] { - App::I.mouse_up(0, mouseLoc.x, App::I.height - mouseLoc.y - 1, kEventSource::Mouse, 0); + App::I->ui_task_async([mouseLoc] { + App::I->mouse_up(0, mouseLoc.x, App::I->height - mouseLoc.y - 1, kEventSource::Mouse, 0); }); } - (void)rightMouseUp:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc] { - App::I.mouse_up(1, mouseLoc.x, App::I.height - mouseLoc.y - 1, kEventSource::Mouse, 0); + App::I->ui_task_async([mouseLoc] { + App::I->mouse_up(1, mouseLoc.x, App::I->height - mouseLoc.y - 1, kEventSource::Mouse, 0); }); } - (void)mouseMoved:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc,p=theEvent.pressure] { - App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); + App::I->ui_task_async([mouseLoc,p=theEvent.pressure] { + App::I->mouse_move(mouseLoc.x, App::I->height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); }); } -(void)mouseDragged:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc,p=theEvent.pressure] { - App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); + App::I->ui_task_async([mouseLoc,p=theEvent.pressure] { + App::I->mouse_move(mouseLoc.x, App::I->height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); }); } - (void)rightMouseDragged:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc,p=theEvent.pressure] { - App::I.mouse_move(mouseLoc.x, App::I.height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); + App::I->ui_task_async([mouseLoc,p=theEvent.pressure] { + App::I->mouse_move(mouseLoc.x, App::I->height - mouseLoc.y - 1, p, kEventSource::Mouse, 0); }); } -(void)mouseExited:(NSEvent *)event @@ -459,9 +361,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime - (void)scrollWheel:(NSEvent *)theEvent { auto mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([mouseLoc,d=[theEvent deltaY]] { - App::I.mouse_scroll(mouseLoc.x, App::I.height - mouseLoc.y - 1, d); + App::I->ui_task_async([mouseLoc,d=[theEvent deltaY]] { + App::I->mouse_scroll(mouseLoc.x, App::I->height - mouseLoc.y - 1, d); }); } - (void)keyDown:(NSEvent *)theEvent @@ -470,27 +371,25 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime auto chars = [theEvent characters]; const char* c_str = [chars cStringUsingEncoding:NSASCIIStringEncoding]; std::string s = c_str ? c_str : ""; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([keyCode, s] { - if (App::I.keys[(int)kKey::KeyCtrl]) + App::I->ui_task_async([keyCode, s] { + if (App::I->keys[(int)kKey::KeyCtrl]) { - App::I.key_down(convert_key(keyCode)); - App::I.key_up(convert_key(keyCode)); + App::I->key_down(convert_key(keyCode)); + App::I->key_up(convert_key(keyCode)); } else { - App::I.key_down(convert_key(keyCode)); + App::I->key_down(convert_key(keyCode)); if (!s.empty()) - App::I.key_char(s[0]); + App::I->key_char(s[0]); } }); } - (void)keyUp:(NSEvent *)theEvent { auto keyCode = [theEvent keyCode]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([keyCode] { - App::I.key_up(convert_key(keyCode)); + App::I->ui_task_async([keyCode] { + App::I->key_up(convert_key(keyCode)); }); } - (void)flagsChanged:(NSEvent *)event @@ -498,25 +397,24 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime [super flagsChanged:event]; auto flags = [event modifierFlags]; - std::lock_guard lock(task_mutex); - tasklist.emplace_back([flags] { + App::I->ui_task_async([flags] { static bool pressed_shift = false; if (pressed_shift != (flags & NSShiftKeyMask)) { pressed_shift = (flags & NSShiftKeyMask); - pressed_shift ? App::I.key_down(kKey::KeyShift) : App::I.key_up(kKey::KeyShift); + pressed_shift ? App::I->key_down(kKey::KeyShift) : App::I->key_up(kKey::KeyShift); } static bool pressed_alt = false; if (pressed_alt != (flags & NSAlternateKeyMask)) { pressed_alt = (flags & NSAlternateKeyMask); - pressed_alt ? App::I.key_down(kKey::KeyAlt) : App::I.key_up(kKey::KeyAlt); + pressed_alt ? App::I->key_down(kKey::KeyAlt) : App::I->key_up(kKey::KeyAlt); } static bool pressed_cmd = false; if (pressed_cmd != (flags & NSCommandKeyMask)) { pressed_cmd = (flags & NSCommandKeyMask); - pressed_cmd ? App::I.key_down(kKey::KeyCtrl) : App::I.key_up(kKey::KeyCtrl); + pressed_cmd ? App::I->key_down(kKey::KeyCtrl) : App::I->key_up(kKey::KeyCtrl); } }); } @@ -532,7 +430,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime } -(BOOL)windowShouldClose:(NSWindow *)sender { - return App::I.request_close(); + return App::I->request_close(); } @end @@ -555,7 +453,12 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime { LOG("open file %s", [filename UTF8String]); if (view && view->gl_ready) - App::I.open_document([filename UTF8String]); + { + App::I->ui_task_async([=] + { + App::I->open_document([filename UTF8String]); + }); + } file2open = filename; return YES; } @@ -572,17 +475,18 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime // Do some additional configuration if needed here [[BITHockeyManager sharedHockeyManager] startManager]; - if (!App::I.check_license()) + if (!App::I->check_license()) return; - App::I.initLog(); - App::I.create(); - NSRect r = NSMakeRect(0, 0, App::I.width, App::I.height); + App::I = new App; + App::I->initLog(); + App::I->create(); + NSRect r = NSMakeRect(0, 0, App::I->width, App::I->height); view = [[View alloc] initWithFrame:r]; view->file2open = file2open; controller = [[Controller alloc] initWithWindow:window]; - App::I.osx_view = view; + App::I->osx_view = view; auto style = NSTitledWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask|NSClosableWindowMask; window = [[Window alloc] initWithContentRect:r styleMask:style backing:NSBackingStoreBuffered defer:NO]; @@ -609,6 +513,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime [appMenuItem setSubmenu:appMenu]; NSLog(@"app launched"); + App::I->ui_thread_start(); } @end diff --git a/PanoPainter-OSX/main.h b/PanoPainter-OSX/main.h index 587aa31..756208a 100644 --- a/PanoPainter-OSX/main.h +++ b/PanoPainter-OSX/main.h @@ -12,7 +12,6 @@ @interface View : NSOpenGLView { @public Window* wnd; - CVDisplayLinkRef dl; NSOpenGLContext* glctx; _CGLContextObject* cgl; bool gl_ready; diff --git a/src/app.cpp b/src/app.cpp index bdffee4..381702f 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -24,6 +24,20 @@ void destroy_window(); App* App::I = nullptr; // singleton +std::deque> App::render_tasklist; +std::mutex App::render_task_mutex; +std::condition_variable App::render_cv; +std::thread App::render_thread; +std::thread::id App::render_thread_id; +bool App::render_running = false; + +std::deque> App::ui_tasklist; +std::mutex App::ui_task_mutex; +std::condition_variable App::ui_cv; +std::thread App::ui_thread; +std::thread::id App::ui_thread_id; +bool App::ui_running = false; + void App::create() { width = 1920/2; diff --git a/src/app.h b/src/app.h index 2511fc6..e93306f 100644 --- a/src/app.h +++ b/src/app.h @@ -256,12 +256,12 @@ public: // RENDER THREAD ////////////////////////////////////////////////////////////////////////// - std::deque> render_tasklist; - std::mutex render_task_mutex; - std::condition_variable render_cv; - std::thread render_thread; - std::thread::id render_thread_id; - bool render_running = false; + static std::deque> render_tasklist; + static std::mutex render_task_mutex; + static std::condition_variable render_cv; + static std::thread render_thread; + static std::thread::id render_thread_id; + static bool render_running; void render_thread_main(); void render_thread_start(); void render_thread_stop(); @@ -322,12 +322,12 @@ public: // UI THREAD ////////////////////////////////////////////////////////////////////////// - std::deque> ui_tasklist; - std::mutex ui_task_mutex; - std::condition_variable ui_cv; - std::thread ui_thread; - std::thread::id ui_thread_id; - bool ui_running = false; + static std::deque> ui_tasklist; + static std::mutex ui_task_mutex; + static std::condition_variable ui_cv; + static std::thread ui_thread; + static std::thread::id ui_thread_id; + static bool ui_running; void ui_thread_main(); void ui_thread_start(); void ui_thread_stop(); diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index 012dbf6..4676554 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -508,13 +508,7 @@ void NodeStrokePreview::draw_stroke() s_running = true; s_renderer = std::thread([] { BT_SetTerminate(); - #if __OSX__ - // There's some weird multithread bug at startup - // This random wait is a temp fix - // Today is 25/05/2019 - // Good luck, future Omar - std::this_thread::sleep_for(std::chrono::seconds(1)); - #endif + m_sampler_linear.create(); m_sampler_linear_repeat.create(GL_LINEAR, GL_REPEAT); m_sampler_mipmap.create(); @@ -553,6 +547,8 @@ void NodeStrokePreview::draw_stroke() gl.restore(); }); + + node->app_redraw(); //std::this_thread::sleep_for(std::chrono::milliseconds(30)); std::this_thread::yield(); diff --git a/src/objc_utils.cpp b/src/objc_utils.cpp index 2d963dd..3056988 100644 --- a/src/objc_utils.cpp +++ b/src/objc_utils.cpp @@ -3,6 +3,9 @@ #include "log.h" #include "app.h" #include +#include +#include +#include #ifdef __OBJC__ @implementation PathWithModDate @@ -45,8 +48,15 @@ void exception_handler(NSException *exception) LOG("exception %s\n", [[exception name] cStringUsingEncoding:NSUTF8StringEncoding]); NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"]; LOG("base:\n%s\ncallstack:\n%s", base_address.c_str(), [callstack cStringUsingEncoding:NSUTF8StringEncoding]); - if (App::I.canvas && App::I.canvas->m_canvas) - App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi"); + + auto t = std::time(nullptr); + auto tm = *std::localtime(&t); + std::ostringstream oss; + oss << std::put_time(&tm, "%d-%m-%Y %H-%M-%S"); + auto path = App::I->data_path + "/" + App::I->doc_name + "-recovery (" + oss.str() + ").ppi"; + + if (App::I->canvas && App::I->canvas->m_canvas) + App::I->canvas->m_canvas->project_save_thread(path); exit(0); } @@ -56,8 +66,15 @@ static void signal_handler (int signo) { LOG("signal %d\n", signo); NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"]; LOG("base:\n%s\ncallstack:\n%s", base_address.c_str(), [callstack cStringUsingEncoding:NSUTF8StringEncoding]); - if (App::I.canvas && App::I.canvas->m_canvas) - App::I.canvas->m_canvas->project_save_thread(App::I.data_path + "/recovery.ppi"); + + auto t = std::time(nullptr); + auto tm = *std::localtime(&t); + std::ostringstream oss; + oss << std::put_time(&tm, "%d-%m-%Y %H-%M-%S"); + auto path = App::I->data_path + "/" + App::I->doc_name + "-recovery (" + oss.str() + ").ppi"; + + if (App::I->canvas && App::I->canvas->m_canvas) + App::I->canvas->m_canvas->project_save_thread(path); exit(0); } diff --git a/src/shape.cpp b/src/shape.cpp index 859f918..68c827a 100644 --- a/src/shape.cpp +++ b/src/shape.cpp @@ -193,7 +193,7 @@ void Shape::draw_stroke() const void Shape::destroy() { - App::I->render_task_async([b1=buffers[0],b2=buffers[1],a1=arrays[0],a2=arrays[1]] + if (App::I) App::I->render_task_async([b1=buffers[0],b2=buffers[1],a1=arrays[0],a2=arrays[1]] { if (b1 || b2) {