From f7ead8e15783912034eb0205e26f646febd28869 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Mon, 8 Jul 2019 16:57:30 +0200 Subject: [PATCH] remove all async_start/end calls --- src/app.cpp | 157 ++++--- src/app.h | 1 + src/app_cloud.cpp | 38 +- src/app_layout.cpp | 23 +- src/canvas.cpp | 792 ++++++++++++++++-------------------- src/canvas_actions.cpp | 19 +- src/canvas_modes.cpp | 33 +- src/main.cpp | 40 +- src/node.cpp | 15 - src/node.h | 3 - src/node_dialog_browse.cpp | 3 - src/node_dialog_cloud.cpp | 14 - src/node_dialog_open.cpp | 6 - src/node_panel_brush.cpp | 3 - src/node_panel_grid.cpp | 5 - src/node_panel_stroke.cpp | 20 - src/node_stroke_preview.cpp | 1 + src/util.cpp | 41 ++ src/util.h | 38 +- 19 files changed, 531 insertions(+), 721 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index e5adf56..9817818 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -566,22 +566,87 @@ bool App::update_ui_observer(Node *n) return false; } -void App::update(float dt) +void App::draw(float dt) { - static std::mutex mutex; - static float rec_timer = 0.f; - static float reload_timer = 0.f; - - // avoid multiple threads to update the scene - std::lock_guard lock(mutex); - - static std::mutex m; - std::lock_guard _lock(m); - // update offscreen stuff if (canvas && canvas->m_canvas) canvas->m_canvas->stroke_draw(); + auto observer = std::bind(&App::update_ui_observer, this, std::placeholders::_1); + + if (vr_active && ui_visible) + { + uirtt.bindFramebuffer(); + uirtt.clear(); + glViewport(0, 0, uirtt.getWidth(), uirtt.getHeight()); + glEnable(GL_SCISSOR_TEST); + for (int i = 1; i < layout[main_id]->m_children.size(); i++) + layout[main_id]->m_children[i]->watch(observer); + //msgbox->watch(observer); + glDisable(GL_SCISSOR_TEST); + uirtt.unbindFramebuffer(); + } + + if (!vr_only) + { +#if __IOS__ + [ios_view->glview bindDrawable]; +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + glViewport(off_x, off_y, (GLsizei)width, (GLsizei)height); + glEnable(GL_SCISSOR_TEST); + for (int i = 0; i < layout[main_id]->m_children.size(); i++) + layout[main_id]->m_children[i]->watch(observer); + //msgbox->watch(observer); + glDisable(GL_SCISSOR_TEST); + } + + if (rec_running) + { + static float rec_timer = 0.f; + rec_timer += dt; + if (rec_timer > 1.f && canvas->m_canvas->m_dirty_stroke) + { + canvas->m_canvas->m_dirty_stroke = false; + + LOG("rec tick"); + rec_timer = 0.f; + + auto data = new uint8_t[width * height * 4]; +#if __IOS__ + [ios_view->glview bindDrawable]; +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + + GLint dfbo, rfbo; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &rfbo); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &dfbo); + if (dfbo != rfbo) + LOG("DIFFERENT FB"); + + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + { + std::lock_guard lock(rec_mutex); + rec_frames.emplace_back(data); + rec_cv.notify_all(); + } + update_rec_frames(); + } + } + + redraw = false; +} + +void App::update(float dt) +{ + static std::mutex mutex; + static float reload_timer = 0.f; + + // avoid multiple threads to update the scene + //std::lock_guard lock(mutex); + if (!(redraw || animate)) return; @@ -620,71 +685,6 @@ void App::update(float dt) layout[main_id]->find("btn-mask-line")->set_active(mode == kCanvasMode::MaskLine); layout[main_id]->find("btn-bucket")->set_active(mode == kCanvasMode::FloodFill); } - - auto observer = std::bind(&App::update_ui_observer, this, std::placeholders::_1); - - if (vr_active && ui_visible) - { - uirtt.bindFramebuffer(); - uirtt.clear(); - glViewport(0, 0, uirtt.getWidth(), uirtt.getHeight()); - glEnable(GL_SCISSOR_TEST); - for (int i = 1; i < layout[main_id]->m_children.size(); i++) - layout[main_id]->m_children[i]->watch(observer); - //msgbox->watch(observer); - glDisable(GL_SCISSOR_TEST); - uirtt.unbindFramebuffer(); - } - - if (!vr_only) - { -#if __IOS__ - [ios_view->glview bindDrawable]; -#else - glBindFramebuffer(GL_FRAMEBUFFER, 0); -#endif - glViewport(off_x, off_y, (GLsizei)width, (GLsizei)height); - glEnable(GL_SCISSOR_TEST); - for (int i = 0; i < layout[main_id]->m_children.size(); i++) - layout[main_id]->m_children[i]->watch(observer); - //msgbox->watch(observer); - glDisable(GL_SCISSOR_TEST); - } - - if (rec_running) - { - rec_timer += dt; - if (rec_timer > 1.f && canvas->m_canvas->m_dirty_stroke) - { - canvas->m_canvas->m_dirty_stroke = false; - - LOG("rec tick"); - rec_timer = 0.f; - - auto data = new uint8_t[width * height * 4]; - #if __IOS__ - [ios_view->glview bindDrawable]; - #else - glBindFramebuffer(GL_FRAMEBUFFER, 0); - #endif - - GLint dfbo, rfbo; - glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &rfbo); - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &dfbo); - if (dfbo != rfbo) - LOG("DIFFERENT FB"); - - glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); - { - std::lock_guard lock(rec_mutex); - rec_frames.emplace_back(data); - rec_cv.notify_all(); - } - update_rec_frames(); - } - } - - redraw = false; } void App::terminate() @@ -803,9 +803,7 @@ void App::rec_stop() rec_cv.notify_all(); if (rec_thread.joinable()) rec_thread.join(); - async_start(); update_rec_frames(); - async_end(); } } @@ -821,7 +819,6 @@ void App::rec_export(std::string path) auto pb = layout[main_id]->add_child(); pb->m_progress->SetWidthP(0); pb->m_title->set_text("Exporting MP4 movie"); - async_update(); #if defined(__IOS__) || defined(__OSX__) NSString* mov_path = [NSString stringWithFormat:@"%s/out.mp4", rec_path.c_str()]; @@ -978,8 +975,6 @@ void App::rec_export(std::string path) #endif pb->destroy(); - async_update(); - } void App::rec_loop() diff --git a/src/app.h b/src/app.h index 56ce4f3..1816f69 100644 --- a/src/app.h +++ b/src/app.h @@ -165,6 +165,7 @@ public: void terminate(); void clear(); void tick(float dt); + void draw(float dt); void update(float dt); bool update_ui_observer(Node* n); bool vr_start(); diff --git a/src/app_cloud.cpp b/src/app_cloud.cpp index 61ff50f..77a739b 100644 --- a/src/app_cloud.cpp +++ b/src/app_cloud.cpp @@ -22,24 +22,18 @@ void App::cloud_upload() { auto upload_thread = [this] { BT_SetTerminate(); + if (Canvas::I->m_unsaved) { Canvas::I->project_save_thread(doc_path); } - async_start(); auto pb = show_progress("Uploading"); - async_redraw(); - async_end(); upload(doc_path, doc_filename, [this,pb](float p){ - async_start(); pb->m_progress->SetWidthP(p * 100.f); - async_redraw(); - async_end(); }); - async_start(); pb->destroy(); auto msgbox = new NodeMessageBox(); msgbox->m_manager = &layout; @@ -48,8 +42,6 @@ void App::cloud_upload() msgbox->m_message->set_text("This document has been succesfully uploaded."); layout[main_id]->add_child(msgbox); layout[main_id]->update(); - async_redraw(); - async_end(); }; auto m = layout[main_id]->add_child(); @@ -59,14 +51,10 @@ void App::cloud_upload() m->btn_cancel->m_text->set_text("No"); m->btn_ok->on_click = [this, m, upload_thread](Node*) { std::thread(upload_thread).detach(); - async_start(); m->destroy(); - async_end(); }; m->btn_cancel->on_click = [this, m, upload_thread](Node*) { - async_start(); m->destroy(); - async_end(); }; } @@ -76,16 +64,14 @@ void App::cloud_upload_all() { std::thread([this] { BT_SetTerminate(); + auto names = Asset::list_files(data_path, ".*\\.ppi"); gl_state gl; std::shared_ptr pb; if (layout.m_loaded) { - async_start(); pb = show_progress("Export Pano Image"); - async_redraw(); - async_end(); } int progress = 0; @@ -102,21 +88,13 @@ void App::cloud_upload_all() if (layout.m_loaded) { - async_start(); pb->m_progress->SetWidthP(p); - gl.save(); - async_redraw(); - gl.restore(); - async_end(); } } if (layout.m_loaded) { - async_start(); pb->destroy(); - async_redraw(); - async_end(); } }).detach(); } @@ -143,38 +121,28 @@ void App::cloud_browse() dialog->destroy(); std::thread([this, dialog] { BT_SetTerminate(); - async_start(); + auto* m = layout[main_id]->add_child(); m->m_title->set_text("Downloading"); m->m_message->set_text("Download in progress"); - async_redraw(); - async_end(); std::string url = "https://panopainter.com/cloud/cloud-dwl.php?file=" + dialog->selected_file; download(url, dialog->selected_path, [this,m](float p){ static char progress[256]; sprintf(progress, "Download in progress %.2f%%", p * 100.f); - async_start(); m->m_message->set_text(progress); - async_redraw(); - async_end(); }); - async_start(); canvas->reset_camera(); layers->clear(); - async_end(); canvas->m_canvas->project_open_thread(dialog->selected_path); - async_start(); doc_name = dialog->selected_name; title_update(); for (auto& l : canvas->m_canvas->m_layers) layers->add_layer(l->m_name.c_str(), false); ActionManager::clear(); m->destroy(); - async_redraw(); - async_end(); }).detach(); }; } diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 85d4e69..9ea389c 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -1099,16 +1099,19 @@ void App::brush_update() { // brushes->select_brush(canvas->m_brush->id); // stroke->set_params(canvas->m_brush); - stroke->update_controls(); - quick->m_slider_flow->set_value(stroke->m_tip_flow->get_value()); - quick->m_slider_size->set_value(stroke->m_tip_size->get_value()); - *quick->m_button_brush_current_preview->m_brush = *Canvas::I->m_current_brush; - quick->m_button_brush_current_preview->draw_stroke(); - quick->m_button_color_current_inner->m_color = Canvas::I->m_current_brush->m_tip_color; - if (floating_picker) - floating_picker->set_color(Canvas::I->m_current_brush->m_tip_color); - if (floating_color) - floating_color->set_color(Canvas::I->m_current_brush->m_tip_color); + render_task_async([this] + { + stroke->update_controls(); + quick->m_slider_flow->set_value(stroke->m_tip_flow->get_value()); + quick->m_slider_size->set_value(stroke->m_tip_size->get_value()); + *quick->m_button_brush_current_preview->m_brush = *Canvas::I->m_current_brush; + quick->m_button_brush_current_preview->draw_stroke(); + quick->m_button_color_current_inner->m_color = Canvas::I->m_current_brush->m_tip_color; + if (floating_picker) + floating_picker->set_color(Canvas::I->m_current_brush->m_tip_color); + if (floating_color) + floating_color->set_color(Canvas::I->m_current_brush->m_tip_color); + }); } void App::init_menu_layer() diff --git a/src/canvas.cpp b/src/canvas.cpp index ad255ca..a28ae70 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -179,6 +179,8 @@ void Canvas::stroke_cancel() } void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz) { + assert(App::I.is_render_thread()); + gl_state gl; gl.save(); @@ -321,6 +323,8 @@ std::array, 6> Canvas::stroke_draw_project(std::array& P) { + assert(App::I.is_render_thread()); + if (!ShaderManager::ext_framebuffer_fetch) { glActiveTexture(GL_TEXTURE1); @@ -454,6 +458,8 @@ std::vector Canvas::stroke_draw_compute(Stroke& stroke) con void Canvas::stroke_draw() { + assert(App::I.is_render_thread()); + if (!(m_current_stroke && m_current_stroke->has_sample())) { //stroke_draw_mix({ 0,0 }, { m_mixer.getWidth(), m_mixer.getHeight() }); @@ -690,6 +696,8 @@ glm::vec3 Canvas::point_trace(glm::vec2 loc) } void Canvas::stroke_commit() { + assert(App::I.is_render_thread()); + if (!m_dirty || m_layers.empty()) return; @@ -866,8 +874,8 @@ void Canvas::stroke_commit() void Canvas::draw_merge(std::array faces /*= SIXPLETTE(false)*/) { - gl_state gl; - gl.save(); + assert(App::I.is_render_thread()); + glViewport(0, 0, m_width, m_height); auto ortho = glm::ortho(-0.5f, 0.5f, -0.5f, 0.5f, -1.f, 1.f); const auto& b = m_current_stroke->m_brush; @@ -1112,8 +1120,6 @@ void Canvas::draw_merge(std::array faces /*= SIXPLETTE(false)*/) m_layers_merge.m_rtt[plane_index].unbindFramebuffer(); } - - gl.restore(); } void Canvas::stroke_update(glm::vec3 point, float pressure) @@ -1124,6 +1130,8 @@ void Canvas::stroke_update(glm::vec3 point, float pressure) } void Canvas::stroke_start(glm::vec3 point, float pressure) { + assert(App::I.is_render_thread()); + // need to commit this now before starting a new stroke if (m_current_stroke && m_commit_delayed) { @@ -1221,93 +1229,61 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index { m_dirty = false; - // save viewport and clear color states - GLint vp[4]; - GLfloat cc[4]; - glGetIntegerv(GL_VIEWPORT, vp); - glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); - GLboolean blend = glIsEnabled(GL_BLEND); - - // allocate action to add to history - auto action = new ActionStroke; - - // prepare common states - glViewport(0, 0, m_width, m_height); - glDisable(GL_BLEND); - - for (int i = 0; i < 6; i++) + App::I.render_task([&] { - if (!m_layers[source_idx]->m_dirty_face[i]) - continue; // no stroke on this face, skip it + // prepare common states + glViewport(0, 0, m_width, m_height); + glDisable(GL_BLEND); - m_layers[dest_idx]->m_rtt[i].bindFramebuffer(); - -/* - // save image before commit - glm::vec2 box_sz = m_dirty_box[i].zw() - m_dirty_box[i].xy(); - action->m_image[i] = std::make_unique(box_sz.x * box_sz.y * 4); - glReadPixels(m_dirty_box[i].x, m_dirty_box[i].y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, action->m_image[i].get()); - - action->m_box[i] = m_dirty_box[i]; - action->m_old_box[i] = m_layers[m_current_layer_idx]->m_dirty_box[i]; - action->m_old_dirty[i] = m_layers[m_current_layer_idx]->m_dirty_face[i]; -*/ - - auto& lbox = m_layers[dest_idx]->m_dirty_box[i]; - lbox = glm::vec4( - glm::min(xy(m_layers[source_idx]->m_dirty_box[i]), xy(lbox)), - glm::max(zw(m_layers[source_idx]->m_dirty_box[i]), zw(lbox)) - ); - m_layers[dest_idx]->m_dirty_face[i] = true; - - // copy to tmp2 for layer blending - glActiveTexture(GL_TEXTURE0); - m_tex2[i].bind(); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height); - m_tex2[i].unbind(); - - m_sampler.bind(0); - m_sampler_bg.bind(1); + for (int i = 0; i < 6; i++) { - ShaderManager::use(kShader::CompDraw); - ShaderManager::u_int(kShaderUniform::Tex, 0); // dest - ShaderManager::u_int(kShaderUniform::TexStroke, 1); // source - ShaderManager::u_vec2(kShaderUniform::Resolution, m_size); - ShaderManager::u_float(kShaderUniform::PatternAlpha, 0); - ShaderManager::u_float(kShaderUniform::Alpha, m_layers[source_idx]->m_opacity); - ShaderManager::u_int(kShaderUniform::Lock, false); - ShaderManager::u_int(kShaderUniform::UseFragcoord, false); - ShaderManager::u_int(kShaderUniform::BlendMode, m_layers[source_idx]->m_blend_mode); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - ShaderManager::u_int(kShaderUniform::UseDual, false); - ShaderManager::u_int(kShaderUniform::UsePattern, false); + if (!m_layers[source_idx]->m_dirty_face[i]) + continue; // no stroke on this face, skip it + m_layers[dest_idx]->m_rtt[i].bindFramebuffer(); + + auto& lbox = m_layers[dest_idx]->m_dirty_box[i]; + lbox = glm::vec4( + glm::min(xy(m_layers[source_idx]->m_dirty_box[i]), xy(lbox)), + glm::max(zw(m_layers[source_idx]->m_dirty_box[i]), zw(lbox)) + ); + m_layers[dest_idx]->m_dirty_face[i] = true; + + // copy to tmp2 for layer blending glActiveTexture(GL_TEXTURE0); m_tex2[i].bind(); - glActiveTexture(GL_TEXTURE1); - m_layers[source_idx]->m_rtt[i].bindTexture(); - m_plane.draw_fill(); - m_layers[source_idx]->m_rtt[i].unbindTexture(); - glActiveTexture(GL_TEXTURE0); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height); m_tex2[i].unbind(); + + m_sampler.bind(0); + m_sampler_bg.bind(1); + { + ShaderManager::use(kShader::CompDraw); + ShaderManager::u_int(kShaderUniform::Tex, 0); // dest + ShaderManager::u_int(kShaderUniform::TexStroke, 1); // source + ShaderManager::u_vec2(kShaderUniform::Resolution, m_size); + ShaderManager::u_float(kShaderUniform::PatternAlpha, 0); + ShaderManager::u_float(kShaderUniform::Alpha, m_layers[source_idx]->m_opacity); + ShaderManager::u_int(kShaderUniform::Lock, false); + ShaderManager::u_int(kShaderUniform::UseFragcoord, false); + ShaderManager::u_int(kShaderUniform::BlendMode, m_layers[source_idx]->m_blend_mode); + ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + ShaderManager::u_int(kShaderUniform::UseDual, false); + ShaderManager::u_int(kShaderUniform::UsePattern, false); + + glActiveTexture(GL_TEXTURE0); + m_tex2[i].bind(); + glActiveTexture(GL_TEXTURE1); + m_layers[source_idx]->m_rtt[i].bindTexture(); + m_plane.draw_fill(); + m_layers[source_idx]->m_rtt[i].unbindTexture(); + glActiveTexture(GL_TEXTURE0); + m_tex2[i].unbind(); + } + + m_layers[dest_idx]->m_rtt[i].unbindFramebuffer(); } - - m_layers[dest_idx]->m_rtt[i].unbindFramebuffer(); - } - - // restore viewport and clear color states - blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND); - glViewport(vp[0], vp[1], vp[2], vp[3]); - glClearColor(cc[0], cc[1], cc[2], cc[3]); - glActiveTexture(GL_TEXTURE0); - -/* - // save history - action->m_layer_idx = m_current_layer_idx; - action->m_canvas = this; - action->m_stroke = std::move(m_current_stroke); - ActionManager::add(action); -*/ + }); } void Canvas::flood_fill(int layer, int plane, std::vector pos, FloodData& plane_data, @@ -1611,26 +1587,25 @@ void Canvas::clear_context() void Canvas::import_equirectangular(std::string file_path, std::shared_ptr layer /*= nullptr*/) { - std::thread t(&Canvas::import_equirectangular_thread, this, file_path, layer); - t.detach(); + if (App::I.check_license()) + { + std::thread t([=] { + BT_SetTerminate(); + import_equirectangular_thread(file_path, layer); + }); + t.detach(); + } } void Canvas::import_equirectangular_thread(std::string file_path, std::shared_ptr layer /*= nullptr*/) { - BT_SetTerminate(); - Image img; if (!img.load_file(file_path)) return; - App::I.async_start(); - if (!layer) layer = m_layers[m_current_layer_idx]; - gl_state gl; - gl.save(); - auto a = new ActionImportEquirect; a->m_layer = layer; a->m_snap = std::make_shared(layer->snapshot()); @@ -1642,14 +1617,15 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt if (img.width == img.height / 6) { Texture2D tex; - static GLint indices[] = { 5, 0, 4, 1, 2, 3 }; - static GLint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA }; - static GLint iformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 }; + static const GLint indices[] = { 5, 0, 4, 1, 2, 3 }; + static const GLint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA }; + static const GLint iformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 }; tex.create(img.width, img.width, iformats[img.comp - 1], formats[img.comp - 1]); int stride = img.width * img.width * img.comp; Plane plane; plane.create<1>(2, 2); draw_objects([&](const glm::mat4& camera, const glm::mat4& proj, int i) { + glDisable(GL_DEPTH_TEST); tex.update(img.m_data.get() + indices[i] * stride); m_sampler.bind(0); glActiveTexture(GL_TEXTURE0); @@ -1661,15 +1637,16 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt tex.unbind(); m_sampler.unbind(); }); + plane.destroy(); } else { Texture2D tex; tex.load_file(file_path); Sphere sphere; - glDisable(GL_DEPTH_TEST); sphere.create<64, 64>(2.f); draw_objects([&](const glm::mat4& camera, const glm::mat4& proj, int i) { + glDisable(GL_DEPTH_TEST); m_sampler.bind(0); glActiveTexture(GL_TEXTURE0); tex.bind(); @@ -1681,15 +1658,13 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt tex.unbind(); m_sampler.unbind(); }); + sphere.destroy(); } for (int i = 0; i < 6; i++) { layer->m_dirty_box[i] = glm::vec4(0, 0, m_width, m_height); layer->m_dirty_face[i] = true; } - App::I.async_update(); - gl.restore(); - App::I.async_end(); } void Canvas::export_equirectangular(std::string file_path, std::function on_complete) @@ -1708,10 +1683,6 @@ void Canvas::export_equirectangular(std::string file_path, std::function void Canvas::export_equirectangular_thread(std::string file_path) { - gl_state gl; - - App::I.async_start(); - std::shared_ptr pb; if (App::I.layout.m_loaded) { @@ -1723,28 +1694,12 @@ void Canvas::export_equirectangular_thread(std::string file_path) pb->m_progress->SetWidthP(0); pb->m_title->set_text("Export Pano Image"); App::I.layout[App::I.main_id]->add_child(pb); - App::I.async_update(); } - // save viewport and clear color states - GLint vp[4]; - GLfloat cc[4]; - glGetIntegerv(GL_VIEWPORT, vp); - glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); - GLboolean blend = glIsEnabled(GL_BLEND); - - // prepare common states - glViewport(0, 0, m_width, m_height); - glEnable(GL_BLEND); - RTT m_latlong; m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense GLuint cube_id; - glGenTextures(1, &cube_id); - glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); - for (GLuint i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); static int faces[]{ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, // front GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // right @@ -1753,6 +1708,17 @@ void Canvas::export_equirectangular_thread(std::string file_path) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // top GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // bottom }; + + App::I.render_task([&] + { + glGenTextures(1, &cube_id); + glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); + for (GLuint i = 0; i < 6; i++) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, + m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + } + }); int progress = 0; int total = 6 + 2; @@ -1762,77 +1728,80 @@ void Canvas::export_equirectangular_thread(std::string file_path) for (int i = 0; i < 6; i++) { - // prepare common states - glViewport(0, 0, m_width, m_height); - glDisable(GL_BLEND); - - ShaderManager::use(kShader::TextureBlend); - ShaderManager::u_int(kShaderUniform::Tex, 0); - ShaderManager::u_int(kShaderUniform::TexA, 1); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - - m_tmp[i].bindFramebuffer(); - // clear transparent not to mess with blending modes - m_tmp[i].clear({ 1, 1, 1, 0 }); - - if (!ShaderManager::ext_framebuffer_fetch) + App::I.render_task([&] { - ShaderManager::u_int(kShaderUniform::TexBG, 2); - glActiveTexture(GL_TEXTURE2); - face.bind(); - m_sampler_bg.bind(2); - } - m_sampler_bg.bind(0); // nearest - m_sampler_mask.bind(1); // linear - for (int layer_index = 0; layer_index < m_layers.size(); layer_index++) - { - if (!m_layers[layer_index]->m_visible || - m_layers[layer_index]->m_opacity == 0.f || - !m_layers[layer_index]->m_dirty_face[i]) - continue; + // prepare common states + glViewport(0, 0, m_width, m_height); + glDisable(GL_BLEND); + + ShaderManager::use(kShader::TextureBlend); + ShaderManager::u_int(kShaderUniform::Tex, 0); + ShaderManager::u_int(kShaderUniform::TexA, 1); + ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + + m_tmp[i].bindFramebuffer(); + // clear transparent not to mess with blending modes + m_tmp[i].clear({ 1, 1, 1, 0 }); + + if (!ShaderManager::ext_framebuffer_fetch) + { + ShaderManager::u_int(kShaderUniform::TexBG, 2); + glActiveTexture(GL_TEXTURE2); + face.bind(); + m_sampler_bg.bind(2); + } + m_sampler_bg.bind(0); // nearest + m_sampler_mask.bind(1); // linear + for (int layer_index = 0; layer_index < m_layers.size(); layer_index++) + { + if (!m_layers[layer_index]->m_visible || + m_layers[layer_index]->m_opacity == 0.f || + !m_layers[layer_index]->m_dirty_face[i]) + continue; + if (!ShaderManager::ext_framebuffer_fetch) + { + glActiveTexture(GL_TEXTURE2); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height); + } + ShaderManager::u_int(kShaderUniform::BlendMode, m_layers[layer_index]->m_blend_mode); + ShaderManager::u_float(kShaderUniform::Alpha, m_layers[layer_index]->m_opacity); + glActiveTexture(GL_TEXTURE0); + m_layers[layer_index]->m_rtt[i].bindTexture(); + glActiveTexture(GL_TEXTURE1); + m_layers[layer_index]->m_rtt[i].bindTexture(); + m_plane.draw_fill(); + m_layers[layer_index]->m_rtt[i].unbindTexture(); + glActiveTexture(GL_TEXTURE0); + m_layers[layer_index]->m_rtt[i].unbindTexture(); + } + if (!ShaderManager::ext_framebuffer_fetch) { glActiveTexture(GL_TEXTURE2); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height); + face.unbind(); } - ShaderManager::u_int(kShaderUniform::BlendMode, m_layers[layer_index]->m_blend_mode); - ShaderManager::u_float(kShaderUniform::Alpha, m_layers[layer_index]->m_opacity); + + // now blend with the background + glEnable(GL_BLEND); + ShaderManager::use(kShader::Texture); + ShaderManager::u_int(kShaderUniform::Tex, 0); + ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + m_sampler_mask.bind(0); // linear glActiveTexture(GL_TEXTURE0); - m_layers[layer_index]->m_rtt[i].bindTexture(); - glActiveTexture(GL_TEXTURE1); - m_layers[layer_index]->m_rtt[i].bindTexture(); + face.bind(); + // copy the framebuffer before clearing to white + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height); + m_tmp[i].clear({ 1, 1, 1, 0 }); m_plane.draw_fill(); - m_layers[layer_index]->m_rtt[i].unbindTexture(); - glActiveTexture(GL_TEXTURE0); - m_layers[layer_index]->m_rtt[i].unbindTexture(); - } - - if (!ShaderManager::ext_framebuffer_fetch) - { - glActiveTexture(GL_TEXTURE2); face.unbind(); - } - // now blend with the background - glEnable(GL_BLEND); - ShaderManager::use(kShader::Texture); - ShaderManager::u_int(kShaderUniform::Tex, 0); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - m_sampler_mask.bind(0); // linear - glActiveTexture(GL_TEXTURE0); - face.bind(); - // copy the framebuffer before clearing to white - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height); - m_tmp[i].clear({ 1, 1, 1, 0 }); - m_plane.draw_fill(); - face.unbind(); + // copy result to cubemap + glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); + glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - // copy result to cubemap - glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); - glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - - m_tmp[i].unbindFramebuffer(); + m_tmp[i].unbindFramebuffer(); + }); progress++; float p = (float)progress / total * 100.f; @@ -1841,9 +1810,6 @@ void Canvas::export_equirectangular_thread(std::string file_path) if (App::I.layout.m_loaded) { pb->m_progress->SetWidthP(p); - gl.save(); - App::I.async_update(); - gl.restore(); } } @@ -1859,94 +1825,79 @@ void Canvas::export_equirectangular_thread(std::string file_path) // int ret = stbi_write_png(name, m_tmp[i].getWidth(), m_tmp[i].getHeight(), 4, data.get(), m_tmp[i].stride()); //} - glDisable(GL_BLEND); - glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight()); - glActiveTexture(GL_TEXTURE0); - m_latlong.bindFramebuffer(); - ShaderManager::use(kShader::Equirect); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - ShaderManager::u_int(kShaderUniform::Tex, 0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); - m_sampler_mask.bind(0); - m_plane.draw_fill(); - m_sampler_mask.unbind(); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - m_latlong.unbindFramebuffer(); + App::I.render_task([&] { - auto latlong_data = std::make_unique(m_latlong.bytes()); - m_latlong.readTextureData(latlong_data.get()); + glDisable(GL_BLEND); + glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight()); + glActiveTexture(GL_TEXTURE0); + m_latlong.bindFramebuffer(); + ShaderManager::use(kShader::Equirect); + ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + ShaderManager::u_int(kShaderUniform::Tex, 0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); + m_sampler_mask.bind(0); + m_plane.draw_fill(); + m_sampler_mask.unbind(); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + m_latlong.unbindFramebuffer(); + }); - { - progress++; - float p = (float)progress / total * 100.f; - LOG("progress: %f", p); + auto latlong_data = std::make_unique(m_latlong.bytes()); + m_latlong.readTextureData(latlong_data.get()); - if (App::I.layout.m_loaded) - { - pb->m_progress->SetWidthP(p); - gl.save(); - App::I.async_update(); - gl.restore(); - } - } + progress++; + LOG("progress: %f", (float)progress / total * 100.f); - LOG("writing %s", file_path.c_str()); - if (file_path.substr(file_path.size() - 4) == ".jpg") - { - stbi_write_jpg(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 100); - inject_xmp(file_path); - } - else if (file_path.substr(file_path.size() - 4) == ".png") - { - stbi_write_png(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 0); - } - - { - progress++; - float p = (float)progress / total * 100.f; - LOG("progress: %f", p); - - if (App::I.layout.m_loaded) - { - pb->m_progress->SetWidthP(p); - gl.save(); - App::I.async_update(); - gl.restore(); - } - } - - //int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride()); -#ifdef __IOS__ - [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ - NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:file_path.c_str()]]; - PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url]; - changeRequest.creationDate = [NSDate date]; - } completionHandler:^(BOOL success, NSError *error) { - if (success) { - NSLog(@"successfully saved"); - } - else { - NSLog(@"error saving to photos: %@", error); - } - }]; -#endif + if (App::I.layout.m_loaded) + { + pb->m_progress->SetWidthP((float)progress / total * 100.f); } - glDeleteTextures(1, &cube_id); - m_latlong.destroy(); + LOG("writing %s", file_path.c_str()); + if (file_path.substr(file_path.size() - 4) == ".jpg") + { + stbi_write_jpg(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 100); + inject_xmp(file_path); + } + else if (file_path.substr(file_path.size() - 4) == ".png") + { + stbi_write_png(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 0); + } - // restore viewport and clear color states - blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND); - glViewport(vp[0], vp[1], vp[2], vp[3]); - glClearColor(cc[0], cc[1], cc[2], cc[3]); - glActiveTexture(GL_TEXTURE0); + progress++; + LOG("progress: %f", (float)progress / total * 100.f); + + if (App::I.layout.m_loaded) + { + pb->m_progress->SetWidthP((float)progress / total * 100.f); + } + + //int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride()); +#ifdef __IOS__ + [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ + NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:file_path.c_str()]]; + PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url]; + changeRequest.creationDate = [NSDate date]; + } completionHandler:^(BOOL success, NSError *error) { + if (success) { + NSLog(@"successfully saved"); + } + else { + NSLog(@"error saving to photos: %@", error); + } + }]; +#endif + + App::I.render_task_async([id=cube_id] + { + glDeleteTextures(1, &id); + }); + m_latlong.destroy(); if (App::I.layout.m_loaded) { pb->destroy(); - App::I.async_update(); } - App::I.async_end(); } void Canvas::inject_xmp(std::string jpg_path) @@ -2002,7 +1953,6 @@ void Canvas::export_depth(std::string file_name, std::function on_comple if (App::I.check_license()) { std::thread t([=] { - BT_SetTerminate(); export_depth_thread(file_name); if (on_complete) on_complete(); @@ -2013,69 +1963,23 @@ void Canvas::export_depth(std::string file_name, std::function on_comple void Canvas::export_depth_thread(std::string file_name) { - App::I.async_start(); - gl_state gl; - gl.save(); - - draw_merge(); - - glEnable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - RTT rtt; rtt.create(1024, 1024); - rtt.bindFramebuffer(); - rtt.clear({ 0, 0, 0, 1 }); - glViewport(0, 0, rtt.getWidth(), rtt.getHeight()); glm::mat4 proj = glm::perspective(glm::radians(m_cam_fov), (float)rtt.getWidth() / (float)rtt.getHeight(), 0.1f, 100.f); glm::mat4 camera = m_cam_rot; - for (int plane_index = 0; plane_index < 6; plane_index++) + App::I.render_task([&] { - auto plane_mvp_z = proj * camera * - m_plane_transform[plane_index] * - glm::translate(glm::vec3(0, 0, -1)) * - glm::scale(glm::vec3(2)); + draw_merge(); - m_sampler.bind(0); - m_sampler_linear.bind(1); - ShaderManager::use(kShader::TextureAlphaSep); - ShaderManager::u_int(kShaderUniform::Tex, 0); - ShaderManager::u_int(kShaderUniform::TexA, 1); - ShaderManager::u_float(kShaderUniform::Alpha, 1.f); - ShaderManager::u_int(kShaderUniform::Highlight, false); - ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); - - glActiveTexture(GL_TEXTURE0); - m_layers_merge.m_rtt[plane_index].bindTexture(); - glActiveTexture(GL_TEXTURE1); - m_layers_merge.m_rtt[plane_index].bindTexture(); - - m_plane.draw_fill(); - - glActiveTexture(GL_TEXTURE1); - m_layers_merge.m_rtt[plane_index].unbindTexture(); - glActiveTexture(GL_TEXTURE0); - m_layers_merge.m_rtt[plane_index].unbindTexture(); - } - - uint8_t* rgba_data = rtt.readTextureData(); - stbi_flip_vertically_on_write(true); - std::string path_rgba = App::I.work_path + "/" + file_name + ".png"; - stbi_write_jpg(path_rgba.c_str(), rtt.getWidth(), rtt.getHeight(), 4, rgba_data, 100); - delete rgba_data; - - rtt.clear({ 0, 0, 0, 1 }); - for (int layer_index = 0; layer_index < m_layers.size(); layer_index++) - { + rtt.bindFramebuffer(); + rtt.clear({ 0, 0, 0, 1 }); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glViewport(0, 0, rtt.getWidth(), rtt.getHeight()); for (int plane_index = 0; plane_index < 6; plane_index++) { - if ((!m_layers[layer_index]->m_visible || - m_layers[layer_index]->m_opacity == .0f || - !m_layers[layer_index]->m_dirty_face[plane_index])) - continue; - auto plane_mvp_z = proj * camera * m_plane_transform[plane_index] * glm::translate(glm::vec3(0, 0, -1)) * @@ -2083,17 +1987,70 @@ void Canvas::export_depth_thread(std::string file_name) m_sampler.bind(0); m_sampler_linear.bind(1); - ShaderManager::use(kShader::TextureColorize); + ShaderManager::use(kShader::TextureAlphaSep); ShaderManager::u_int(kShaderUniform::Tex, 0); - ShaderManager::u_vec4(kShaderUniform::Col, { glm::vec3((float)(layer_index + 1) / (float)(m_layers.size() + 1)), 1.f }); + ShaderManager::u_int(kShaderUniform::TexA, 1); + ShaderManager::u_float(kShaderUniform::Alpha, 1.f); + ShaderManager::u_int(kShaderUniform::Highlight, false); ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); glActiveTexture(GL_TEXTURE0); - m_layers[layer_index]->m_rtt[plane_index].bindTexture(); + m_layers_merge.m_rtt[plane_index].bindTexture(); + glActiveTexture(GL_TEXTURE1); + m_layers_merge.m_rtt[plane_index].bindTexture(); + m_plane.draw_fill(); - m_layers[layer_index]->m_rtt[plane_index].unbindTexture(); + + glActiveTexture(GL_TEXTURE1); + m_layers_merge.m_rtt[plane_index].unbindTexture(); + glActiveTexture(GL_TEXTURE0); + m_layers_merge.m_rtt[plane_index].unbindTexture(); } - } + rtt.unbindFramebuffer(); + }); + + uint8_t* rgba_data = rtt.readTextureData(); + stbi_flip_vertically_on_write(true); + std::string path_rgba = App::I.work_path + "/" + file_name + ".png"; + stbi_write_jpg(path_rgba.c_str(), rtt.getWidth(), rtt.getHeight(), 4, rgba_data, 100); + delete rgba_data; + + App::I.render_task([&] + { + rtt.bindFramebuffer(); + rtt.clear({ 0, 0, 0, 1 }); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glViewport(0, 0, rtt.getWidth(), rtt.getHeight()); + for (int layer_index = 0; layer_index < m_layers.size(); layer_index++) + { + for (int plane_index = 0; plane_index < 6; plane_index++) + { + if ((!m_layers[layer_index]->m_visible || + m_layers[layer_index]->m_opacity == .0f || + !m_layers[layer_index]->m_dirty_face[plane_index])) + continue; + + auto plane_mvp_z = proj * camera * + m_plane_transform[plane_index] * + glm::translate(glm::vec3(0, 0, -1)) * + glm::scale(glm::vec3(2)); + + m_sampler.bind(0); + m_sampler_linear.bind(1); + ShaderManager::use(kShader::TextureColorize); + ShaderManager::u_int(kShaderUniform::Tex, 0); + ShaderManager::u_vec4(kShaderUniform::Col, { glm::vec3((float)(layer_index + 1) / (float)(m_layers.size() + 1)), 1.f }); + ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); + + glActiveTexture(GL_TEXTURE0); + m_layers[layer_index]->m_rtt[plane_index].bindTexture(); + m_plane.draw_fill(); + m_layers[layer_index]->m_rtt[plane_index].unbindTexture(); + } + } + rtt.unbindFramebuffer(); + }); uint8_t* depth_data = rtt.readTextureData(); std::string path_depth = App::I.work_path + "/" + file_name + "_depth.png"; @@ -2101,11 +2058,7 @@ void Canvas::export_depth_thread(std::string file_name) delete depth_data; stbi_flip_vertically_on_write(false); - rtt.unbindFramebuffer(); rtt.destroy(); - - gl.restore(); - App::I.async_end(); } void Canvas::export_layers(std::string file_name, std::function on_complete) @@ -2124,16 +2077,6 @@ void Canvas::export_layers(std::string file_name, std::function on_compl void Canvas::export_layers_thread(std::string file_name) { - App::I.async_start(); - - // save viewport and clear color states - GLint vp[4]; - GLfloat cc[4]; - glGetIntegerv(GL_VIEWPORT, vp); - glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); - GLboolean blend = glIsEnabled(GL_BLEND); - - gl_state gl; std::shared_ptr pb; if (App::I.layout.m_loaded) { @@ -2145,22 +2088,14 @@ void Canvas::export_layers_thread(std::string file_name) pb->m_progress->SetWidthP(0); pb->m_title->set_text("Export Pano Layers"); App::I.layout[App::I.main_id]->add_child(pb); - App::I.async_update(); } int progress = 0; int total = (int)(m_layers.size() + 1) * 6; - // prepare common states - glViewport(0, 0, m_width, m_height); - RTT m_latlong; m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense GLuint cube_id; - glGenTextures(1, &cube_id); - glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); - for (GLuint i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); int faces[]{ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, // front GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // right @@ -2169,49 +2104,59 @@ void Canvas::export_layers_thread(std::string file_name) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // top GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // bottom }; + App::I.render_task([&] + { + glGenTextures(1, &cube_id); + glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); + for (GLuint i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + }); int seq = 0; for (int layer_index = 0; layer_index < m_layers.size(); layer_index++) { - glViewport(0, 0, m_width, m_height); for (int i = 0; i < 6; i++) { - glEnable(GL_BLEND); - m_tmp[i].bindFramebuffer(); - - //if (seq == 0) - //{ - // m_tmp[i].clear({ 1, 1, 1, 1 }); - // ShaderManager::use(kShader::Checkerboard); - // ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - // m_plane.draw_fill(); - // glEnable(GL_BLEND); - //} - //else + App::I.render_task([&] { - m_tmp[i].clear({ 1, 1, 1, 0 }); - //glDisable(GL_BLEND); - } + glEnable(GL_BLEND); + glViewport(0, 0, m_width, m_height); + m_tmp[i].bindFramebuffer(); - glActiveTexture(GL_TEXTURE0); - ShaderManager::use(kShader::TextureAlpha); - ShaderManager::u_float(kShaderUniform::Alpha, 1); - ShaderManager::u_int(kShaderUniform::Highlight, false); - ShaderManager::u_int(kShaderUniform::Tex, 0); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - - m_sampler_mask.bind(0); - m_layers[layer_index]->m_rtt[i].bindTexture(); - m_plane.draw_fill(); - m_layers[layer_index]->m_rtt[i].unbindTexture(); - m_sampler_mask.unbind(); - - // copy result to cubemap - glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); - glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - - m_tmp[i].unbindFramebuffer(); + //if (seq == 0) + //{ + // m_tmp[i].clear({ 1, 1, 1, 1 }); + // ShaderManager::use(kShader::Checkerboard); + // ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + // m_plane.draw_fill(); + // glEnable(GL_BLEND); + //} + //else + { + m_tmp[i].clear({ 1, 1, 1, 0 }); + //glDisable(GL_BLEND); + } + + glActiveTexture(GL_TEXTURE0); + ShaderManager::use(kShader::TextureAlpha); + ShaderManager::u_float(kShaderUniform::Alpha, 1); + ShaderManager::u_int(kShaderUniform::Highlight, false); + ShaderManager::u_int(kShaderUniform::Tex, 0); + ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + + m_sampler_mask.bind(0); + m_layers[layer_index]->m_rtt[i].bindTexture(); + m_plane.draw_fill(); + m_layers[layer_index]->m_rtt[i].unbindTexture(); + m_sampler_mask.unbind(); + + // copy result to cubemap + glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); + glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + + m_tmp[i].unbindFramebuffer(); + }); progress++; float p = (float)progress / total * 100.f; @@ -2220,27 +2165,27 @@ void Canvas::export_layers_thread(std::string file_name) if (App::I.layout.m_loaded) { pb->m_progress->SetWidthP(p); - gl.save(); - App::I.async_update(); - gl.restore(); } } + App::I.render_task([&] + { + glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight()); + glActiveTexture(GL_TEXTURE0); + m_latlong.bindFramebuffer(); + m_latlong.clear({ 1, 1, 1, 0 }); + ShaderManager::use(kShader::Equirect); + ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + ShaderManager::u_int(kShaderUniform::Tex, 0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); + glDisable(GL_BLEND); + m_sampler_mask.bind(0); + m_plane.draw_fill(); + m_sampler_mask.unbind(); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + m_latlong.unbindFramebuffer(); + }); - glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight()); - glActiveTexture(GL_TEXTURE0); - m_latlong.bindFramebuffer(); - m_latlong.clear({ 1, 1, 1, 0 }); - ShaderManager::use(kShader::Equirect); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); - ShaderManager::u_int(kShaderUniform::Tex, 0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); - glDisable(GL_BLEND); - m_sampler_mask.bind(0); - m_plane.draw_fill(); - m_sampler_mask.unbind(); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - m_latlong.unbindFramebuffer(); { auto latlong_data = std::make_unique(m_latlong.bytes()); m_latlong.readTextureData(latlong_data.get()); @@ -2248,9 +2193,7 @@ void Canvas::export_layers_thread(std::string file_name) sprintf(name, "%s/%s-layer-%02d.png", App::I.work_path.c_str(), file_name.c_str(), seq); seq++; LOG("writing %s", name); - App::I.async_end(); int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride()); - App::I.async_start(); } progress++; @@ -2260,28 +2203,19 @@ void Canvas::export_layers_thread(std::string file_name) if (App::I.layout.m_loaded) { pb->m_progress->SetWidthP(p); - gl.save(); - App::I.async_update(); - gl.restore(); } } - glDeleteTextures(1, &cube_id); - m_latlong.destroy(); + App::I.render_task([&] + { + glDeleteTextures(1, &cube_id); + m_latlong.destroy(); + }); if (App::I.layout.m_loaded) { pb->destroy(); - App::I.async_update(); } - - // restore viewport and clear color states - blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND); - glViewport(vp[0], vp[1], vp[2], vp[3]); - glClearColor(cc[0], cc[1], cc[2], cc[3]); - glActiveTexture(GL_TEXTURE0); - - App::I.async_end(); } void Canvas::export_cubes() @@ -2401,8 +2335,6 @@ void Canvas::project_save(std::string file_path, std::function on_co bool Canvas::project_save_thread(std::string file_path) { - gl_state gl; - // already saved, nothing to do if (!m_unsaved && file_path == App::I.doc_path) { @@ -2453,7 +2385,6 @@ bool Canvas::project_save_thread(std::string file_path) fwrite(&ppi_header, sizeof(PPIHeader), 1, fp); // load thumbnail - App::I.async_start(); Image thumb = thumbnail_generate(ppi_header.thumb_header.width, ppi_header.thumb_header.height); auto pb = std::make_shared(); pb->m_manager = &App::I.layout; @@ -2463,8 +2394,6 @@ bool Canvas::project_save_thread(std::string file_path) pb->m_progress->SetWidthP(0); pb->m_title->set_text("Saving Pano Project"); App::I.layout[App::I.main_id]->add_child(pb); - App::I.async_update(); - App::I.async_end(); thumb.flip(); fwrite(thumb.data(), thumb.size(), 1, fp); @@ -2497,10 +2426,7 @@ bool Canvas::project_save_thread(std::string file_path) fwrite(&m_layers[i]->m_visible, sizeof(bool), 1, fp); } - App::I.async_start(); auto snap = m_layers[i]->snapshot(); - App::I.async_update(); - App::I.async_end(); for (int plane_index = 0; plane_index < 6; plane_index++) { int has_data = snap.m_dirty_face[plane_index] ? 1 : 0; @@ -2527,11 +2453,8 @@ bool Canvas::project_save_thread(std::string file_path) } progress++; float p = (float)progress / total * 100.f; - App::I.async_start(); pb->m_progress->SetWidthP(p); LOG("progress: %f", p); - App::I.async_update(); - App::I.async_end(); } } fclose(fp); @@ -2571,11 +2494,8 @@ bool Canvas::project_save_thread(std::string file_path) m_newdoc = false; } - App::I.async_start(); pb->destroy(); App::I.title_update(); - App::I.async_update(); - App::I.async_end(); return success; } @@ -2609,11 +2529,9 @@ bool Canvas::project_open_thread(std::string file_path) return false; } - gl_state gl; std::shared_ptr pb; if (App::I.layout.m_loaded) { - App::I.async_start(); pb = std::make_shared(); pb->m_manager = &App::I.layout; pb->init(); @@ -2622,10 +2540,6 @@ bool Canvas::project_open_thread(std::string file_path) pb->m_progress->SetWidthP(0); pb->m_title->set_text("Opening Pano Project"); App::I.layout[App::I.main_id]->add_child(pb); - gl.save(); - App::I.async_update(); - gl.restore(); - App::I.async_end(); } // skip thumbnail @@ -2648,13 +2562,11 @@ bool Canvas::project_open_thread(std::string file_path) int progress = 0; int total = n_layers * 6; - App::I.async_start(); for (auto& l : m_layers) l->destroy(); m_layers.clear(); //clear_all(); resize(m_width, m_height); - App::I.async_end(); std::vector> tmp_layers(n_layers); @@ -2713,20 +2625,12 @@ bool Canvas::project_open_thread(std::string file_path) if (App::I.layout.m_loaded) { - App::I.async_start(); pb->m_progress->SetWidthP(p); - gl.save(); - App::I.async_update(); - gl.restore(); - App::I.async_end(); } } - App::I.async_start(); layer->create(m_width, m_height, name.c_str()); - layer->clear({ 0, 0, 0, 0 }); layer->restore(snap); - App::I.async_end(); } std::swap(tmp_layers, m_layers); @@ -2749,20 +2653,8 @@ bool Canvas::project_open_thread(std::string file_path) m_newdoc = false; if (App::I.layout.m_loaded) { - App::I.async_start(); pb->destroy(); - gl.save(); - draw_merge(); - App::I.async_update(); - gl.restore(); App::I.title_update(); - App::I.async_end(); - } - else - { - App::I.async_start(); - draw_merge(); - App::I.async_end(); } return true; } diff --git a/src/canvas_actions.cpp b/src/canvas_actions.cpp index 40023f9..fa2ec60 100644 --- a/src/canvas_actions.cpp +++ b/src/canvas_actions.cpp @@ -34,9 +34,12 @@ void ActionStroke::undo() glm::vec2 box_sz = zw(m_box[i]) - xy(m_box[i]); if (box_sz.x > 0 && box_sz.y > 0 && box_sz.x <= m_canvas->m_layers[m_layer_idx]->w && box_sz.y <= m_canvas->m_layers[m_layer_idx]->h) { - m_canvas->m_layers[m_layer_idx]->m_rtt[i].bindTexture(); - glTexSubImage2D(GL_TEXTURE_2D, 0, (int)m_box[i].x, (int)m_box[i].y, (int)box_sz.x, (int)box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, m_image[i].get()); - m_canvas->m_layers[m_layer_idx]->m_rtt[i].unbindTexture(); + App::I.render_task([&] + { + m_canvas->m_layers[m_layer_idx]->m_rtt[i].bindTexture(); + glTexSubImage2D(GL_TEXTURE_2D, 0, (int)m_box[i].x, (int)m_box[i].y, (int)box_sz.x, (int)box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, m_image[i].get()); + m_canvas->m_layers[m_layer_idx]->m_rtt[i].unbindTexture(); + }); } else { @@ -66,7 +69,6 @@ Action* ActionStroke::get_redo() if (!layer->m_dirty_face[i] && !m_image[i]) continue; // no stroke on this face, skip it - layer->m_rtt[i].bindFramebuffer(); auto box = clear_layer ? glm::ivec4(layer->m_dirty_box[i]) : m_box[i]; @@ -76,7 +78,12 @@ Action* ActionStroke::get_redo() if (box_sz.x > 0 && box_sz.y > 0 && box_sz.x <= layer->w && box_sz.y <= layer->h) { action->m_image[i] = std::make_unique(box_sz.x * box_sz.y * 4); - glReadPixels(box_or.x, box_or.y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, action->m_image[i].get()); + App::I.render_task([&] + { + layer->m_rtt[i].bindFramebuffer(); + glReadPixels(box_or.x, box_or.y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, action->m_image[i].get()); + layer->m_rtt[i].unbindFramebuffer(); + }); } else { @@ -86,8 +93,6 @@ Action* ActionStroke::get_redo() action->m_box[i] = box; action->m_old_box[i] = layer->m_dirty_box[i]; action->m_old_dirty[i] = layer->m_dirty_face[i]; - - layer->m_rtt[i].unbindFramebuffer(); } // save history action->m_layer_idx = m_layer_idx; diff --git a/src/canvas_modes.cpp b/src/canvas_modes.cpp index f7e33b4..6535b8f 100644 --- a/src/canvas_modes.cpp +++ b/src/canvas_modes.cpp @@ -135,7 +135,10 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) } else { - Canvas::I->stroke_start({ loc, 0 }, me->m_pressure); + App::I.render_task_async([loc, pr=me->m_pressure] + { + Canvas::I->stroke_start({ loc, 0 }, pr); + }); } m_dragging = true; node->mouse_capture(); @@ -144,7 +147,10 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) if (m_dragging && !m_picking) { node->mouse_release(); - Canvas::I->stroke_end(); + App::I.render_task_async([] + { + Canvas::I->stroke_end(); + }); } if (m_dragging && m_picking) { @@ -178,7 +184,12 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) break; case kEventType::MouseMove: if (m_dragging && !m_picking && !m_resizing) - Canvas::I->stroke_update({ loc, 0 }, me->m_pressure); + { + App::I.render_task_async([loc, pr=me->m_pressure] + { + Canvas::I->stroke_update({ loc, 0 }, pr); + }); + } if (m_dragging && m_picking) { glm::vec4 pix = Canvas::I->pick_get(loc); @@ -197,7 +208,10 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) case kEventType::MouseCancel: if (m_dragging) { - Canvas::I->stroke_cancel(); + App::I.render_task_async([] + { + Canvas::I->stroke_cancel(); + }); m_dragging = false; node->mouse_release(); } @@ -299,10 +313,13 @@ void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) node->mouse_release(); if (m_dragging) { - Canvas::I->stroke_start({ m_drag_start, 0 }, 1.f); - Canvas::I->stroke_update({ m_drag_pos, 0 }, 1.f); - Canvas::I->stroke_draw(); - Canvas::I->stroke_end(); + App::I.render_task_async([=] + { + Canvas::I->stroke_start({ m_drag_start, 0 }, 1.f); + Canvas::I->stroke_update({ m_drag_pos, 0 }, 1.f); + Canvas::I->stroke_draw(); + Canvas::I->stroke_end(); + }); } m_dragging = false; break; diff --git a/src/main.cpp b/src/main.cpp index a0dcdfc..34a721a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -811,7 +811,7 @@ void render_thread_main() async_lock(); while (!working_list.empty()) { - //LOG("render task %d", count); + LOG("render task %d", count); count++; working_list.front()(); working_list.pop_front(); @@ -1133,11 +1133,12 @@ int main(int argc, char** argv) if (App::I.redraw) { + App::I.update(frame_timer); render_task([frame_timer] { glBindFramebuffer(GL_FRAMEBUFFER, 0); App::I.clear(); - App::I.update(frame_timer); + App::I.draw(frame_timer); SwapBuffers(hDC); }); frame_timer = 0; @@ -1244,39 +1245,28 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) BT_SetTerminate(); break; case WM_CLOSE: - if (App::I.request_close()) - { - running = 0; - ui_render_cv.notify_all(); - if (ui_renderer.joinable()) - ui_renderer.join(); - if (hmd_renderer.joinable()) - hmd_renderer.join(); - App::I.terminate(); - PostQuitMessage(0); - render_running = false; - if (render_thread.joinable()) - render_thread.join(); - return 0; - } - else - { - return true; - } + { + std::lock_guard lock(task_mutex); + tasklist.emplace_back([=] { + if (App::I.request_close()) + { + destroy_window(); + } + }); + return 1; break; + } case WM_SIZE: { auto w = (float)LOWORD(lp); auto h = (float)HIWORD(lp); if (h != 0 && running == 1) { - App::I.render_task([=] + std::lock_guard lock(task_mutex); + tasklist.emplace_back([=] { App::I.resize(w, h); - App::I.clear(); App::I.redraw = true; - App::I.update(0.f); - SwapBuffers(hDC); }); } break; diff --git a/src/node.cpp b/src/node.cpp index e9bb2c4..194c488 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -42,21 +42,6 @@ void Node::app_redraw() App::I.redraw = true; } -void Node::async_start() -{ - App::I.async_start(); -} - -void Node::async_update() -{ - App::I.async_update(); -} - -void Node::async_end() -{ - App::I.async_end(); -} - void Node::watch(std::function observer) { bool cont = observer(this); diff --git a/src/node.h b/src/node.h index 30472a0..65b6745 100644 --- a/src/node.h +++ b/src/node.h @@ -266,9 +266,6 @@ public: const Node* init_template(const char* id); void tick(float dt); void app_redraw(); - void async_start(); - void async_update(); - void async_end(); void add_child(Node* n); void add_child(Node* n, int index); void add_child(std::shared_ptr n); diff --git a/src/node_dialog_browse.cpp b/src/node_dialog_browse.cpp index 30f8884..8dbeee9 100644 --- a/src/node_dialog_browse.cpp +++ b/src/node_dialog_browse.cpp @@ -80,7 +80,6 @@ void NodeDialogBrowse::init_controls() btn_path->on_click = [this](Node*){ App::I.pick_dir([this](std::string path){ LOG("change working path to %s", path.c_str()); - async_start(); App::I.work_path = path; #ifdef _WIN32 GetFullPathNameA(path.c_str(), sizeof(path_buffer), path_buffer, nullptr); @@ -91,8 +90,6 @@ void NodeDialogBrowse::init_controls() search_paths = {path}; clear_list(); init_list(); - async_update(); - async_end(); }); }; working_path = find("path"); diff --git a/src/node_dialog_cloud.cpp b/src/node_dialog_cloud.cpp index 7e4bbb6..9d55652 100644 --- a/src/node_dialog_cloud.cpp +++ b/src/node_dialog_cloud.cpp @@ -55,7 +55,6 @@ void NodeDialogCloud::load_thumbs_thread() std::string res; if (curl) { - async_start(); auto* align = container->add_child(); align->SetWidthP(100.f); align->SetHeightP(100.f); @@ -64,8 +63,6 @@ void NodeDialogCloud::load_thumbs_thread() auto* text = align->add_child(); text->set_font(kFont::Arial_30); text->set_text("Connecting to the server..."); - async_update(); - async_end(); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &res); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_handler); @@ -78,16 +75,11 @@ void NodeDialogCloud::load_thumbs_thread() if (err != CURLE_OK) { LOG("connection error: %d", err); - async_start(); text->set_text("Could not connect to the server"); - async_update(); - async_end(); return; } - async_start(); align->destroy(); - async_end(); LOG("CLOUD LIST: %s", res.c_str()); @@ -95,7 +87,6 @@ void NodeDialogCloud::load_thumbs_thread() std::vector nodes; // create slots with name - App::I.async_start(); for (const auto& n : names) { auto node = new NodeDialogCloudItem; @@ -117,8 +108,6 @@ void NodeDialogCloud::load_thumbs_thread() }; nodes.push_back(node); } - App::I.async_update(); - App::I.async_end(); // load the icons for (int i = 0; i < names.size(); i++) @@ -149,12 +138,9 @@ void NodeDialogCloud::load_thumbs_thread() thumb.create(width, height); thumb.copy_from((uint8_t*)rgb.data()); - App::I.async_start(); auto image_tex = node->find("thumb-tex"); image_tex->tex.destroy(); image_tex->tex.create(thumb); - App::I.async_update(); - App::I.async_end(); } curl_easy_cleanup(curl); } diff --git a/src/node_dialog_open.cpp b/src/node_dialog_open.cpp index cf5ef51..5316cec 100644 --- a/src/node_dialog_open.cpp +++ b/src/node_dialog_open.cpp @@ -200,7 +200,6 @@ void NodeDialogSave::init_controls() btn_path->on_click = [this](Node*){ App::I.pick_dir([this](std::string path){ LOG("change working path to %s", path.c_str()); - async_start(); App::I.work_path = path; #ifdef _WIN32 GetFullPathNameA(path.c_str(), sizeof(path_buffer), path_buffer, nullptr); @@ -208,8 +207,6 @@ void NodeDialogSave::init_controls() realpath(path.c_str(), path_buffer); #endif working_path->set_text_format("Working dir: %s", path_buffer); - async_update(); - async_end(); }); }; working_path = find("path"); @@ -264,7 +261,6 @@ void NodeDialogNewDoc::init_controls() btn_path->on_click = [this](Node*){ App::I.pick_dir([this](std::string path){ LOG("change working path to %s", path.c_str()); - async_start(); App::I.work_path = path; #ifdef _WIN32 GetFullPathNameA(path.c_str(), sizeof(path_buffer), path_buffer, nullptr); @@ -272,8 +268,6 @@ void NodeDialogNewDoc::init_controls() realpath(path.c_str(), path_buffer); #endif working_path->set_text_format("Working dir: %s", path_buffer); - async_update(); - async_end(); }); }; working_path = find("path"); diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp index e44ebf5..c3febbc 100644 --- a/src/node_panel_brush.cpp +++ b/src/node_panel_brush.cpp @@ -102,7 +102,6 @@ void NodePanelBrush::init() //auto po2 = img.resize_power2(); img.save(path_high); - async_start(); NodeButtonBrush* brush = new NodeButtonBrush; m_container->add_child(brush); brush->init(); @@ -114,8 +113,6 @@ void NodePanelBrush::init() brush->brush_name = name; brush->m_user_brush = true; brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1); - app_redraw(); - async_end(); save(); } }); diff --git a/src/node_panel_grid.cpp b/src/node_panel_grid.cpp index 50edddf..e51c6bd 100644 --- a/src/node_panel_grid.cpp +++ b/src/node_panel_grid.cpp @@ -78,7 +78,6 @@ void NodePanelGrid::init_controls() m_hm_load->on_click = [this](Node*) { App::I.pick_image([this](std::string path) { Image img; - async_start(); if (img.load_file(path)) { m_file_path = path; @@ -93,8 +92,6 @@ void NodePanelGrid::init_controls() m_groud_opacity->set_value(1.f); m_rt_dirty = true; } - async_update(); - async_end(); }); }; @@ -380,7 +377,6 @@ void NodePanelGrid::bake_uvs() pb->m_progress->SetWidthP(0); pb->m_title->set_text("Lightmap Rendering"); pb->btn_cancel->destroy(); - async_update(); if (m_rt_dirty) { @@ -462,7 +458,6 @@ void NodePanelGrid::bake_uvs() while (pb_value < fb.getHeight()) { pb->m_progress->SetWidthP((float)pb_value / (float)fb.getHeight() * 100.f); - async_update(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } worker.join(); diff --git a/src/node_panel_stroke.cpp b/src/node_panel_stroke.cpp index 51ba5ee..c37c2ee 100644 --- a/src/node_panel_stroke.cpp +++ b/src/node_panel_stroke.cpp @@ -42,11 +42,7 @@ bool NodePanelStroke::import_abr(const std::string& path) if (!str_iequals(ext, "abr") || !Asset::exist(path)) return false; - async_start(); auto pb = App::I.show_progress("Importing ABR"); - app_redraw(); - async_update(); - async_end(); abr.open(path); @@ -68,7 +64,6 @@ bool NodePanelStroke::import_abr(const std::string& path) auto thumb = padded.resize(64, 64); thumb.save(path_thumb); - async_start(); NodeButtonBrush* brush = new NodeButtonBrush; m_brush_popup->m_container->add_child(brush); brush->init(); @@ -83,9 +78,6 @@ bool NodePanelStroke::import_abr(const std::string& path) count++; float prog = (float)count / (float)tot; pb->m_progress->SetWidthP(prog * 100.f); - app_redraw(); - async_update(); - async_end(); }); m_brush_popup->save(); @@ -101,7 +93,6 @@ bool NodePanelStroke::import_abr(const std::string& path) auto thumb = patt.second->resize(64, 64); thumb.save(path_thumb); - async_start(); NodeButtonBrush* brush = new NodeButtonBrush; m_pattern_popup->m_container->add_child(brush); brush->init(); @@ -116,16 +107,12 @@ bool NodePanelStroke::import_abr(const std::string& path) count++; float prog = (float)count / (float)tot; pb->m_progress->SetWidthP(prog * 100.f); - app_redraw(); - async_update(); - async_end(); }); m_pattern_popup->save(); auto brushes = abr.compute_brushes(App::I.data_path); for (const auto& pr : brushes) { - async_start(); if (pr->valid()) { LOG("add preset %s", pr->m_name.c_str()); @@ -134,17 +121,10 @@ bool NodePanelStroke::import_abr(const std::string& path) count++; float prog = (float)count / (float)tot; pb->m_progress->SetWidthP(prog * 100.f); - app_redraw(); - async_update(); - async_end(); } - async_start(); App::I.presets->save(); pb->destroy(); - app_redraw(); - async_update(); - async_end(); //save(); return true; diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index 217fcd5..9939702 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -264,6 +264,7 @@ void NodeStrokePreview::draw_stroke_immediate() glm::mat4 ortho_proj = glm::ortho(0, size.x, 0, size.y, -1, 1); glViewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight()); m_rtt.bindFramebuffer(); + m_rtt.clear(); m_sampler_mipmap.bind(0); m_sampler_linear.bind(1); m_sampler_linear_repeat.bind(2); diff --git a/src/util.cpp b/src/util.cpp index dbb0651..e105e53 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -2,6 +2,7 @@ #include "log.h" #include "util.h" #include +#include "app.h" template<> std::vector poly_remove_duplicate(const std::vector& v, const float tollerance) @@ -714,3 +715,43 @@ void parallel_for(size_t nb_elements, std::function functor, boo if (use_threads) std::for_each(my_threads.begin(), my_threads.end(), std::mem_fn(&std::thread::join)); } + +void gl_state::save() +{ + assert(App::I.is_render_thread()); + blend = glIsEnabled(GL_BLEND); + depth_test = glIsEnabled(GL_DEPTH_TEST); + scissor_test = glIsEnabled(GL_SCISSOR_TEST); + glGetIntegerv(GL_VIEWPORT, vp); + glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); + glGetIntegerv(GL_CURRENT_PROGRAM, &program); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb); + glGetIntegerv(GL_ACTIVE_TEXTURE, &active_tex); + glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &cube); + for (int i = 0; i < 10; ++i) + { + glActiveTexture(GL_TEXTURE0 + i); + glGetIntegerv(GL_TEXTURE_BINDING_2D, tex + i); + glGetIntegerv(GL_SAMPLER_BINDING, sampler + i); + } +} + +void gl_state::restore() +{ + assert(App::I.is_render_thread()); + blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND); + depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST); + scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST); + glViewport(vp[0], vp[1], vp[2], vp[3]); + glClearColor(cc[0], cc[1], cc[2], cc[3]); + glBindFramebuffer(GL_FRAMEBUFFER, fb); + glUseProgram(program); + for (int i = 0; i < 10; ++i) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, tex[i]); + glBindSampler(i, sampler[i]); + } + glActiveTexture(active_tex); + glBindTexture(GL_TEXTURE_CUBE_MAP, cube); +} diff --git a/src/util.h b/src/util.h index f51b6a8..a6c8fc0 100644 --- a/src/util.h +++ b/src/util.h @@ -251,40 +251,6 @@ struct gl_state GLint fb; GLint active_tex; GLfloat line_width; - void save() - { - blend = glIsEnabled(GL_BLEND); - depth_test = glIsEnabled(GL_DEPTH_TEST); - scissor_test = glIsEnabled(GL_SCISSOR_TEST); - glGetIntegerv(GL_VIEWPORT, vp); - glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); - glGetIntegerv(GL_CURRENT_PROGRAM, &program); - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb); - glGetIntegerv(GL_ACTIVE_TEXTURE, &active_tex); - glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &cube); - for (int i = 0; i < 10; ++i) - { - glActiveTexture(GL_TEXTURE0 + i); - glGetIntegerv(GL_TEXTURE_BINDING_2D, tex + i); - glGetIntegerv(GL_SAMPLER_BINDING, sampler + i); - } - } - void restore() - { - blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND); - depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST); - scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST); - glViewport(vp[0], vp[1], vp[2], vp[3]); - glClearColor(cc[0], cc[1], cc[2], cc[3]); - glBindFramebuffer(GL_FRAMEBUFFER, fb); - glUseProgram(program); - for (int i = 0; i < 10; ++i) - { - glActiveTexture(GL_TEXTURE0 + i); - glBindTexture(GL_TEXTURE_2D, tex[i]); - glBindSampler(i, sampler[i]); - } - glActiveTexture(active_tex); - glBindTexture(GL_TEXTURE_CUBE_MAP, cube); - } + void save(); + void restore(); };