update osx project

This commit is contained in:
2019-07-11 22:33:58 +02:00
parent b89274e7a6
commit c4633a906f
7 changed files with 114 additions and 183 deletions

View File

@@ -17,9 +17,6 @@
#include <deque>
#include <chrono>
std::deque<std::packaged_task<void()>> 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<std::packaged_task<void()>> working_list;
{
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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

View File

@@ -12,7 +12,6 @@
@interface View : NSOpenGLView<NSSharingServiceDelegate>
{
@public Window* wnd;
CVDisplayLinkRef dl;
NSOpenGLContext* glctx;
_CGLContextObject* cgl;
bool gl_ready;

View File

@@ -24,6 +24,20 @@ void destroy_window();
App* App::I = nullptr; // singleton
std::deque<std::packaged_task<void()>> 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<std::packaged_task<void()>> 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;

View File

@@ -256,12 +256,12 @@ public:
// RENDER THREAD
//////////////////////////////////////////////////////////////////////////
std::deque<std::packaged_task<void()>> 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<std::packaged_task<void()>> 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<std::packaged_task<void()>> 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<std::packaged_task<void()>> 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();

View File

@@ -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();
@@ -554,6 +548,8 @@ void NodeStrokePreview::draw_stroke()
gl.restore();
});
node->app_redraw();
//std::this_thread::sleep_for(std::chrono::milliseconds(30));
std::this_thread::yield();
}

View File

@@ -3,6 +3,9 @@
#include "log.h"
#include "app.h"
#include <atomic>
#include <iomanip>
#include <ctime>
#include <sstream>
#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);
}

View File

@@ -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)
{