diff --git a/engine/main.cpp b/engine/main.cpp index dbfb2b6..e7d6b1e 100644 --- a/engine/main.cpp +++ b/engine/main.cpp @@ -8,10 +8,17 @@ #include "keymap.h" #include "../resource.h" +#include +#include "wacom.h" +#include +#include + #pragma comment (lib, "opengl32.lib") #pragma comment (lib, "glew32.lib") #pragma comment(lib, "wbemuuid.lib") +#define WM_USER_CLOSE (WM_USER + 1) + LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); HINSTANCE hInst; HWND hWnd; @@ -24,11 +31,7 @@ std::mutex async_mutex; std::thread::id gl_thread; int gl_count = 0; std::deque> tasklist; - -#include -#include "wacom.h" -#include -#include +std::mutex task_mutex; //Returns the last Win32 error, in string format. Returns an empty string if there is no error. std::string GetLastErrorAsString() @@ -52,7 +55,7 @@ std::string GetLastErrorAsString() void destroy_window() { - DestroyWindow(hWnd); + SendMessage(hWnd, WM_USER_CLOSE, 0, 0); } void async_lock() @@ -427,6 +430,7 @@ int main(int argc, char** argv) std::condition_variable render_cv; std::thread renderer([&] { + BT_SetTerminate(); const float target_fps = 10; unsigned long t0 = GetTickCount(); unsigned long t1; @@ -450,6 +454,24 @@ int main(int argc, char** argv) frames = 0; } + { + std::deque> working_list; + { + std::lock_guard lock(task_mutex); + working_list = std::move(tasklist); + } + + async_lock(); + while (!working_list.empty()) + { + + working_list.front()(); + working_list.pop_front(); + } + async_unlock(); + } + + std::unique_lock lock(render_mutex); if (render_timer > 1.0f / target_fps || App::I.redraw) { render_timer = 0; @@ -467,7 +489,6 @@ int main(int argc, char** argv) } frames++; - std::unique_lock 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)); @@ -477,12 +498,6 @@ int main(int argc, char** argv) 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); @@ -493,7 +508,9 @@ int main(int argc, char** argv) DispatchMessage(&msg); TranslateMessage(&msg); } - render_cv.notify_all(); + + if (!tasklist.empty()) + render_cv.notify_all(); } render_cv.notify_all(); if (renderer.joinable()) @@ -501,7 +518,7 @@ int main(int argc, char** argv) App::I.terminate(); // Clean up WacomTablet::I.terminate(); - DestroyWindow(hWnd); + //DestroyWindow(hWnd); UnregisterClass(className, hInst); LogRemote::I.stop(); } @@ -513,6 +530,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) static POINT lastPoint; switch (msg) { + case WM_USER_CLOSE: + DestroyWindow(hWnd); + PostQuitMessage(0); + break; case WM_PAINT: App::I.redraw = true; break; @@ -522,7 +543,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) case WM_CLOSE: if (App::I.request_close()) PostQuitMessage(0); - else return true; + else + return true; break; case WM_SIZE: { @@ -550,112 +572,76 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) break; case WM_SYSKEYDOWN: case WM_KEYDOWN: - async_lock(); - keys[wp] = true; - App::I.key_down(convert_key((int)wp)); - async_unlock(); - break; - case WM_SYSKEYUP: - case WM_KEYUP: - async_lock(); - keys[wp] = false; - App::I.key_up(convert_key((int)wp)); - async_unlock(); - break; - case WM_CHAR: - async_lock(); - App::I.key_char((int)wp); - async_unlock(); - break; - case WM_MOUSEMOVE: - 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); + std::lock_guard lock(task_mutex); + tasklist.emplace_back([wp] { + App::I.key_down(convert_key((int)wp)); }); break; } - //TODO: find a way to check if event is mouse/stylus. For now use Mouse for all - if (0 && leftDown) + break; + case WM_SYSKEYUP: + case WM_KEYUP: { - POINT pt = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) }; - // See discussion for why this code is wrong - ClientToScreen(hWnd, &pt); - MOUSEMOVEPOINT mmpt = { pt.x & 0x0000FFFF, pt.y & 0x0000FFFF, GetMessageTime() }; - MOUSEMOVEPOINT rgmmpt[64]; - int cmmpt = GetMouseMovePointsEx(sizeof(mmpt), &mmpt, - rgmmpt, 64, GMMP_USE_DISPLAY_POINTS); - - if (cmmpt == -1 || cmmpt == 64) - { - App::I.mouse_move((float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), WacomTablet::I.get_pressure(), kEventSource::Mouse); - lastPoint = pt; - lastTime = GetMessageTime(); - break; - } - - POINT ptLastScreen = lastPoint; - ClientToScreen(hWnd, &ptLastScreen); - int i; - for (i = 0; i < cmmpt; i++) - { - if (rgmmpt[i].x > 32767) rgmmpt[i].x -= 65536; - if (rgmmpt[i].y > 32767) rgmmpt[i].y -= 65536; - LOG("x %4d y %4d", rgmmpt[i].x, rgmmpt[i].y); - - if (rgmmpt[i].time < lastTime) break; - if (rgmmpt[i].time == lastTime && - rgmmpt[i].x == ptLastScreen.x && - rgmmpt[i].y == ptLastScreen.y) break; - } - while (--i >= 0) - { - POINT ptClient = { rgmmpt[i].x, rgmmpt[i].y }; - ScreenToClient(hWnd, &ptClient); - if (ptClient.x != lastPoint.x || ptClient.y != lastPoint.y) - { - lastPoint = ptClient; - App::I.mouse_move((float)ptClient.x, (float)ptClient.y, WacomTablet::I.get_pressure(), kEventSource::Mouse); - } - } - lastTime = GetMessageTime(); + std::lock_guard lock(task_mutex); + tasklist.emplace_back([wp] { + App::I.key_up(convert_key((int)wp)); + }); } - else + break; + case WM_CHAR: { - App::I.mouse_move((float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), WacomTablet::I.get_pressure(), kEventSource::Mouse); + std::lock_guard lock(task_mutex); + tasklist.emplace_back([wp]{ + App::I.key_char((int)wp); + }); + } + break; + case WM_MOUSEMOVE: + { + std::lock_guard lock(task_mutex); + 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); + }); } - async_unlock(); break; case WM_LBUTTONDOWN: - //TODO: find a way to check if event is mouse/stylus. For now use Mouse for all - async_lock(); - leftDown = true; SetCapture(hWnd); - lastTime = GetMessageTime(); - lastPoint = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) }; - App::I.mouse_down(0, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), WacomTablet::I.get_pressure(), kEventSource::Mouse); - async_unlock(); + { + std::lock_guard lock(task_mutex); + tasklist.emplace_back([lp, p = WacomTablet::I.get_pressure()]{ + App::I.mouse_down(0, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), p, kEventSource::Mouse); + }); + } break; case WM_LBUTTONUP: - async_lock(); WacomTablet::I.reset_pressure(); - //TODO: find a way to check if event is mouse/stylus. For now use Mouse for all - App::I.mouse_up(0, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), kEventSource::Mouse); ReleaseCapture(); - leftDown = false; - async_unlock(); + { + std::lock_guard lock(task_mutex); + tasklist.emplace_back([lp]{ + App::I.mouse_up(0, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), kEventSource::Mouse); + }); + } break; case WM_RBUTTONDOWN: - async_lock(); - App::I.mouse_down(1, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), 1.f, kEventSource::Mouse); SetCapture(hWnd); - async_unlock(); + { + std::lock_guard lock(task_mutex); + tasklist.emplace_back([lp]{ + App::I.mouse_down(1, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), 1.f, kEventSource::Mouse); + }); + } break; case WM_RBUTTONUP: - async_lock(); - App::I.mouse_up(1, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), kEventSource::Mouse); ReleaseCapture(); - async_unlock(); + { + std::lock_guard lock(task_mutex); + tasklist.emplace_back([lp]{ + App::I.mouse_up(1, (float)GET_X_LPARAM(lp), (float)GET_Y_LPARAM(lp), kEventSource::Mouse); + }); + break; + } break; case WM_MOUSEWHEEL: { @@ -664,8 +650,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) pt.x = GET_X_LPARAM(lp); pt.y = GET_Y_LPARAM(lp); ScreenToClient(hWnd, &pt); - App::I.mouse_scroll((float)pt.x, (float)pt.y, - (float)GET_WHEEL_DELTA_WPARAM(wp) / (float)WHEEL_DELTA); + { + std::lock_guard lock(task_mutex); + tasklist.emplace_back([pt, wp] { + App::I.mouse_scroll((float)pt.x, (float)pt.y, + (float)GET_WHEEL_DELTA_WPARAM(wp) / (float)WHEEL_DELTA); + }); + } break; } case WM_POINTERUPDATE: diff --git a/engine/node_image_texture.cpp b/engine/node_image_texture.cpp index 93709e2..d440d0e 100644 --- a/engine/node_image_texture.cpp +++ b/engine/node_image_texture.cpp @@ -20,7 +20,7 @@ void NodeImageTexture::draw() { using namespace ui; tex.bind(); - auto& sampler = tex.has_mips ? NodeImage::m_sampler : NodeImage::m_sampler_mips; + auto& sampler = tex.has_mips ? NodeImage::m_sampler_mips : NodeImage::m_sampler; sampler.bind(0); glEnable(GL_BLEND); ui::ShaderManager::use(kShader::Texture);