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> <Filter>libs\yoga</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="engine\node_panel_grid.h"> <ClInclude Include="engine\node_panel_grid.h">
<Filter>Source Files\ui</Filter> <Filter>Header Files\ui</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<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_swap(struct engine* engine);
void android_async_unlock(struct engine* engine); void android_async_unlock(struct engine* engine);
#elif _WIN32 #elif _WIN32
bool async_lock_try();
void async_lock(); void async_lock();
void async_swap(); void async_swap();
void async_unlock(); void async_unlock();
@@ -119,7 +120,7 @@ void App::initLog()
rec_path = data_path + "\\frames"; rec_path = data_path + "\\frames";
#endif #endif
LogRemote::I.start(); //LogRemote::I.start();
LogRemote::I.file_init(); LogRemote::I.file_init();
} }

View File

@@ -23,9 +23,12 @@ std::mutex gl_mutex;
std::mutex async_mutex; std::mutex async_mutex;
std::thread::id gl_thread; std::thread::id gl_thread;
int gl_count = 0; int gl_count = 0;
std::deque<std::packaged_task<void()>> tasklist;
#include <WbemCli.h> #include <WbemCli.h>
#include "wacom.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. //Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString() std::string GetLastErrorAsString()
@@ -68,6 +71,24 @@ void async_lock()
//assert(ret == true); //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() void async_swap()
{ {
SwapBuffers(hDC); SwapBuffers(hDC);
@@ -401,30 +422,37 @@ int main(int argc, char** argv)
App::I.redraw = true; App::I.redraw = true;
}); });
MSG msg;
bool running = true; bool running = true;
unsigned long t0 = GetTickCount(); std::mutex render_mutex;
unsigned long t1; std::condition_variable render_cv;
float one_sec = 0;
while (running) std::thread renderer([&] {
{ const float target_fps = 10;
// If there any message in the queue process it unsigned long t0 = GetTickCount();
auto present = App::I.animate || App::I.redraw ? unsigned long t1;
PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0); int frames = 0;
float one_sec = 0;
running = !(msg.message == WM_QUIT/* || gl.keys[VK_ESCAPE]*/); float render_timer = 0;
if (present) while(running)
{
DispatchMessage(&msg);
TranslateMessage(&msg);
}
//else // Otherwise render next frame
{ {
t1 = GetTickCount(); t1 = GetTickCount();
float dt = (float)(t1 - t0) / 1000.0f; 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)
{ {
t0 = t1; 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) if (App::I.redraw)
{ {
async_lock(); async_lock();
@@ -437,8 +465,39 @@ int main(int argc, char** argv)
//LOG("swap main"); //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(); App::I.terminate();
// Clean up // Clean up
WacomTablet::I.terminate(); WacomTablet::I.terminate();
@@ -509,7 +568,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
async_unlock(); async_unlock();
break; break;
case WM_MOUSEMOVE: 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 //TODO: find a way to check if event is mouse/stylus. For now use Mouse for all
if (0 && leftDown) if (0 && leftDown)
{ {