From a3276906f9fb7b981d90ffff4a2aa125400db937 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 3 Nov 2017 21:27:33 +0000 Subject: [PATCH] implement multithreading for windows, implement file uploading when saving --- engine.vcxproj | 2 ++ engine.vcxproj.filters | 6 ++++ engine/app.cpp | 53 ++++++++++++++++++++++++++++++ engine/app.h | 1 + engine/canvas.cpp | 6 +++- engine/canvas_modes.cpp | 2 +- engine/main.cpp | 72 ++++++++++++++++++++++++++++++++++++++++- engine/util.h | 2 +- 8 files changed, 140 insertions(+), 4 deletions(-) diff --git a/engine.vcxproj b/engine.vcxproj index b8f2c16..590d27a 100644 --- a/engine.vcxproj +++ b/engine.vcxproj @@ -203,6 +203,7 @@ + @@ -311,6 +312,7 @@ + diff --git a/engine.vcxproj.filters b/engine.vcxproj.filters index 9fac23a..7aeba11 100644 --- a/engine.vcxproj.filters +++ b/engine.vcxproj.filters @@ -219,6 +219,9 @@ Source Files\libs\poly2tri + + Source Files\ui + @@ -389,6 +392,9 @@ Header Files\ui + + Header Files\ui + diff --git a/engine/app.cpp b/engine/app.cpp index 65f372c..61880b1 100644 --- a/engine/app.cpp +++ b/engine/app.cpp @@ -12,6 +12,10 @@ void android_async_lock(struct engine* engine); void android_async_swap(struct engine* engine); void android_async_unlock(struct engine* engine); +#elif _WIN32 +void async_lock(); +void async_swap(); +void async_unlock(); #endif using namespace ui; @@ -59,6 +63,43 @@ void App::initLog() LogRemote::I.file_init(); } +static size_t curl_data_handler(void *contents, size_t size, size_t nmemb, void *userp) +{ + auto buffer = reinterpret_cast(userp); + buffer->append((char*)contents, size * nmemb); + return size * nmemb; +} + +void App::upload(std::string filename) +{ + CURL *curl; + + struct curl_httppost *formpost = NULL; + struct curl_httppost *lastptr = NULL; + + //curl_global_init(CURL_GLOBAL_ALL); + + curl_formadd(&formpost, + &lastptr, + CURLFORM_COPYNAME, "fileToUpload", + CURLFORM_FILE, filename.c_str(), + CURLFORM_END); + + curl = curl_easy_init(); + std::string res; + + if (curl) + { + curl_easy_setopt(curl, CURLOPT_URL, "http://omigamedev.ddns.net:8080/upload/upl.php"); + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &res); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_handler); + auto err = curl_easy_perform(curl); //here it crashes + std::cout << "\n\nUPLOAD RESULT\n" << res << "\n\n\n"; + curl_easy_cleanup(curl); + } +} + void App::init() { #ifdef _WIN32 @@ -133,6 +174,9 @@ void App::async_start() [ios_view async_lock]; #elif __ANDROID__ android_async_lock(and_engine); +#elif _WIN32 + async_lock(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif } @@ -140,6 +184,8 @@ void App::async_update() { #if __IOS__ [ios_view->glview bindDrawable]; +#elif _WIN32 + glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif redraw = true; clear(); @@ -151,6 +197,8 @@ void App::async_update() [ios_view async_swap]; #elif __ANDROID__ android_async_swap(and_engine); +#elif _WIN32 + async_swap(); #endif } @@ -162,11 +210,16 @@ void App::async_end() [ios_view async_unlock]; #elif __ANDROID__ android_async_unlock(and_engine); +#elif _WIN32 + async_unlock(); #endif } void App::update(float dt) { + static std::mutex m; + std::lock_guard _lock(m); + // update offscreen stuff if (canvas && canvas->m_canvas) canvas->m_canvas->stroke_draw(); diff --git a/engine/app.h b/engine/app.h index 44f9697..8a84458 100644 --- a/engine/app.h +++ b/engine/app.h @@ -92,6 +92,7 @@ public: void initShaders(); void initAssets(); void initLayout(); + void upload(std::string filename); void create(); void terminate(); void clear(); diff --git a/engine/canvas.cpp b/engine/canvas.cpp index d8bbf6a..8f8e411 100644 --- a/engine/canvas.cpp +++ b/engine/canvas.cpp @@ -1213,6 +1213,10 @@ void ui::Canvas::project_save_thread(std::string data_path) } fclose(fp); LOG("project saved to %s", data_path.c_str()); + + App::I.upload(data_path); + LOG("uploaded"); + App::I.async_start(); pb->destroy(); App::I.async_update(); @@ -1284,7 +1288,6 @@ void ui::Canvas::project_open_thread(std::string data_path) { int n_order; fread(&n_order, sizeof(int), 1, fp); - m_order.push_back(n_order); int name_len; fread(&name_len, sizeof(int), 1, fp); @@ -1327,6 +1330,7 @@ void ui::Canvas::project_open_thread(std::string data_path) m_layers.emplace_back(); m_layers.back().create(m_width, m_height, name.c_str()); m_layers.back().restore(snap); + m_order.push_back(n_order); App::I.async_end(); } fclose(fp); diff --git a/engine/canvas_modes.cpp b/engine/canvas_modes.cpp index 9bb6f74..1fb4699 100644 --- a/engine/canvas_modes.cpp +++ b/engine/canvas_modes.cpp @@ -146,7 +146,7 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const ui::ShaderManager::u_float(ui::kShaderUniform::Alpha, node->m_brush.m_tip_flow); auto tip_color = glm::vec4(glm::vec3(node->m_brush.m_tip_color), 1); ui::ShaderManager::u_vec4(ui::kShaderUniform::Col, tip_color); - ui::ShaderManager::u_int(ui::kShaderUniform::Highlight, 0); + //ui::ShaderManager::u_int(ui::kShaderUniform::Highlight, 0); float tip_scale = 1.f / glm::tan(glm::radians(ui::Canvas::I->m_cam_fov * 0.5f)); ui::ShaderManager::u_mat4(ui::kShaderUniform::MVP, glm::scale(glm::vec3(1, -1, 1)) * diff --git a/engine/main.cpp b/engine/main.cpp index 70fdb85..587cde7 100644 --- a/engine/main.cpp +++ b/engine/main.cpp @@ -19,10 +19,74 @@ HDC hDC; HGLRC hRC; wchar_t* className; bool keys[256]; +std::mutex gl_mutex; +std::mutex async_mutex; +std::thread::id gl_thread; +int gl_count = 0; #include #include "wacom.h" +//Returns the last Win32 error, in string format. Returns an empty string if there is no error. +std::string GetLastErrorAsString() +{ + //Get the error message, if any. + DWORD errorMessageID = ::GetLastError(); + if (errorMessageID == 0) + return std::string(); //No error message has been recorded + + LPSTR messageBuffer = nullptr; + size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + + std::string message(messageBuffer, size); + + //Free the buffer. + LocalFree(messageBuffer); + + return message; +} + +void async_lock() +{ + //std::lock_guard _lock(async_mutex); + if (gl_count == 0 || gl_thread != std::this_thread::get_id()) + { + gl_mutex.lock(); + 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); +} + +void async_swap() +{ + SwapBuffers(hDC); + //LOG("swap"); +} + +void async_unlock() +{ + //std::lock_guard _lock(async_mutex); + gl_count--; + if (gl_count == 0) + { + //LOG("unlock"); + wglMakeCurrent(0, 0); + gl_mutex.unlock(); + } +} + +struct async_locker +{ + async_locker() { async_lock(); } + ~async_locker() { async_unlock(); } +}; + int read_WMI_info() { // see: http://win32easy.blogspot.co.uk/2011/03/wmi-in-c-query-everyting-from-your-os.html @@ -303,9 +367,14 @@ int main(int argc, char** argv) t0 = t1; if (App::I.redraw) { + async_lock(); + App::I.redraw = true; + glBindFramebuffer(GL_FRAMEBUFFER, 0); App::I.clear(); App::I.update((float)(t1 - t0) / 1000.0f); SwapBuffers(hDC); + async_unlock(); + //LOG("swap main"); } } // else @@ -323,6 +392,7 @@ int main(int argc, char** argv) LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { + async_locker lock; static bool leftDown = false; static DWORD lastTime; static POINT lastPoint; @@ -368,7 +438,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) App::I.key_up(convert_key((int)wp)); break; case WM_CHAR: - //App::I.key_char((int)wp); + App::I.key_char((int)wp); break; case WM_MOUSEMOVE: //TODO: find a way to check if event is mouse/stylus. For now use Mouse for all diff --git a/engine/util.h b/engine/util.h index 5941869..90e6f65 100644 --- a/engine/util.h +++ b/engine/util.h @@ -158,7 +158,7 @@ struct gl_state glBindSampler(i, sampler[i]); } glActiveTexture(active_tex); - glBindTexture(GL_TEXTURE_BINDING_CUBE_MAP, cube); + glBindTexture(GL_TEXTURE_CUBE_MAP, cube); } };