decouple windows events and render in a separate thread for better response
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user