decouple windows events and render in a separate thread for better response

This commit is contained in:
2018-08-08 12:50:39 +02:00
parent 9cccecd381
commit 91add1b0b3
3 changed files with 88 additions and 22 deletions

View File

@@ -438,7 +438,7 @@
<Filter>libs\yoga</Filter>
</ClInclude>
<ClInclude Include="engine\node_panel_grid.h">
<Filter>Source Files\ui</Filter>
<Filter>Header Files\ui</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>

View File

@@ -14,6 +14,7 @@ void android_async_lock(struct engine* engine);
void android_async_swap(struct engine* engine);
void android_async_unlock(struct engine* engine);
#elif _WIN32
bool async_lock_try();
void async_lock();
void async_swap();
void async_unlock();
@@ -119,7 +120,7 @@ void App::initLog()
rec_path = data_path + "\\frames";
#endif
LogRemote::I.start();
//LogRemote::I.start();
LogRemote::I.file_init();
}

View File

@@ -23,9 +23,12 @@ std::mutex gl_mutex;
std::mutex async_mutex;
std::thread::id gl_thread;
int gl_count = 0;
std::deque<std::packaged_task<void()>> tasklist;
#include <WbemCli.h>
#include "wacom.h"
#include <deque>
#include <chrono>
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
@@ -68,6 +71,24 @@ void async_lock()
//assert(ret == true);
}
bool async_lock_try()
{
//std::lock_guard<std::mutex> _lock(async_mutex);
if (gl_count == 0 || gl_thread != std::this_thread::get_id())
{
if (!gl_mutex.try_lock())
return false;
bool ret = wglMakeCurrent(hDC, hRC);
if (ret == false)
LOG("FAILED wglMakeCurrent: %s", GetLastErrorAsString().c_str());
gl_thread = std::this_thread::get_id();
//LOG("lock");
}
gl_count++;
//assert(ret == true);
return true;
}
void async_swap()
{
SwapBuffers(hDC);
@@ -401,30 +422,37 @@ int main(int argc, char** argv)
App::I.redraw = true;
});
MSG msg;
bool running = true;
std::mutex render_mutex;
std::condition_variable render_cv;
std::thread renderer([&] {
const float target_fps = 10;
unsigned long t0 = GetTickCount();
unsigned long t1;
int frames = 0;
float one_sec = 0;
while (running)
{
// If there any message in the queue process it
auto present = App::I.animate || App::I.redraw ?
PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0);
running = !(msg.message == WM_QUIT/* || gl.keys[VK_ESCAPE]*/);
if (present)
{
DispatchMessage(&msg);
TranslateMessage(&msg);
}
//else // Otherwise render next frame
float render_timer = 0;
while(running)
{
t1 = GetTickCount();
float dt = (float)(t1 - t0) / 1000.0f;
if (dt > 1.0f / 60.0f || App::I.redraw)
{
one_sec += dt;
render_timer += dt;
t0 = t1;
if (one_sec > 1.f)
{
static char title[512];
sprintf_s(title, "PanoPainter 0.1.2 alpha - OpenGL 3.1 - %d fps", frames);
SetWindowTextA(hWnd, title);
one_sec = 0;
frames = 0;
}
if (render_timer > 1.0f / target_fps || App::I.redraw)
{
render_timer = 0;
if (App::I.redraw)
{
async_lock();
@@ -437,8 +465,39 @@ int main(int argc, char** argv)
//LOG("swap main");
}
}
frames++;
std::unique_lock<std::mutex> lock(render_mutex);
const int framerate = (1.f / target_fps) * 1000;
const int diff = framerate - (t1 - t0);
render_cv.wait_for(lock, std::chrono::milliseconds(diff));
}
});
MSG msg;
while (running)
{
while (!tasklist.empty())
{
tasklist.front()();
tasklist.pop_front();
}
// If there any message in the queue process it
auto present = App::I.animate || App::I.redraw ?
PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0);
running = !(msg.message == WM_QUIT/* || gl.keys[VK_ESCAPE]*/);
if (present)
{
DispatchMessage(&msg);
TranslateMessage(&msg);
}
render_cv.notify_all();
}
render_cv.notify_all();
if (renderer.joinable())
renderer.join();
App::I.terminate();
// Clean up
WacomTablet::I.terminate();
@@ -509,7 +568,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
async_unlock();
break;
case WM_MOUSEMOVE:
async_lock();
if (!async_lock_try())
{
tasklist.emplace_back([lp,p=WacomTablet::I.get_pressure()] {
App::I.mouse_move((float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), p, kEventSource::Mouse);
});
break;
}
//TODO: find a way to check if event is mouse/stylus. For now use Mouse for all
if (0 && leftDown)
{