From 27f4cb3ba8d3be7d4a943b39d380f32b34427eff Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 1 Mar 2019 15:16:05 +0100 Subject: [PATCH] restore multithreading on iOS and use DisplayLink to decouple rendering from the main loop --- PanoPainter/GameViewController.h | 3 + PanoPainter/GameViewController.m | 112 ++++++++++++++++++------------- src/canvas.cpp | 34 ---------- src/node_stroke_preview.cpp | 1 + 4 files changed, 69 insertions(+), 81 deletions(-) diff --git a/PanoPainter/GameViewController.h b/PanoPainter/GameViewController.h index 4a0f86b..902e5f7 100644 --- a/PanoPainter/GameViewController.h +++ b/PanoPainter/GameViewController.h @@ -21,6 +21,7 @@ > { @public GameView* glview; +@public CADisplayLink *displayLink; } - (void)display_file:(std::string)filename; - (void)reset_touch; @@ -32,4 +33,6 @@ - (void)unregisterForKeyboardNotifications; - (void)crash; - (void)share_file:(NSString*)file_path; +- (void)tick; +- (void)render_loop; @end diff --git a/PanoPainter/GameViewController.m b/PanoPainter/GameViewController.m index 2f1e463..0d4f763 100644 --- a/PanoPainter/GameViewController.m +++ b/PanoPainter/GameViewController.m @@ -14,6 +14,8 @@ std::deque> tasklist; std::mutex task_mutex; +std::mutex render_mutex; +std::condition_variable render_cv; @interface GameImagePicker : UIImagePickerController { @@ -432,6 +434,64 @@ std::set ignored_touch; return YES; } +-(void)tick +{ + //std::lock_guard lock(render_mutex); + render_cv.notify_one(); +} + +-(void)render_loop +{ + while (true) + { + static auto time = std::chrono::steady_clock::now(); + static double elapsed = 0; + static double min_fps_timer = 0; + auto now = std::chrono::steady_clock::now(); + auto dt = std::chrono::duration(now - time); + time = now; + elapsed += dt.count(); + min_fps_timer += dt.count(); + + if (min_fps_timer > 0.5) + { + App::I.redraw = true; + min_fps_timer = 0; + } + + std::deque> working_list; + if (!tasklist.empty()) + { + std::lock_guard lock(task_mutex); + working_list = std::move(tasklist); + } + + App::I.tick(dt.count()); + + if (!(App::I.redraw || App::I.animate || !working_list.empty())) + { + //[self.context presentRenderbuffer:GL_FRAMEBUFFER]; + //[self async_unlock]; + std::unique_lock lock(render_mutex); + render_cv.wait(lock); + continue; + } + + [self async_lock]; + while (!working_list.empty()) + { + working_list.front()(); + working_list.pop_front(); + } + App::I.clear(); + App::I.update(elapsed); + [self.context presentRenderbuffer:GL_FRAMEBUFFER]; + [self async_unlock]; + [self->glview display]; + elapsed = 0; + } +} + - (void)setupGL { [self async_lock]; @@ -439,54 +499,12 @@ std::set ignored_touch; [self async_unlock]; std::thread([self]{ - while (true) - { - static auto time = std::chrono::steady_clock::now(); - static double elapsed = 0; - static double min_fps_timer = 0; - auto now = std::chrono::steady_clock::now(); - auto dt = std::chrono::duration(now - time); - time = now; - elapsed += dt.count(); - min_fps_timer += dt.count(); - - if (min_fps_timer > 0.1) - { - App::I.redraw = true; - min_fps_timer = 0; - } - - std::deque> working_list; - if (!tasklist.empty()) - { - std::lock_guard lock(task_mutex); - working_list = std::move(tasklist); - } - - App::I.tick(dt.count()); - - [self async_lock]; - if (!(App::I.redraw || App::I.animate || !working_list.empty())) - { - //[self.context presentRenderbuffer:GL_FRAMEBUFFER]; - [self async_unlock]; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - continue; - } - - while (!working_list.empty()) - { - working_list.front()(); - working_list.pop_front(); - } - App::I.clear(); - App::I.update(elapsed); - [self.context presentRenderbuffer:GL_FRAMEBUFFER]; - [self async_unlock]; - [self->glview display]; - elapsed = 0; - } + [self render_loop]; }).detach(); + + displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick)]; + displayLink.frameInterval = 4; + [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } - (void)tearDownGL diff --git a/src/canvas.cpp b/src/canvas.cpp index 9730058..05749f4 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1176,10 +1176,6 @@ void Canvas::clear_context() void Canvas::import_equirectangular(std::string file_path) { -#if __IOS__ - import_equirectangular_thread(file_path); - return; -#endif std::thread t(&Canvas::import_equirectangular_thread, this, file_path); t.detach(); } @@ -1253,12 +1249,6 @@ void Canvas::export_equirectangular(std::string file_path, std::function { if (App::I.check_license()) { -#if __IOS__ - export_equirectangular_thread(file_path); - if (on_complete) - on_complete(); - return; -#endif std::thread t([=] { export_equirectangular_thread(file_path); if (on_complete) @@ -1563,12 +1553,6 @@ void Canvas::export_layers(std::string file_name, std::function on_compl { if (App::I.check_license()) { -#if __IOS__ - export_layers_thread(file_name); - if (on_complete) - on_complete(); - return; -#endif std::thread t([=] { export_layers_thread(file_name); if (on_complete) @@ -1824,12 +1808,6 @@ void Canvas::project_save(std::function on_complete) { if (App::I.check_license()) { -#if __IOS__ - bool ret = project_save_thread(App::I.doc_path); - if (on_complete) - on_complete(ret); - return; -#endif std::thread t([=] { bool ret = project_save_thread(App::I.doc_path); if (on_complete) @@ -1844,12 +1822,6 @@ void Canvas::project_save(std::string file_path, std::function on_co LOG("saving %s", file_path.c_str()); if (App::I.check_license()) { -#if __IOS__ - bool ret = project_save_thread(file_path); - if (on_complete) - on_complete(ret); - return; -#endif std::thread t([=] { bool ret = project_save_thread(file_path); if (on_complete) @@ -2046,12 +2018,6 @@ bool Canvas::project_save_thread(std::string file_path) void Canvas::project_open(std::string file_path, std::function on_complete) { -#if __IOS__ - bool ret = project_open_thread(file_path); - if (on_complete) - on_complete(ret); - return; -#endif std::thread t([=] { bool result = project_open_thread(file_path); if (on_complete) diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index 9ba92b0..bda593c 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -492,6 +492,7 @@ void NodeStrokePreview::draw_stroke() gl.save(); node->draw_stroke_immediate(); gl.restore(); + node->app_redraw(); node->async_end(); std::this_thread::sleep_for(std::chrono::milliseconds(30)); }